1 package org.bouncycastle.x509;
2 
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.math.BigInteger;
6 import java.security.GeneralSecurityException;
7 import java.security.InvalidKeyException;
8 import java.security.NoSuchAlgorithmException;
9 import java.security.NoSuchProviderException;
10 import java.security.PrivateKey;
11 import java.security.PublicKey;
12 import java.security.SecureRandom;
13 import java.security.SignatureException;
14 import java.security.cert.CertificateEncodingException;
15 import java.security.cert.X509Certificate;
16 import java.util.Date;
17 import java.util.Iterator;
18 
19 import javax.security.auth.x500.X500Principal;
20 
21 import org.bouncycastle.asn1.ASN1EncodableVector;
22 import org.bouncycastle.asn1.ASN1Encoding;
23 import org.bouncycastle.asn1.ASN1Integer;
24 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
25 import org.bouncycastle.asn1.DERBitString;
26 import org.bouncycastle.asn1.DERSequence;
27 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
28 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
29 import org.bouncycastle.asn1.x509.TBSCertificate;
30 import org.bouncycastle.asn1.x509.Time;
31 import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator;
32 import org.bouncycastle.asn1.x509.X509Name;
33 import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
34 import org.bouncycastle.jcajce.util.BCJcaJceHelper;
35 import org.bouncycastle.jcajce.util.JcaJceHelper;
36 import org.bouncycastle.jce.X509Principal;
37 
38 /**
39  * class to produce an X.509 Version 1 certificate.
40  * @deprecated use org.bouncycastle.cert.X509v1CertificateBuilder.
41  */
42 public class X509V1CertificateGenerator
43 {
44     private final JcaJceHelper bcHelper = new BCJcaJceHelper(); // needed to force provider loading
45     private final CertificateFactory certificateFactory = new CertificateFactory();
46 
47     private V1TBSCertificateGenerator   tbsGen;
48     private ASN1ObjectIdentifier         sigOID;
49     private AlgorithmIdentifier         sigAlgId;
50     private String                      signatureAlgorithm;
51 
X509V1CertificateGenerator()52     public X509V1CertificateGenerator()
53     {
54         tbsGen = new V1TBSCertificateGenerator();
55     }
56 
57     /**
58      * reset the generator
59      */
reset()60     public void reset()
61     {
62         tbsGen = new V1TBSCertificateGenerator();
63     }
64 
65     /**
66      * set the serial number for the certificate.
67      */
setSerialNumber( BigInteger serialNumber)68     public void setSerialNumber(
69         BigInteger      serialNumber)
70     {
71         if (serialNumber.compareTo(BigInteger.ZERO) <= 0)
72         {
73             throw new IllegalArgumentException("serial number must be a positive integer");
74         }
75 
76         tbsGen.setSerialNumber(new ASN1Integer(serialNumber));
77     }
78 
79     /**
80      * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
81      * certificate.
82      */
setIssuerDN( X500Principal issuer)83     public void setIssuerDN(
84         X500Principal   issuer)
85     {
86         try
87         {
88             tbsGen.setIssuer(new X509Principal(issuer.getEncoded()));
89         }
90         catch (IOException e)
91         {
92             throw new IllegalArgumentException("can't process principal: " + e);
93         }
94     }
95 
96     /**
97      * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
98      * certificate.
99      */
setIssuerDN( X509Name issuer)100     public void setIssuerDN(
101         X509Name   issuer)
102     {
103         tbsGen.setIssuer(issuer);
104     }
105 
setNotBefore( Date date)106     public void setNotBefore(
107         Date    date)
108     {
109         tbsGen.setStartDate(new Time(date));
110     }
111 
setNotAfter( Date date)112     public void setNotAfter(
113         Date    date)
114     {
115         tbsGen.setEndDate(new Time(date));
116     }
117 
118     /**
119      * Set the subject distinguished name. The subject describes the entity associated with the public key.
120      */
setSubjectDN( X500Principal subject)121     public void setSubjectDN(
122         X500Principal   subject)
123     {
124         try
125         {
126             tbsGen.setSubject(new X509Principal(subject.getEncoded()));
127         }
128         catch (IOException e)
129         {
130             throw new IllegalArgumentException("can't process principal: " + e);
131         }
132     }
133 
134     /**
135      * Set the subject distinguished name. The subject describes the entity associated with the public key.
136      */
setSubjectDN( X509Name subject)137     public void setSubjectDN(
138         X509Name   subject)
139     {
140         tbsGen.setSubject(subject);
141     }
142 
setPublicKey( PublicKey key)143     public void setPublicKey(
144         PublicKey       key)
145     {
146         try
147         {
148             tbsGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(key.getEncoded()));
149         }
150         catch (Exception e)
151         {
152             throw new IllegalArgumentException("unable to process key - " + e.toString());
153         }
154     }
155 
156     /**
157      * Set the signature algorithm. This can be either a name or an OID, names
158      * are treated as case insensitive.
159      *
160      * @param signatureAlgorithm string representation of the algorithm name.
161      */
setSignatureAlgorithm( String signatureAlgorithm)162     public void setSignatureAlgorithm(
163         String  signatureAlgorithm)
164     {
165         this.signatureAlgorithm = signatureAlgorithm;
166 
167         try
168         {
169             sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
170         }
171         catch (Exception e)
172         {
173             throw new IllegalArgumentException("Unknown signature type requested");
174         }
175 
176         sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
177 
178         tbsGen.setSignature(sigAlgId);
179     }
180 
181     /**
182      * generate an X509 certificate, based on the current issuer and subject
183      * using the default provider "BC".
184      * @deprecated use generate(key, "BC")
185      */
generateX509Certificate( PrivateKey key)186     public X509Certificate generateX509Certificate(
187         PrivateKey      key)
188         throws SecurityException, SignatureException, InvalidKeyException
189     {
190         try
191         {
192             return generateX509Certificate(key, "BC", null);
193         }
194         catch (NoSuchProviderException e)
195         {
196             throw new SecurityException("BC provider not installed!");
197         }
198     }
199 
200     /**
201      * generate an X509 certificate, based on the current issuer and subject
202      * using the default provider "BC" and the passed in source of randomness
203      * @deprecated use generate(key, random, "BC")
204      */
generateX509Certificate( PrivateKey key, SecureRandom random)205     public X509Certificate generateX509Certificate(
206         PrivateKey      key,
207         SecureRandom    random)
208         throws SecurityException, SignatureException, InvalidKeyException
209     {
210         try
211         {
212             return generateX509Certificate(key, "BC", random);
213         }
214         catch (NoSuchProviderException e)
215         {
216             throw new SecurityException("BC provider not installed!");
217         }
218     }
219 
220     /**
221      * generate an X509 certificate, based on the current issuer and subject,
222      * using the passed in provider for the signing, and the passed in source
223      * of randomness (if required).
224      * @deprecated use generate()
225      */
generateX509Certificate( PrivateKey key, String provider)226     public X509Certificate generateX509Certificate(
227         PrivateKey      key,
228         String          provider)
229         throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
230     {
231         return generateX509Certificate(key, provider, null);
232     }
233 
234     /**
235      * generate an X509 certificate, based on the current issuer and subject,
236      * using the passed in provider for the signing, and the passed in source
237      * of randomness (if required).
238      * @deprecated use generate()
239      */
generateX509Certificate( PrivateKey key, String provider, SecureRandom random)240     public X509Certificate generateX509Certificate(
241         PrivateKey      key,
242         String          provider,
243         SecureRandom    random)
244         throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
245     {
246         try
247         {
248             return generate(key, provider, random);
249         }
250         catch (NoSuchProviderException e)
251         {
252             throw e;
253         }
254         catch (SignatureException e)
255         {
256             throw e;
257         }
258         catch (InvalidKeyException e)
259         {
260             throw e;
261         }
262         catch (GeneralSecurityException e)
263         {
264             throw new SecurityException("exception: " + e);
265         }
266     }
267 
268     /**
269      * generate an X509 certificate, based on the current issuer and subject
270      * using the default provider.
271      * <p>
272      * <b>Note:</b> this differs from the deprecated method in that the default provider is
273      * used - not "BC".
274      * </p>
275      */
generate( PrivateKey key)276     public X509Certificate generate(
277         PrivateKey      key)
278         throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
279     {
280         return generate(key, (SecureRandom)null);
281     }
282 
283     /**
284      * generate an X509 certificate, based on the current issuer and subject
285      * using the default provider and the passed in source of randomness
286      * <p>
287      * <b>Note:</b> this differs from the deprecated method in that the default provider is
288      * used - not "BC".
289      * </p>
290      */
generate( PrivateKey key, SecureRandom random)291     public X509Certificate generate(
292         PrivateKey      key,
293         SecureRandom    random)
294         throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
295     {
296         TBSCertificate tbsCert = tbsGen.generateTBSCertificate();
297         byte[] signature;
298 
299         try
300         {
301             signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert);
302         }
303         catch (IOException e)
304         {
305             throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
306         }
307 
308         return generateJcaObject(tbsCert, signature);
309     }
310 
311     /**
312      * generate an X509 certificate, based on the current issuer and subject,
313      * using the passed in provider for the signing, and the passed in source
314      * of randomness (if required).
315      */
generate( PrivateKey key, String provider)316     public X509Certificate generate(
317         PrivateKey      key,
318         String          provider)
319         throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
320     {
321         return generate(key, provider, null);
322     }
323 
324     /**
325      * generate an X509 certificate, based on the current issuer and subject,
326      * using the passed in provider for the signing, and the passed in source
327      * of randomness (if required).
328      */
generate( PrivateKey key, String provider, SecureRandom random)329     public X509Certificate generate(
330         PrivateKey      key,
331         String          provider,
332         SecureRandom    random)
333         throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
334     {
335         TBSCertificate tbsCert = tbsGen.generateTBSCertificate();
336         byte[] signature;
337 
338         try
339         {
340             signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert);
341         }
342         catch (IOException e)
343         {
344             throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
345         }
346 
347         return generateJcaObject(tbsCert, signature);
348     }
349 
generateJcaObject(TBSCertificate tbsCert, byte[] signature)350     private X509Certificate generateJcaObject(TBSCertificate tbsCert, byte[] signature)
351         throws CertificateEncodingException
352     {
353         ASN1EncodableVector v = new ASN1EncodableVector();
354 
355         v.add(tbsCert);
356         v.add(sigAlgId);
357         v.add(new DERBitString(signature));
358 
359         try
360         {
361             return (X509Certificate)certificateFactory.engineGenerateCertificate(
362                 new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER)));
363         }
364         catch (Exception e)
365         {
366             throw new ExtCertificateEncodingException("exception producing certificate object", e);
367         }
368     }
369 
370     /**
371      * Return an iterator of the signature names supported by the generator.
372      *
373      * @return an iterator containing recognised names.
374      */
getSignatureAlgNames()375     public Iterator getSignatureAlgNames()
376     {
377         return X509Util.getAlgNames();
378     }
379 }
380