1 package org.bouncycastle.cert; 2 3 import java.math.BigInteger; 4 import java.util.Date; 5 import java.util.Locale; 6 7 import org.bouncycastle.asn1.ASN1Encodable; 8 import org.bouncycastle.asn1.ASN1Integer; 9 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 10 import org.bouncycastle.asn1.x500.X500Name; 11 import org.bouncycastle.asn1.x509.Certificate; 12 import org.bouncycastle.asn1.x509.Extension; 13 import org.bouncycastle.asn1.x509.ExtensionsGenerator; 14 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; 15 import org.bouncycastle.asn1.x509.Time; 16 import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; 17 import org.bouncycastle.operator.ContentSigner; 18 19 20 /** 21 * class to produce an X.509 Version 3 certificate. 22 */ 23 public class X509v3CertificateBuilder 24 { 25 private V3TBSCertificateGenerator tbsGen; 26 private ExtensionsGenerator extGenerator; 27 28 /** 29 * Create a builder for a version 3 certificate. 30 * 31 * @param issuer the certificate issuer 32 * @param serial the certificate serial number 33 * @param notBefore the date before which the certificate is not valid 34 * @param notAfter the date after which the certificate is not valid 35 * @param subject the certificate subject 36 * @param publicKeyInfo the info structure for the public key to be associated with this certificate. 37 */ X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo)38 public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) 39 { 40 this(issuer, serial, new Time(notBefore), new Time(notAfter), subject, publicKeyInfo); 41 } 42 43 /** 44 * Create a builder for a version 3 certificate. You may need to use this constructor if the default locale 45 * doesn't use a Gregorian calender so that the Time produced is compatible with other ASN.1 implementations. 46 * 47 * @param issuer the certificate issuer 48 * @param serial the certificate serial number 49 * @param notBefore the date before which the certificate is not valid 50 * @param notAfter the date after which the certificate is not valid 51 * @param dateLocale locale to be used for date interpretation. 52 * @param subject the certificate subject 53 * @param publicKeyInfo the info structure for the public key to be associated with this certificate. 54 */ X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, Locale dateLocale, X500Name subject, SubjectPublicKeyInfo publicKeyInfo)55 public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, Locale dateLocale, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) 56 { 57 this(issuer, serial, new Time(notBefore, dateLocale), new Time(notAfter, dateLocale), subject, publicKeyInfo); 58 } 59 60 /** 61 * Create a builder for a version 3 certificate. 62 * 63 * @param issuer the certificate issuer 64 * @param serial the certificate serial number 65 * @param notBefore the Time before which the certificate is not valid 66 * @param notAfter the Time after which the certificate is not valid 67 * @param subject the certificate subject 68 * @param publicKeyInfo the info structure for the public key to be associated with this certificate. 69 */ X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo)70 public X509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, SubjectPublicKeyInfo publicKeyInfo) 71 { 72 tbsGen = new V3TBSCertificateGenerator(); 73 tbsGen.setSerialNumber(new ASN1Integer(serial)); 74 tbsGen.setIssuer(issuer); 75 tbsGen.setStartDate(notBefore); 76 tbsGen.setEndDate(notAfter); 77 tbsGen.setSubject(subject); 78 tbsGen.setSubjectPublicKeyInfo(publicKeyInfo); 79 80 extGenerator = new ExtensionsGenerator(); 81 } 82 83 /** 84 * Set the subjectUniqueID - note: it is very rare that it is correct to do this. 85 * 86 * @param uniqueID a boolean array representing the bits making up the subjectUniqueID. 87 * @return this builder object. 88 */ setSubjectUniqueID(boolean[] uniqueID)89 public X509v3CertificateBuilder setSubjectUniqueID(boolean[] uniqueID) 90 { 91 tbsGen.setSubjectUniqueID(CertUtils.booleanToBitString(uniqueID)); 92 93 return this; 94 } 95 96 /** 97 * Set the issuerUniqueID - note: it is very rare that it is correct to do this. 98 * 99 * @param uniqueID a boolean array representing the bits making up the issuerUniqueID. 100 * @return this builder object. 101 */ setIssuerUniqueID(boolean[] uniqueID)102 public X509v3CertificateBuilder setIssuerUniqueID(boolean[] uniqueID) 103 { 104 tbsGen.setIssuerUniqueID(CertUtils.booleanToBitString(uniqueID)); 105 106 return this; 107 } 108 109 /** 110 * Add a given extension field for the standard extensions tag (tag 3) 111 * 112 * @param oid the OID defining the extension type. 113 * @param isCritical true if the extension is critical, false otherwise. 114 * @param value the ASN.1 structure that forms the extension's value. 115 * @return this builder object. 116 */ addExtension( ASN1ObjectIdentifier oid, boolean isCritical, ASN1Encodable value)117 public X509v3CertificateBuilder addExtension( 118 ASN1ObjectIdentifier oid, 119 boolean isCritical, 120 ASN1Encodable value) 121 throws CertIOException 122 { 123 CertUtils.addExtension(extGenerator, oid, isCritical, value); 124 125 return this; 126 } 127 128 /** 129 * Add a given extension field for the standard extensions tag (tag 3). 130 * 131 * @param extension the full extension value. 132 * @return this builder object. 133 */ addExtension( Extension extension)134 public X509v3CertificateBuilder addExtension( 135 Extension extension) 136 throws CertIOException 137 { 138 extGenerator.addExtension(extension); 139 140 return this; 141 } 142 143 /** 144 * Add a given extension field for the standard extensions tag (tag 3) using a byte encoding of the 145 * extension value. 146 * 147 * @param oid the OID defining the extension type. 148 * @param isCritical true if the extension is critical, false otherwise. 149 * @param encodedValue a byte array representing the encoding of the extension value. 150 * @return this builder object. 151 */ addExtension( ASN1ObjectIdentifier oid, boolean isCritical, byte[] encodedValue)152 public X509v3CertificateBuilder addExtension( 153 ASN1ObjectIdentifier oid, 154 boolean isCritical, 155 byte[] encodedValue) 156 throws CertIOException 157 { 158 extGenerator.addExtension(oid, isCritical, encodedValue); 159 160 return this; 161 } 162 163 /** 164 * Add a given extension field for the standard extensions tag (tag 3) 165 * copying the extension value from another certificate. 166 * 167 * @param oid the OID defining the extension type. 168 * @param isCritical true if the copied extension is to be marked as critical, false otherwise. 169 * @param certHolder the holder for the certificate that the extension is to be copied from. 170 * @return this builder object. 171 */ copyAndAddExtension( ASN1ObjectIdentifier oid, boolean isCritical, X509CertificateHolder certHolder)172 public X509v3CertificateBuilder copyAndAddExtension( 173 ASN1ObjectIdentifier oid, 174 boolean isCritical, 175 X509CertificateHolder certHolder) 176 { 177 Certificate cert = certHolder.toASN1Structure(); 178 179 Extension extension = cert.getTBSCertificate().getExtensions().getExtension(oid); 180 181 if (extension == null) 182 { 183 throw new NullPointerException("extension " + oid + " not present"); 184 } 185 186 extGenerator.addExtension(oid, isCritical, extension.getExtnValue().getOctets()); 187 188 return this; 189 } 190 191 /** 192 * Generate an X.509 certificate, based on the current issuer and subject 193 * using the passed in signer. 194 * 195 * @param signer the content signer to be used to generate the signature validating the certificate. 196 * @return a holder containing the resulting signed certificate. 197 */ build( ContentSigner signer)198 public X509CertificateHolder build( 199 ContentSigner signer) 200 { 201 tbsGen.setSignature(signer.getAlgorithmIdentifier()); 202 203 if (!extGenerator.isEmpty()) 204 { 205 tbsGen.setExtensions(extGenerator.generate()); 206 } 207 208 return CertUtils.generateFullCert(signer, tbsGen.generateTBSCertificate()); 209 } 210 }