~brian-thomason/+junk/bouncycastle

« back to all changes in this revision

Viewing changes to jdk1.3/org/bouncycastle/x509/X509V3CertificateGenerator.java

  • Committer: Brian Thomason
  • Date: 2011-12-20 17:20:32 UTC
  • Revision ID: brian.thomason@canonical.com-20111220172032-rdtm13jgdxtksacr
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.bouncycastle.x509;
 
2
 
 
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;
 
22
 
 
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;
 
38
 
 
39
/**
 
40
 * class to produce an X.509 Version 3 certificate.
 
41
 */
 
42
public class X509V3CertificateGenerator
 
43
{
 
44
    private V3TBSCertificateGenerator   tbsGen;
 
45
    private DERObjectIdentifier         sigOID;
 
46
    private AlgorithmIdentifier         sigAlgId;
 
47
    private String                      signatureAlgorithm;
 
48
    private X509ExtensionsGenerator     extGenerator;
 
49
 
 
50
    public X509V3CertificateGenerator()
 
51
    {
 
52
        tbsGen = new V3TBSCertificateGenerator();
 
53
        extGenerator = new X509ExtensionsGenerator();
 
54
    }
 
55
 
 
56
    /**
 
57
     * reset the generator
 
58
     */
 
59
    public void reset()
 
60
    {
 
61
        tbsGen = new V3TBSCertificateGenerator();
 
62
        extGenerator.reset();
 
63
    }
 
64
 
 
65
    /**
 
66
     * set the serial number for the certificate.
 
67
     */
 
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 DERInteger(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
     */
 
83
    public void setIssuerDN(
 
84
        X509Name   issuer)
 
85
    {
 
86
        tbsGen.setIssuer(issuer);
 
87
    }
 
88
 
 
89
    public void setNotBefore(
 
90
        Date    date)
 
91
    {
 
92
        tbsGen.setStartDate(new Time(date));
 
93
    }
 
94
 
 
95
    public void setNotAfter(
 
96
        Date    date)
 
97
    {
 
98
        tbsGen.setEndDate(new Time(date));
 
99
    }
 
100
 
 
101
    /**
 
102
     * Set the subject distinguished name. The subject describes the entity associated with the public key.
 
103
     */
 
104
    public void setSubjectDN(
 
105
        X509Name   subject)
 
106
    {
 
107
        tbsGen.setSubject(subject);
 
108
    }
 
109
 
 
110
    public void setPublicKey(
 
111
        PublicKey       key)
 
112
        throws IllegalArgumentException
 
113
    {
 
114
        try
 
115
        {
 
116
            tbsGen.setSubjectPublicKeyInfo(
 
117
                       SubjectPublicKeyInfo.getInstance(new ASN1InputStream(key.getEncoded()).readObject()));
 
118
        }
 
119
        catch (Exception e)
 
120
        {
 
121
            throw new IllegalArgumentException("unable to process key - " + e.toString());
 
122
        }
 
123
    }
 
124
 
 
125
    /**
 
126
     * Set the signature algorithm. This can be either a name or an OID, names
 
127
     * are treated as case insensitive.
 
128
     * 
 
129
     * @param signatureAlgorithm string representation of the algorithm name.
 
130
     */
 
131
    public void setSignatureAlgorithm(
 
132
        String  signatureAlgorithm)
 
133
    {
 
134
        this.signatureAlgorithm = signatureAlgorithm;
 
135
 
 
136
        try
 
137
        {
 
138
            sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
 
139
        }
 
140
        catch (Exception e)
 
141
        {
 
142
            throw new IllegalArgumentException("Unknown signature type requested: " + signatureAlgorithm);
 
143
        }
 
144
 
 
145
        sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
 
146
 
 
147
        tbsGen.setSignature(sigAlgId);
 
148
    }
 
149
 
 
150
    /**
 
151
     * Set the subject unique ID - note: it is very rare that it is correct to do this.
 
152
     */
 
153
    public void setSubjectUniqueID(boolean[] uniqueID)
 
154
    {
 
155
        tbsGen.setSubjectUniqueID(booleanToBitString(uniqueID));
 
156
    }
 
157
 
 
158
    /**
 
159
     * Set the issuer unique ID - note: it is very rare that it is correct to do this.
 
160
     */
 
161
    public void setIssuerUniqueID(boolean[] uniqueID)
 
162
    {
 
163
        tbsGen.setIssuerUniqueID(booleanToBitString(uniqueID));
 
164
    }
 
165
 
 
166
    private DERBitString booleanToBitString(boolean[] id)
 
167
    {
 
168
        byte[] bytes = new byte[(id.length + 7) / 8];
 
169
 
 
170
        for (int i = 0; i != id.length; i++)
 
171
        {
 
172
            bytes[i / 8] |= (id[i]) ? (1 << ((7 - (i % 8)))) : 0;
 
173
        }
 
174
 
 
175
        int pad = id.length % 8;
 
176
 
 
177
        if (pad == 0)
 
178
        {
 
179
            return new DERBitString(bytes);
 
180
        }
 
181
        else
 
182
        {
 
183
            return new DERBitString(bytes, 8 - pad);
 
184
        }
 
185
    }
 
186
    
 
187
    /**
 
188
     * add a given extension field for the standard extensions tag (tag 3)
 
189
     */
 
190
    public void addExtension(
 
191
        String          oid,
 
192
        boolean         critical,
 
193
        DEREncodable    value)
 
194
    {
 
195
        this.addExtension(new DERObjectIdentifier(oid), critical, value);
 
196
    }
 
197
 
 
198
    /**
 
199
     * add a given extension field for the standard extensions tag (tag 3)
 
200
     */
 
201
    public void addExtension(
 
202
        DERObjectIdentifier oid,
 
203
        boolean             critical,
 
204
        DEREncodable        value)
 
205
    {
 
206
        extGenerator.addExtension(oid, critical,  value);
 
207
    }
 
208
 
 
209
    /**
 
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.
 
213
     */
 
214
    public void addExtension(
 
215
        String          oid,
 
216
        boolean         critical,
 
217
        byte[]          value)
 
218
    {
 
219
        this.addExtension(new DERObjectIdentifier(oid), critical, value);
 
220
    }
 
221
 
 
222
    /**
 
223
     * add a given extension field for the standard extensions tag (tag 3)
 
224
     */
 
225
    public void addExtension(
 
226
        DERObjectIdentifier oid,
 
227
        boolean             critical,
 
228
        byte[]              value)
 
229
    {
 
230
        extGenerator.addExtension(oid, critical, value);
 
231
    }
 
232
 
 
233
    /**
 
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.
 
237
     */
 
238
    public void copyAndAddExtension(
 
239
        String          oid,
 
240
        boolean         critical,
 
241
        X509Certificate cert) 
 
242
        throws CertificateParsingException
 
243
    {
 
244
        byte[] extValue = cert.getExtensionValue(oid);
 
245
        
 
246
        if (extValue == null)
 
247
        {
 
248
            throw new CertificateParsingException("extension " + oid + " not present");
 
249
        }
 
250
        
 
251
        try
 
252
        {
 
253
            ASN1Encodable value = X509ExtensionUtil.fromExtensionValue(extValue);
 
254
    
 
255
            this.addExtension(oid, critical, value);
 
256
        }
 
257
        catch (IOException e)
 
258
        {
 
259
            throw new CertificateParsingException(e.toString());
 
260
        }
 
261
    }
 
262
 
 
263
    /**
 
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.
 
267
     */
 
268
    public void copyAndAddExtension(
 
269
        DERObjectIdentifier oid,
 
270
        boolean             critical,
 
271
        X509Certificate     cert)
 
272
        throws CertificateParsingException
 
273
    {
 
274
        this.copyAndAddExtension(oid.getId(), critical, cert);
 
275
    }
 
276
 
 
277
    /**
 
278
     * generate an X509 certificate, based on the current issuer and subject
 
279
     * using the default provider "BC".
 
280
     * @deprecated use generate(key, "BC")
 
281
     */
 
282
    public X509Certificate generateX509Certificate(
 
283
        PrivateKey      key)
 
284
        throws SecurityException, SignatureException, InvalidKeyException
 
285
    {
 
286
        try
 
287
        {
 
288
            return generateX509Certificate(key, "BC", null);
 
289
        }
 
290
        catch (NoSuchProviderException e)
 
291
        {
 
292
            throw new SecurityException("BC provider not installed!");
 
293
        }
 
294
    }
 
295
 
 
296
    /**
 
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
 
299
     * (if required).
 
300
     * @deprecated use generate(key, random, "BC")
 
301
     */
 
302
    public X509Certificate generateX509Certificate(
 
303
        PrivateKey      key,
 
304
        SecureRandom    random)
 
305
        throws SecurityException, SignatureException, InvalidKeyException
 
306
    {
 
307
        try
 
308
        {
 
309
            return generateX509Certificate(key, "BC", random);
 
310
        }
 
311
        catch (NoSuchProviderException e)
 
312
        {
 
313
            throw new SecurityException("BC provider not installed!");
 
314
        }
 
315
    }
 
316
 
 
317
    /**
 
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()
 
321
     */
 
322
    public X509Certificate generateX509Certificate(
 
323
        PrivateKey      key,
 
324
        String          provider)
 
325
        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
 
326
    {
 
327
        return generateX509Certificate(key, provider, null);
 
328
    }
 
329
 
 
330
    /**
 
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()
 
335
     */
 
336
    public X509Certificate generateX509Certificate(
 
337
        PrivateKey      key,
 
338
        String          provider,
 
339
        SecureRandom    random)
 
340
        throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
 
341
    {
 
342
        try
 
343
        {
 
344
            return generate(key, provider, random);
 
345
        }
 
346
        catch (NoSuchProviderException e)
 
347
        {
 
348
            throw e;
 
349
        }
 
350
        catch (SignatureException e)
 
351
        {
 
352
            throw e;
 
353
        }
 
354
        catch (InvalidKeyException e)
 
355
        {
 
356
            throw e;
 
357
        }
 
358
        catch (GeneralSecurityException e)
 
359
        {
 
360
            throw new SecurityException("exception: " + e);
 
361
        }
 
362
    }
 
363
 
 
364
    /**
 
365
     * generate an X509 certificate, based on the current issuer and subject
 
366
     * using the default provider.
 
367
     * <p>
 
368
     * <b>Note:</b> this differs from the deprecated method in that the default provider is
 
369
     * used - not "BC".
 
370
     * </p>
 
371
     */
 
372
    public X509Certificate generate(
 
373
        PrivateKey      key)
 
374
        throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
 
375
    {
 
376
        return generate(key, (SecureRandom)null);
 
377
    }
 
378
 
 
379
    /**
 
380
     * generate an X509 certificate, based on the current issuer and subject
 
381
     * using the default provider, and the passed in source of randomness
 
382
     * (if required).
 
383
     * <p>
 
384
     * <b>Note:</b> this differs from the deprecated method in that the default provider is
 
385
     * used - not "BC".
 
386
     * </p>
 
387
     */
 
388
    public X509Certificate generate(
 
389
        PrivateKey      key,
 
390
        SecureRandom    random)
 
391
        throws CertificateEncodingException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
 
392
    {
 
393
        TBSCertificateStructure tbsCert = generateTbsCert();
 
394
        byte[] signature;
 
395
 
 
396
        try
 
397
        {
 
398
            signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCert);
 
399
        }
 
400
        catch (IOException e)
 
401
        {
 
402
            throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
 
403
        }
 
404
 
 
405
        try
 
406
        {
 
407
            return generateJcaObject(tbsCert, signature);
 
408
        }
 
409
        catch (CertificateParsingException e)
 
410
        {
 
411
            throw new ExtCertificateEncodingException("exception producing certificate object", e);
 
412
        }
 
413
    }
 
414
 
 
415
    /**
 
416
     * generate an X509 certificate, based on the current issuer and subject,
 
417
     * using the passed in provider for the signing.
 
418
     */
 
419
    public X509Certificate generate(
 
420
        PrivateKey      key,
 
421
        String          provider)
 
422
        throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
 
423
    {
 
424
        return generate(key, provider, null);
 
425
    }
 
426
 
 
427
    /**
 
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.
 
431
     */
 
432
    public X509Certificate generate(
 
433
        PrivateKey      key,
 
434
        String          provider,
 
435
        SecureRandom    random)
 
436
        throws CertificateEncodingException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
 
437
    {
 
438
        TBSCertificateStructure tbsCert = generateTbsCert();
 
439
        byte[] signature;
 
440
 
 
441
        try
 
442
        {
 
443
            signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCert);
 
444
        }
 
445
        catch (IOException e)
 
446
        {
 
447
            throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
 
448
        }
 
449
 
 
450
        try
 
451
        {
 
452
            return generateJcaObject(tbsCert, signature);
 
453
        }
 
454
        catch (CertificateParsingException e)
 
455
        {
 
456
            throw new ExtCertificateEncodingException("exception producing certificate object", e);
 
457
        }
 
458
    }
 
459
 
 
460
    private TBSCertificateStructure generateTbsCert()
 
461
    {
 
462
        if (!extGenerator.isEmpty())
 
463
        {
 
464
            tbsGen.setExtensions(extGenerator.generate());
 
465
        }
 
466
 
 
467
        return tbsGen.generateTBSCertificate();
 
468
    }
 
469
 
 
470
    private X509Certificate generateJcaObject(TBSCertificateStructure tbsCert, byte[] signature)
 
471
        throws CertificateParsingException
 
472
    {
 
473
        ASN1EncodableVector v = new ASN1EncodableVector();
 
474
 
 
475
        v.add(tbsCert);
 
476
        v.add(sigAlgId);
 
477
        v.add(new DERBitString(signature));
 
478
 
 
479
        return new X509CertificateObject(new X509CertificateStructure(new DERSequence(v)));
 
480
    }
 
481
 
 
482
    /**
 
483
     * Return an iterator of the signature names supported by the generator.
 
484
     * 
 
485
     * @return an iterator containing recognised names.
 
486
     */
 
487
    public Iterator getSignatureAlgNames()
 
488
    {
 
489
        return X509Util.getAlgNames();
 
490
    }
 
491
}