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