1 package org.bouncycastle.cert.selector; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.asn1.ASN1OctetString; 6 import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; 7 import org.bouncycastle.asn1.x500.X500Name; 8 import org.bouncycastle.asn1.x509.Extension; 9 import org.bouncycastle.cert.X509CertificateHolder; 10 import org.bouncycastle.util.Arrays; 11 import org.bouncycastle.util.Selector; 12 13 /** 14 * a basic index for a X509CertificateHolder class 15 */ 16 public class X509CertificateHolderSelector 17 implements Selector 18 { 19 private byte[] subjectKeyId; 20 21 private X500Name issuer; 22 private BigInteger serialNumber; 23 24 /** 25 * Construct a selector with the value of a public key's subjectKeyId. 26 * 27 * @param subjectKeyId a subjectKeyId 28 */ 29 public X509CertificateHolderSelector(byte[] subjectKeyId) 30 { 31 this(null, null, subjectKeyId); 32 } 33 34 /** 35 * Construct a signer ID based on the issuer and serial number of the signer's associated 36 * certificate. 37 * 38 * @param issuer the issuer of the signer's associated certificate. 39 * @param serialNumber the serial number of the signer's associated certificate. 40 */ 41 public X509CertificateHolderSelector(X500Name issuer, BigInteger serialNumber) 42 { 43 this(issuer, serialNumber, null); 44 } 45 46 /** 47 * Construct a signer ID based on the issuer and serial number of the signer's associated 48 * certificate. 49 * 50 * @param issuer the issuer of the signer's associated certificate. 51 * @param serialNumber the serial number of the signer's associated certificate. 52 * @param subjectKeyId the subject key identifier to use to match the signers associated certificate. 53 */ 54 public X509CertificateHolderSelector(X500Name issuer, BigInteger serialNumber, byte[] subjectKeyId) 55 { 56 this.issuer = issuer; 57 this.serialNumber = serialNumber; 58 this.subjectKeyId = subjectKeyId; 59 } 60 61 public X500Name getIssuer() 62 { 63 return issuer; 64 } 65 66 public BigInteger getSerialNumber() 67 { 68 return serialNumber; 69 } 70 71 public byte[] getSubjectKeyIdentifier() 72 { 73 return Arrays.clone(subjectKeyId); 74 } 75 76 public int hashCode() 77 { 78 int code = Arrays.hashCode(subjectKeyId); 79 80 if (this.serialNumber != null) 81 { 82 code ^= this.serialNumber.hashCode(); 83 } 84 85 if (this.issuer != null) 86 { 87 code ^= this.issuer.hashCode(); 88 } 89 90 return code; 91 } 92 93 public boolean equals( 94 Object o) 95 { 96 if (!(o instanceof X509CertificateHolderSelector)) 97 { 98 return false; 99 } 100 101 X509CertificateHolderSelector id = (X509CertificateHolderSelector)o; 102 103 return Arrays.areEqual(subjectKeyId, id.subjectKeyId) 104 && equalsObj(this.serialNumber, id.serialNumber) 105 && equalsObj(this.issuer, id.issuer); 106 } 107 108 private boolean equalsObj(Object a, Object b) 109 { 110 return (a != null) ? a.equals(b) : b == null; 111 } 112 113 public boolean match(Object obj) 114 { 115 if (obj instanceof X509CertificateHolder) 116 { 117 X509CertificateHolder certHldr = (X509CertificateHolder)obj; 118 119 if (this.getSerialNumber() != null) 120 { 121 IssuerAndSerialNumber iAndS = new IssuerAndSerialNumber(certHldr.toASN1Structure()); 122 123 return iAndS.getName().equals(this.issuer) 124 && iAndS.getSerialNumber().getValue().equals(this.serialNumber); 125 } 126 else if (subjectKeyId != null) 127 { 128 Extension ext = certHldr.getExtension(Extension.subjectKeyIdentifier); 129 130 if (ext == null) 131 { 132 return Arrays.areEqual(subjectKeyId, MSOutlookKeyIdCalculator.calculateKeyId(certHldr.getSubjectPublicKeyInfo())); 133 } 134 135 byte[] subKeyID = ASN1OctetString.getInstance(ext.getParsedValue()).getOctets(); 136 137 return Arrays.areEqual(subjectKeyId, subKeyID); 138 } 139 } 140 else if (obj instanceof byte[]) 141 { 142 return Arrays.areEqual(subjectKeyId, (byte[])obj); 143 } 144 145 return false; 146 } 147 148 public Object clone() 149 { 150 return new X509CertificateHolderSelector(this.issuer, this.serialNumber, this.subjectKeyId); 151 } 152 } 153