1 package org.bouncycastle.cert.ocsp; 2 3 import java.io.OutputStream; 4 import java.math.BigInteger; 5 6 import org.bouncycastle.asn1.ASN1Encoding; 7 import org.bouncycastle.asn1.ASN1Integer; 8 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 9 import org.bouncycastle.asn1.ASN1OctetString; 10 import org.bouncycastle.asn1.DERNull; 11 import org.bouncycastle.asn1.DEROctetString; 12 import org.bouncycastle.asn1.ocsp.CertID; 13 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 14 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 15 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 16 import org.bouncycastle.cert.X509CertificateHolder; 17 import org.bouncycastle.operator.DigestCalculator; 18 import org.bouncycastle.operator.DigestCalculatorProvider; 19 import org.bouncycastle.operator.OperatorCreationException; 20 21 public class CertificateID 22 { 23 public static final AlgorithmIdentifier HASH_SHA1 = new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1, DERNull.INSTANCE); 24 25 private final CertID id; 26 27 public CertificateID( 28 CertID id) 29 { 30 if (id == null) 31 { 32 throw new IllegalArgumentException("'id' cannot be null"); 33 } 34 this.id = id; 35 } 36 37 /** 38 * create from an issuer certificate and the serial number of the 39 * certificate it signed. 40 * 41 * @param issuerCert issuing certificate 42 * @param number serial number 43 * 44 * @exception OCSPException if any problems occur creating the id fields. 45 */ 46 public CertificateID( 47 DigestCalculator digestCalculator, X509CertificateHolder issuerCert, 48 BigInteger number) 49 throws OCSPException 50 { 51 this.id = createCertID(digestCalculator, issuerCert, new ASN1Integer(number)); 52 } 53 54 public ASN1ObjectIdentifier getHashAlgOID() 55 { 56 return id.getHashAlgorithm().getAlgorithm(); 57 } 58 59 public byte[] getIssuerNameHash() 60 { 61 return id.getIssuerNameHash().getOctets(); 62 } 63 64 public byte[] getIssuerKeyHash() 65 { 66 return id.getIssuerKeyHash().getOctets(); 67 } 68 69 /** 70 * return the serial number for the certificate associated 71 * with this request. 72 */ 73 public BigInteger getSerialNumber() 74 { 75 return id.getSerialNumber().getValue(); 76 } 77 78 public boolean matchesIssuer(X509CertificateHolder issuerCert, DigestCalculatorProvider digCalcProvider) 79 throws OCSPException 80 { 81 try 82 { 83 return createCertID(digCalcProvider.get(id.getHashAlgorithm()), issuerCert, id.getSerialNumber()).equals(id); 84 } 85 catch (OperatorCreationException e) 86 { 87 throw new OCSPException("unable to create digest calculator: " + e.getMessage(), e); 88 } 89 } 90 91 public CertID toASN1Primitive() 92 { 93 return id; 94 } 95 96 public boolean equals( 97 Object o) 98 { 99 if (!(o instanceof CertificateID)) 100 { 101 return false; 102 } 103 104 CertificateID obj = (CertificateID)o; 105 106 return id.toASN1Primitive().equals(obj.id.toASN1Primitive()); 107 } 108 109 public int hashCode() 110 { 111 return id.toASN1Primitive().hashCode(); 112 } 113 114 /** 115 * Create a new CertificateID for a new serial number derived from a previous one 116 * calculated for the same CA certificate. 117 * 118 * @param original the previously calculated CertificateID for the CA. 119 * @param newSerialNumber the serial number for the new certificate of interest. 120 * 121 * @return a new CertificateID for newSerialNumber 122 */ 123 public static CertificateID deriveCertificateID(CertificateID original, BigInteger newSerialNumber) 124 { 125 return new CertificateID(new CertID(original.id.getHashAlgorithm(), original.id.getIssuerNameHash(), original.id.getIssuerKeyHash(), new ASN1Integer(newSerialNumber))); 126 } 127 128 private static CertID createCertID(DigestCalculator digCalc, X509CertificateHolder issuerCert, ASN1Integer serialNumber) 129 throws OCSPException 130 { 131 try 132 { 133 OutputStream dgOut = digCalc.getOutputStream(); 134 135 dgOut.write(issuerCert.toASN1Structure().getSubject().getEncoded(ASN1Encoding.DER)); 136 dgOut.close(); 137 138 ASN1OctetString issuerNameHash = new DEROctetString(digCalc.getDigest()); 139 140 SubjectPublicKeyInfo info = issuerCert.getSubjectPublicKeyInfo(); 141 142 dgOut = digCalc.getOutputStream(); 143 144 dgOut.write(info.getPublicKeyData().getBytes()); 145 dgOut.close(); 146 147 ASN1OctetString issuerKeyHash = new DEROctetString(digCalc.getDigest()); 148 149 return new CertID(digCalc.getAlgorithmIdentifier(), issuerNameHash, issuerKeyHash, serialNumber); 150 } 151 catch (Exception e) 152 { 153 throw new OCSPException("problem creating ID: " + e, e); 154 } 155 } 156 } 157