001: package org.bouncycastle.x509;
002:
003: import org.bouncycastle.asn1.ASN1EncodableVector;
004: import org.bouncycastle.asn1.ASN1InputStream;
005: import org.bouncycastle.asn1.ASN1Sequence;
006: import org.bouncycastle.asn1.DERBitString;
007: import org.bouncycastle.asn1.DERInteger;
008: import org.bouncycastle.asn1.DERObjectIdentifier;
009: import org.bouncycastle.asn1.DERSequence;
010: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
011: import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
012: import org.bouncycastle.asn1.x509.TBSCertificateStructure;
013: import org.bouncycastle.asn1.x509.Time;
014: import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator;
015: import org.bouncycastle.asn1.x509.X509CertificateStructure;
016: import org.bouncycastle.asn1.x509.X509Name;
017: import org.bouncycastle.jce.X509Principal;
018: import org.bouncycastle.jce.provider.X509CertificateObject;
019:
020: import javax.security.auth.x500.X500Principal;
021: import java.io.ByteArrayInputStream;
022: import java.io.IOException;
023: import java.math.BigInteger;
024: import java.security.GeneralSecurityException;
025: import java.security.InvalidKeyException;
026: import java.security.NoSuchAlgorithmException;
027: import java.security.NoSuchProviderException;
028: import java.security.PrivateKey;
029: import java.security.PublicKey;
030: import java.security.SecureRandom;
031: import java.security.SignatureException;
032: import java.security.cert.CertificateEncodingException;
033: import java.security.cert.CertificateParsingException;
034: import java.security.cert.X509Certificate;
035: import java.util.Date;
036: import java.util.Iterator;
037:
038: /**
039: * class to produce an X.509 Version 1 certificate.
040: */
041: public class X509V1CertificateGenerator {
042: private V1TBSCertificateGenerator tbsGen;
043: private DERObjectIdentifier sigOID;
044: private AlgorithmIdentifier sigAlgId;
045: private String signatureAlgorithm;
046:
047: public X509V1CertificateGenerator() {
048: tbsGen = new V1TBSCertificateGenerator();
049: }
050:
051: /**
052: * reset the generator
053: */
054: public void reset() {
055: tbsGen = new V1TBSCertificateGenerator();
056: }
057:
058: /**
059: * set the serial number for the certificate.
060: */
061: public void setSerialNumber(BigInteger serialNumber) {
062: if (serialNumber.compareTo(BigInteger.ZERO) <= 0) {
063: throw new IllegalArgumentException(
064: "serial number must be a positive integer");
065: }
066:
067: tbsGen.setSerialNumber(new DERInteger(serialNumber));
068: }
069:
070: /**
071: * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
072: * certificate.
073: */
074: public void setIssuerDN(X500Principal issuer) {
075: try {
076: tbsGen.setIssuer(new X509Principal(issuer.getEncoded()));
077: } catch (IOException e) {
078: throw new IllegalArgumentException(
079: "can't process principal: " + e);
080: }
081: }
082:
083: /**
084: * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
085: * certificate.
086: */
087: public void setIssuerDN(X509Name issuer) {
088: tbsGen.setIssuer(issuer);
089: }
090:
091: public void setNotBefore(Date date) {
092: tbsGen.setStartDate(new Time(date));
093: }
094:
095: public void setNotAfter(Date date) {
096: tbsGen.setEndDate(new Time(date));
097: }
098:
099: /**
100: * Set the subject distinguished name. The subject describes the entity associated with the public key.
101: */
102: public void setSubjectDN(X500Principal subject) {
103: try {
104: tbsGen.setSubject(new X509Principal(subject.getEncoded()));
105: } catch (IOException e) {
106: throw new IllegalArgumentException(
107: "can't process principal: " + e);
108: }
109: }
110:
111: /**
112: * Set the subject distinguished name. The subject describes the entity associated with the public key.
113: */
114: public void setSubjectDN(X509Name subject) {
115: tbsGen.setSubject(subject);
116: }
117:
118: public void setPublicKey(PublicKey key) {
119: try {
120: tbsGen.setSubjectPublicKeyInfo(new SubjectPublicKeyInfo(
121: (ASN1Sequence) new ASN1InputStream(
122: new ByteArrayInputStream(key.getEncoded()))
123: .readObject()));
124: } catch (Exception e) {
125: throw new IllegalArgumentException(
126: "unable to process key - " + e.toString());
127: }
128: }
129:
130: /**
131: * Set the signature algorithm. This can be either a name or an OID, names
132: * are treated as case insensitive.
133: *
134: * @param signatureAlgorithm string representation of the algorithm name.
135: */
136: public void setSignatureAlgorithm(String signatureAlgorithm) {
137: this .signatureAlgorithm = signatureAlgorithm;
138:
139: try {
140: sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
141: } catch (Exception e) {
142: throw new IllegalArgumentException(
143: "Unknown signature type requested");
144: }
145:
146: sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
147:
148: tbsGen.setSignature(sigAlgId);
149: }
150:
151: /**
152: * generate an X509 certificate, based on the current issuer and subject
153: * using the default provider "BC".
154: * @deprecated use generate(key, "BC")
155: */
156: public X509Certificate generateX509Certificate(PrivateKey key)
157: throws SecurityException, SignatureException,
158: InvalidKeyException {
159: try {
160: return generateX509Certificate(key, "BC", null);
161: } catch (NoSuchProviderException e) {
162: throw new SecurityException("BC provider not installed!");
163: }
164: }
165:
166: /**
167: * generate an X509 certificate, based on the current issuer and subject
168: * using the default provider "BC" and the passed in source of randomness
169: * @deprecated use generate(key, random, "BC")
170: */
171: public X509Certificate generateX509Certificate(PrivateKey key,
172: SecureRandom random) throws SecurityException,
173: SignatureException, InvalidKeyException {
174: try {
175: return generateX509Certificate(key, "BC", random);
176: } catch (NoSuchProviderException e) {
177: throw new SecurityException("BC provider not installed!");
178: }
179: }
180:
181: /**
182: * generate an X509 certificate, based on the current issuer and subject,
183: * using the passed in provider for the signing, and the passed in source
184: * of randomness (if required).
185: * @deprecated use generate()
186: */
187: public X509Certificate generateX509Certificate(PrivateKey key,
188: String provider) throws NoSuchProviderException,
189: SecurityException, SignatureException, InvalidKeyException {
190: return generateX509Certificate(key, provider, null);
191: }
192:
193: /**
194: * generate an X509 certificate, based on the current issuer and subject,
195: * using the passed in provider for the signing, and the passed in source
196: * of randomness (if required).
197: * @deprecated use generate()
198: */
199: public X509Certificate generateX509Certificate(PrivateKey key,
200: String provider, SecureRandom random)
201: throws NoSuchProviderException, SecurityException,
202: SignatureException, InvalidKeyException {
203: try {
204: return generate(key, provider, random);
205: } catch (NoSuchProviderException e) {
206: throw e;
207: } catch (SignatureException e) {
208: throw e;
209: } catch (InvalidKeyException e) {
210: throw e;
211: } catch (GeneralSecurityException e) {
212: throw new SecurityException("exception: " + e);
213: }
214: }
215:
216: /**
217: * generate an X509 certificate, based on the current issuer and subject
218: * using the default provider.
219: * <p>
220: * <b>Note:</b> this differs from the deprecated method in that the default provider is
221: * used - not "BC".
222: * </p>
223: */
224: public X509Certificate generate(PrivateKey key)
225: throws CertificateEncodingException, IllegalStateException,
226: NoSuchAlgorithmException, SignatureException,
227: InvalidKeyException {
228: return generate(key, (SecureRandom) null);
229: }
230:
231: /**
232: * generate an X509 certificate, based on the current issuer and subject
233: * using the default provider and the passed in source of randomness
234: * <p>
235: * <b>Note:</b> this differs from the deprecated method in that the default provider is
236: * used - not "BC".
237: * </p>
238: */
239: public X509Certificate generate(PrivateKey key, SecureRandom random)
240: throws CertificateEncodingException, IllegalStateException,
241: NoSuchAlgorithmException, SignatureException,
242: InvalidKeyException {
243: TBSCertificateStructure tbsCert = tbsGen
244: .generateTBSCertificate();
245: byte[] signature;
246:
247: try {
248: signature = X509Util.calculateSignature(sigOID,
249: signatureAlgorithm, key, random, tbsCert);
250: } catch (IOException e) {
251: throw new ExtCertificateEncodingException(
252: "exception encoding TBS cert", e);
253: }
254:
255: return generateJcaObject(tbsCert, signature);
256: }
257:
258: /**
259: * generate an X509 certificate, based on the current issuer and subject,
260: * using the passed in provider for the signing, and the passed in source
261: * of randomness (if required).
262: */
263: public X509Certificate generate(PrivateKey key, String provider)
264: throws CertificateEncodingException, IllegalStateException,
265: NoSuchProviderException, NoSuchAlgorithmException,
266: SignatureException, InvalidKeyException {
267: return generate(key, provider, null);
268: }
269:
270: /**
271: * generate an X509 certificate, based on the current issuer and subject,
272: * using the passed in provider for the signing, and the passed in source
273: * of randomness (if required).
274: */
275: public X509Certificate generate(PrivateKey key, String provider,
276: SecureRandom random) throws CertificateEncodingException,
277: IllegalStateException, NoSuchProviderException,
278: NoSuchAlgorithmException, SignatureException,
279: InvalidKeyException {
280: TBSCertificateStructure tbsCert = tbsGen
281: .generateTBSCertificate();
282: byte[] signature;
283:
284: try {
285: signature = X509Util.calculateSignature(sigOID,
286: signatureAlgorithm, provider, key, random, tbsCert);
287: } catch (IOException e) {
288: throw new ExtCertificateEncodingException(
289: "exception encoding TBS cert", e);
290: }
291:
292: return generateJcaObject(tbsCert, signature);
293: }
294:
295: private X509Certificate generateJcaObject(
296: TBSCertificateStructure tbsCert, byte[] signature)
297: throws CertificateEncodingException {
298: ASN1EncodableVector v = new ASN1EncodableVector();
299:
300: v.add(tbsCert);
301: v.add(sigAlgId);
302: v.add(new DERBitString(signature));
303:
304: try {
305: return new X509CertificateObject(
306: new X509CertificateStructure(new DERSequence(v)));
307: } catch (CertificateParsingException e) {
308: throw new ExtCertificateEncodingException(
309: "exception producing certificate object", e);
310: }
311: }
312:
313: /**
314: * Return an iterator of the signature names supported by the generator.
315: *
316: * @return an iterator containing recognised names.
317: */
318: public Iterator getSignatureAlgNames() {
319: return X509Util.getAlgNames();
320: }
321: }
|