项目原来设计只要求读取CRL中吊销列表的序列号和吊销日期,所以并未考虑排序的问题,但是后来又要求按照吊销日期进行排序。
下面是原来的程序,显示出来的吊销列表顺序是乱的,和证书上的顺序不一致。
CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509CRL crl = (X509CRL)cf.generateCRL(new FileInputStream("c:\\1.crl")); //读取版本号 int version = crl.getVersion(); //读取颁发者DN String issuerDN = crl.getIssuerDN().toString(); //读取生效日期 Date startTime = crl.getThisUpdate(); //读取下一次更新日期 Date nextUpdateTime = crl.getNextUpdate(); //读取吊销列表 Set tSet = crl.getRevokedCertificates(); Iterator tIterator = tSet.iterator(); while(tIterator.hasNext()){ X509CRLEntry tEntry = (X509CRLEntry) tIterator.next(); //读取序列号 String sn = getSerialNumber(tEntry); //读取吊销日期 String time = tEntry.getRevocationDate().toLocaleString(); }
根据吊销列表中的每个对象获得序列号的字符串值,entry.getSeriaNumber()读取出来是BigInteger,可读性不好也不直观,所以下面的方法将其转换成字符串,并且和证书上显示的序列号相同。
public static String getSerialNumber(X509CRLEntry entry){ if(entry != null){ byte[] serial = entry.getSerialNumber().toByteArray(); if(serial.length>0){ String serialNumberString = new String(); for(int i=0;i<serial.length;i++){ String s =Integer.toHexString(Byte.valueOf(serial[i]).intValue()); if(s.length()==8){ s = s.substring(6); }else if(1==s.length()){ s="0"+s; } serialNumberString+=s+" "; } return serialNumberString; } } return null; }
现在要对集合进行排序,需要实现Comparator类的compare方法,当吊销日期相同时按照序列号自然排序。
注意:排序方法很重要,如果只比较吊销日期,不做compare==0判断的话,使用第一种方法即TreeSet,最后输出结果可能有误,会导致丢失吊销证书信息的情况。因为TreeSet基于Set接口,虽然可以排序,但是仍然不允许元素重复。第二种方法即List接口允许元素重复,所以不会出现这种情况。
public class CRLDateComparator implements Comparator { public int compare(Object o1, Object o2){ X509CRLEntry entry1 = (X509CRLEntry)o1; X509CRLEntry entry2 = (X509CRLEntry)o2; int compare = entry1.getRevocationDate().compareTo(entry2.getRevocationDate()); if(compare == 0){ String sn1 = getSerialNumber(entry1); String sn2 = getSerialNumber(entry2); compare = sn1.compareTo(sn2); } return compare; }
实现方法有2种:TreeSet和List。
第一种 TreeSet
Set tSet = crl.getRevokedCertificates(); //----------加入代码开始---------- TreeSet ts = new TreeSet(new CRLDateComparator()); ts.addAll(set); //----------加入代码结束---------- Iterator tIterator = ts.iterator();
第二种 List
Set tSet = crl.getRevokedCertificates(); //----------加入代码开始---------- List l = new ArrayList(); l.addAll(set); Collections.sort(l, new CRLDateComparator()); //----------加入代码结束---------- Iterator tIterator = l.iterator();
以上两种方法经过测试,都可以满足要求。