1
package org.bouncycastle.x509;
3
import org.bouncycastle.asn1.ASN1Encodable;
4
import org.bouncycastle.asn1.ASN1EncodableVector;
5
import org.bouncycastle.asn1.ASN1InputStream;
6
import org.bouncycastle.asn1.DERBitString;
7
import org.bouncycastle.asn1.DEREncodable;
8
import org.bouncycastle.asn1.DERInteger;
9
import org.bouncycastle.asn1.DERObjectIdentifier;
10
import org.bouncycastle.asn1.DERSequence;
11
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
12
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
13
import org.bouncycastle.asn1.x509.TBSCertificateStructure;
14
import org.bouncycastle.asn1.x509.Time;
15
import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
16
import org.bouncycastle.asn1.x509.X509CertificateStructure;
17
import org.bouncycastle.asn1.x509.X509ExtensionsGenerator;
18
import org.bouncycastle.asn1.x509.X509Name;
19
import org.bouncycastle.jce.X509Principal;
20
import org.bouncycastle.jce.provider.X509CertificateObject;
21
import org.bouncycastle.x509.extension.X509ExtensionUtil;
23
import java.io.IOException;
24
import java.math.BigInteger;
25
import java.security.GeneralSecurityException;
26
import java.security.InvalidKeyException;
27
import java.security.NoSuchAlgorithmException;
28
import java.security.NoSuchProviderException;
29
import java.security.PrivateKey;
30
import java.security.PublicKey;
31
import java.security.SecureRandom;
32
import java.security.SignatureException;
33
import java.security.cert.CertificateEncodingException;
34
import java.security.cert.CertificateParsingException;
35
import java.security.cert.X509Certificate;
36
import java.util.Date;
37
import java.util.Iterator;
40
* class to produce an X.509 Version 3 certificate.
42
public class X509V3CertificateGenerator
44
private V3TBSCertificateGenerator tbsGen;
45
private DERObjectIdentifier sigOID;
46
private AlgorithmIdentifier sigAlgId;
47
private String signatureAlgorithm;
48
private X509ExtensionsGenerator extGenerator;
50
public X509V3CertificateGenerator()
52
tbsGen = new V3TBSCertificateGenerator();
53
extGenerator = new X509ExtensionsGenerator();
61
tbsGen = new V3TBSCertificateGenerator();
66
* set the serial number for the certificate.
68
public void setSerialNumber(
69
BigInteger serialNumber)
71
if (serialNumber.compareTo(BigInteger.ZERO) <= 0)
73
throw new IllegalArgumentException("serial number must be a positive integer");
76
tbsGen.setSerialNumber(new DERInteger(serialNumber));
80
* Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
83
public void setIssuerDN(
86
tbsGen.setIssuer(issuer);
89
public void setNotBefore(
92
tbsGen.setStartDate(new Time(date));
95
public void setNotAfter(
98
tbsGen.setEndDate(new Time(date));
102
* Set the subject distinguished name. The subject describes the entity associated with the public key.
104
public void setSubjectDN(
107
tbsGen.setSubject(subject);
110
public void setPublicKey(
112
throws IllegalArgumentException
116
tbsGen.setSubjectPublicKeyInfo(
117
SubjectPublicKeyInfo.getInstance(new ASN1InputStream(key.getEncoded()).readObject()));
121
throw new IllegalArgumentException("unable to process key - " + e.toString());
126
* Set the signature algorithm. This can be either a name or an OID, names
127
* are treated as case insensitive.
129
* @param signatureAlgorithm string representation of the algorithm name.
131
public void setSignatureAlgorithm(
132
String signatureAlgorithm)
134
this.signatureAlgorithm = signatureAlgorithm;
138
sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
142
throw new IllegalArgumentException("Unknown signature type requested: " + signatureAlgorithm);
145
sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
147
tbsGen.setSignature(sigAlgId);
151
* Set the subject unique ID - note: it is very rare that it is correct to do this.
153
public void setSubjectUniqueID(boolean[] uniqueID)
155
tbsGen.setSubjectUniqueID(booleanToBitString(uniqueID));
159
* Set the issuer unique ID - note: it is very rare that it is correct to do this.
161
public void setIssuerUniqueID(boolean[] uniqueID)
163
tbsGen.setIssuerUniqueID(booleanToBitString(uniqueID));
166
private DERBitString booleanToBitString(boolean[] id)
168
byte[] bytes = new byte[(id.length + 7) / 8];
170
for (int i = 0; i != id.length; i++)
172
bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0;
175
int pad = id.length % 8;
179
return new DERBitString(bytes);
183
return new DERBitString(bytes, 8 - pad);
188
* add a given extension field for the standard extensions tag (tag 3)
190
public void addExtension(
195
this.addExtension(new DERObjectIdentifier(oid), critical, value);
199
* add a given extension field for the standard extensions tag (tag 3)
201
public void addExtension(
202
DERObjectIdentifier oid,
206
extGenerator.addExtension(oid, critical, value);
210
* add a given extension field for the standard extensions tag (tag 3)
211
* The value parameter becomes the contents of the octet string associated
212
* with the extension.
214
public void addExtension(
219
this.addExtension(new DERObjectIdentifier(oid), critical, value);
223
* add a given extension field for the standard extensions tag (tag 3)
225
public void addExtension(
226
DERObjectIdentifier oid,
230
extGenerator.addExtension(oid, critical, value);
234
* add a given extension field for the standard extensions tag (tag 3)
235
* copying the extension value from another certificate.
236
* @throws CertificateParsingException if the extension cannot be extracted.
238
public void copyAndAddExtension(
241
X509Certificate cert)
242
throws CertificateParsingException
244
byte[] extValue = cert.getExtensionValue(oid);
246
if (extValue == null)
248
throw new CertificateParsingException("extension " + oid + " not present");
253
ASN1Encodable value = X509ExtensionUtil.fromExtensionValue(extValue);
255
this.addExtension(oid, critical, value);
257
catch (IOException e)
259
throw new CertificateParsingException(e.toString());
264
* add a given extension field for the standard extensions tag (tag 3)
265
* copying the extension value from another certificate.
266
* @throws CertificateParsingException if the extension cannot be extracted.
268
public void copyAndAddExtension(
269
DERObjectIdentifier oid,
271
X509Certificate cert)
272
throws CertificateParsingException
274
this.copyAndAddExtension(oid.getId(), critical, cert);
278
* generate an X509 certificate, based on the current issuer and subject
279
* using the default provider "BC".
280
* @deprecated use generate(key, "BC")
282
public X509Certificate generateX509Certificate(
284
throws SecurityException, SignatureException, InvalidKeyException
288
return generateX509Certificate(key, "BC", null);
290
catch (NoSuchProviderException e)
292
throw new SecurityException("BC provider not installed!");
297
* generate an X509 certificate, based on the current issuer and subject
298
* using the default provider "BC", and the passed in source of randomness
300
* @deprecated use generate(key, random, "BC")
302
public X509Certificate generateX509Certificate(
305
throws SecurityException, SignatureException, InvalidKeyException
309
return generateX509Certificate(key, "BC", random);
311
catch (NoSuchProviderException e)
313
throw new SecurityException("BC provider not installed!");
318
* generate an X509 certificate, based on the current issuer and subject,
319
* using the passed in provider for the signing.
320
* @deprecated use generate()
322
public X509Certificate generateX509Certificate(
325
throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
327
return generateX509Certificate(key, provider, null);
331
* generate an X509 certificate, based on the current issuer and subject,
332
* using the passed in provider for the signing and the supplied source
333
* of randomness, if required.
334
* @deprecated use generate()
336
public X509Certificate generateX509Certificate(
340
throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
344
return generate(key, provider, random);
346
catch (NoSuchProviderException e)
350
catch (SignatureException e)
354
catch (InvalidKeyException e)
358
catch (GeneralSecurityException e)
360
throw new SecurityException("exception: " + e);
365
* generate an X509 certificate, based on the current issuer and subject
366
* using the default provider.
368
* <b>Note:</b> this differs from the deprecated method in that the default provider is
372
public X509Certificate generate(
374
throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
376
return generate(key, (SecureRandom)null);
380
* generate an X509 certificate, based on the current issuer and subject
381
* using the default provider, and the passed in source of randomness
384
* <b>Note:</b> this differs from the deprecated method in that the default provider is
388
public X509Certificate generate(
391
throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
393
TBSCertificateStructure tbsCert = generateTbsCert();
398
signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert);
400
catch (IOException e)
402
throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
407
return generateJcaObject(tbsCert, signature);
409
catch (CertificateParsingException e)
411
throw new ExtCertificateEncodingException("exception producing certificate object", e);
416
* generate an X509 certificate, based on the current issuer and subject,
417
* using the passed in provider for the signing.
419
public X509Certificate generate(
422
throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
424
return generate(key, provider, null);
428
* generate an X509 certificate, based on the current issuer and subject,
429
* using the passed in provider for the signing and the supplied source
430
* of randomness, if required.
432
public X509Certificate generate(
436
throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
438
TBSCertificateStructure tbsCert = generateTbsCert();
443
signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert);
445
catch (IOException e)
447
throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
452
return generateJcaObject(tbsCert, signature);
454
catch (CertificateParsingException e)
456
throw new ExtCertificateEncodingException("exception producing certificate object", e);
460
private TBSCertificateStructure generateTbsCert()
462
if (!extGenerator.isEmpty())
464
tbsGen.setExtensions(extGenerator.generate());
467
return tbsGen.generateTBSCertificate();
470
private X509Certificate generateJcaObject(TBSCertificateStructure tbsCert, byte[] signature)
471
throws CertificateParsingException
473
ASN1EncodableVector v = new ASN1EncodableVector();
477
v.add(new DERBitString(signature));
479
return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
483
* Return an iterator of the signature names supported by the generator.
485
* @return an iterator containing recognised names.
487
public Iterator getSignatureAlgNames()
489
return X509Util.getAlgNames();