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.DEREncodable;
008: import org.bouncycastle.asn1.DERGeneralizedTime;
009: import org.bouncycastle.asn1.DERInteger;
010: import org.bouncycastle.asn1.DERObjectIdentifier;
011: import org.bouncycastle.asn1.DERSequence;
012: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
013: import org.bouncycastle.asn1.x509.CertificateList;
014: import org.bouncycastle.asn1.x509.TBSCertList;
015: import org.bouncycastle.asn1.x509.Time;
016: import org.bouncycastle.asn1.x509.V2TBSCertListGenerator;
017: import org.bouncycastle.asn1.x509.X509Extensions;
018: import org.bouncycastle.asn1.x509.X509ExtensionsGenerator;
019: import org.bouncycastle.asn1.x509.X509Name;
020: import org.bouncycastle.jce.X509Principal;
021: import org.bouncycastle.jce.provider.X509CRLObject;
022:
023: import javax.security.auth.x500.X500Principal;
024: import java.io.IOException;
025: import java.math.BigInteger;
026: import java.security.GeneralSecurityException;
027: import java.security.InvalidKeyException;
028: import java.security.NoSuchAlgorithmException;
029: import java.security.NoSuchProviderException;
030: import java.security.PrivateKey;
031: import java.security.SecureRandom;
032: import java.security.SignatureException;
033: import java.security.cert.CRLException;
034: import java.security.cert.X509CRL;
035: import java.security.cert.X509CRLEntry;
036: import java.util.Date;
037: import java.util.Iterator;
038: import java.util.Set;
039:
040: /**
041: * class to produce an X.509 Version 2 CRL.
042: */
043: public class X509V2CRLGenerator {
044: private V2TBSCertListGenerator tbsGen;
045: private DERObjectIdentifier sigOID;
046: private AlgorithmIdentifier sigAlgId;
047: private String signatureAlgorithm;
048: private X509ExtensionsGenerator extGenerator;
049:
050: public X509V2CRLGenerator() {
051: tbsGen = new V2TBSCertListGenerator();
052: extGenerator = new X509ExtensionsGenerator();
053: }
054:
055: /**
056: * reset the generator
057: */
058: public void reset() {
059: tbsGen = new V2TBSCertListGenerator();
060: extGenerator.reset();
061: }
062:
063: /**
064: * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
065: * certificate.
066: */
067: public void setIssuerDN(X500Principal issuer) {
068: try {
069: tbsGen.setIssuer(new X509Principal(issuer.getEncoded()));
070: } catch (IOException e) {
071: throw new IllegalArgumentException(
072: "can't process principal: " + e);
073: }
074: }
075:
076: /**
077: * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
078: * certificate.
079: */
080: public void setIssuerDN(X509Name issuer) {
081: tbsGen.setIssuer(issuer);
082: }
083:
084: public void setThisUpdate(Date date) {
085: tbsGen.setThisUpdate(new Time(date));
086: }
087:
088: public void setNextUpdate(Date date) {
089: tbsGen.setNextUpdate(new Time(date));
090: }
091:
092: /**
093: * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise
094: * or 0 if CRLReason is not to be used
095: **/
096: public void addCRLEntry(BigInteger userCertificate,
097: Date revocationDate, int reason) {
098: tbsGen.addCRLEntry(new DERInteger(userCertificate), new Time(
099: revocationDate), reason);
100: }
101:
102: /**
103: * Add a CRL entry with an Invalidity Date extension as well as a CRLReason extension.
104: * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise
105: * or 0 if CRLReason is not to be used
106: **/
107: public void addCRLEntry(BigInteger userCertificate,
108: Date revocationDate, int reason, Date invalidityDate) {
109: tbsGen.addCRLEntry(new DERInteger(userCertificate), new Time(
110: revocationDate), reason, new DERGeneralizedTime(
111: invalidityDate));
112: }
113:
114: /**
115: * Add a CRL entry with extensions.
116: **/
117: public void addCRLEntry(BigInteger userCertificate,
118: Date revocationDate, X509Extensions extensions) {
119: tbsGen.addCRLEntry(new DERInteger(userCertificate), new Time(
120: revocationDate), extensions);
121: }
122:
123: /**
124: * Add the CRLEntry objects contained in a previous CRL.
125: *
126: * @param other the X509CRL to source the other entries from.
127: */
128: public void addCRL(X509CRL other) throws CRLException {
129: Set revocations = other.getRevokedCertificates();
130:
131: if (revocations != null) {
132: Iterator it = revocations.iterator();
133: while (it.hasNext()) {
134: X509CRLEntry entry = (X509CRLEntry) it.next();
135:
136: ASN1InputStream aIn = new ASN1InputStream(entry
137: .getEncoded());
138:
139: try {
140: tbsGen.addCRLEntry(ASN1Sequence.getInstance(aIn
141: .readObject()));
142: } catch (IOException e) {
143: throw new CRLException(
144: "exception processing encoding of CRL: "
145: + e.toString());
146: }
147: }
148: }
149: }
150:
151: /**
152: * Set the signature algorithm. This can be either a name or an OID, names
153: * are treated as case insensitive.
154: *
155: * @param signatureAlgorithm string representation of the algorithm name.
156: */
157: public void setSignatureAlgorithm(String signatureAlgorithm) {
158: this .signatureAlgorithm = signatureAlgorithm;
159:
160: try {
161: sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
162: } catch (Exception e) {
163: throw new IllegalArgumentException(
164: "Unknown signature type requested");
165: }
166:
167: sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
168:
169: tbsGen.setSignature(sigAlgId);
170: }
171:
172: /**
173: * add a given extension field for the standard extensions tag (tag 0)
174: */
175: public void addExtension(String oid, boolean critical,
176: DEREncodable value) {
177: this
178: .addExtension(new DERObjectIdentifier(oid), critical,
179: value);
180: }
181:
182: /**
183: * add a given extension field for the standard extensions tag (tag 0)
184: */
185: public void addExtension(DERObjectIdentifier oid, boolean critical,
186: DEREncodable value) {
187: extGenerator.addExtension(oid, critical, value);
188: }
189:
190: /**
191: * add a given extension field for the standard extensions tag (tag 0)
192: */
193: public void addExtension(String oid, boolean critical, byte[] value) {
194: this
195: .addExtension(new DERObjectIdentifier(oid), critical,
196: value);
197: }
198:
199: /**
200: * add a given extension field for the standard extensions tag (tag 0)
201: */
202: public void addExtension(DERObjectIdentifier oid, boolean critical,
203: byte[] value) {
204: extGenerator.addExtension(oid, critical, value);
205: }
206:
207: /**
208: * generate an X509 CRL, based on the current issuer and subject
209: * using the default provider "BC".
210: * @deprecated use generate(key, "BC")
211: */
212: public X509CRL generateX509CRL(PrivateKey key)
213: throws SecurityException, SignatureException,
214: InvalidKeyException {
215: try {
216: return generateX509CRL(key, "BC", null);
217: } catch (NoSuchProviderException e) {
218: throw new SecurityException("BC provider not installed!");
219: }
220: }
221:
222: /**
223: * generate an X509 CRL, based on the current issuer and subject
224: * using the default provider "BC" and an user defined SecureRandom object as
225: * source of randomness.
226: * @deprecated use generate(key, random, "BC")
227: */
228: public X509CRL generateX509CRL(PrivateKey key, SecureRandom random)
229: throws SecurityException, SignatureException,
230: InvalidKeyException {
231: try {
232: return generateX509CRL(key, "BC", random);
233: } catch (NoSuchProviderException e) {
234: throw new SecurityException("BC provider not installed!");
235: }
236: }
237:
238: /**
239: * generate an X509 certificate, based on the current issuer and subject
240: * using the passed in provider for the signing.
241: * @deprecated use generate()
242: */
243: public X509CRL generateX509CRL(PrivateKey key, String provider)
244: throws NoSuchProviderException, SecurityException,
245: SignatureException, InvalidKeyException {
246: return generateX509CRL(key, provider, null);
247: }
248:
249: /**
250: * generate an X509 CRL, based on the current issuer and subject,
251: * using the passed in provider for the signing.
252: * @deprecated use generate()
253: */
254: public X509CRL generateX509CRL(PrivateKey key, String provider,
255: SecureRandom random) throws NoSuchProviderException,
256: SecurityException, SignatureException, InvalidKeyException {
257: try {
258: return generate(key, provider, random);
259: } catch (NoSuchProviderException e) {
260: throw e;
261: } catch (SignatureException e) {
262: throw e;
263: } catch (InvalidKeyException e) {
264: throw e;
265: } catch (GeneralSecurityException e) {
266: throw new SecurityException("exception: " + e);
267: }
268: }
269:
270: /**
271: * generate an X509 CRL, based on the current issuer and subject
272: * using the default provider.
273: * <p>
274: * <b>Note:</b> this differs from the deprecated method in that the default provider is
275: * used - not "BC".
276: * </p>
277: */
278: public X509CRL generate(PrivateKey key) throws CRLException,
279: IllegalStateException, NoSuchAlgorithmException,
280: SignatureException, InvalidKeyException {
281: return generate(key, (SecureRandom) null);
282: }
283:
284: /**
285: * generate an X509 CRL, based on the current issuer and subject
286: * using the default provider and an user defined SecureRandom object as
287: * source of randomness.
288: * <p>
289: * <b>Note:</b> this differs from the deprecated method in that the default provider is
290: * used - not "BC".
291: * </p>
292: */
293: public X509CRL generate(PrivateKey key, SecureRandom random)
294: throws CRLException, IllegalStateException,
295: NoSuchAlgorithmException, SignatureException,
296: InvalidKeyException {
297: TBSCertList tbsCrl = generateCertList();
298: byte[] signature;
299:
300: try {
301: signature = X509Util.calculateSignature(sigOID,
302: signatureAlgorithm, key, random, tbsCrl);
303: } catch (IOException e) {
304: throw new ExtCRLException("cannot generate CRL encoding", e);
305: }
306:
307: return generateJcaObject(tbsCrl, signature);
308: }
309:
310: /**
311: * generate an X509 certificate, based on the current issuer and subject
312: * using the passed in provider for the signing.
313: */
314: public X509CRL generate(PrivateKey key, String provider)
315: throws CRLException, IllegalStateException,
316: NoSuchProviderException, NoSuchAlgorithmException,
317: SignatureException, InvalidKeyException {
318: return generate(key, provider, null);
319: }
320:
321: /**
322: * generate an X509 CRL, based on the current issuer and subject,
323: * using the passed in provider for the signing.
324: */
325: public X509CRL generate(PrivateKey key, String provider,
326: SecureRandom random) throws CRLException,
327: IllegalStateException, NoSuchProviderException,
328: NoSuchAlgorithmException, SignatureException,
329: InvalidKeyException {
330: TBSCertList tbsCrl = generateCertList();
331: byte[] signature;
332:
333: try {
334: signature = X509Util.calculateSignature(sigOID,
335: signatureAlgorithm, provider, key, random, tbsCrl);
336: } catch (IOException e) {
337: throw new ExtCRLException("cannot generate CRL encoding", e);
338: }
339:
340: return generateJcaObject(tbsCrl, signature);
341: }
342:
343: private TBSCertList generateCertList() {
344: if (!extGenerator.isEmpty()) {
345: tbsGen.setExtensions(extGenerator.generate());
346: }
347:
348: return tbsGen.generateTBSCertList();
349: }
350:
351: private X509CRL generateJcaObject(TBSCertList tbsCrl,
352: byte[] signature) throws CRLException {
353: ASN1EncodableVector v = new ASN1EncodableVector();
354:
355: v.add(tbsCrl);
356: v.add(sigAlgId);
357: v.add(new DERBitString(signature));
358:
359: return new X509CRLObject(
360: new CertificateList(new DERSequence(v)));
361: }
362:
363: /**
364: * Return an iterator of the signature names supported by the generator.
365: *
366: * @return an iterator containing recognised names.
367: */
368: public Iterator getSignatureAlgNames() {
369: return X509Util.getAlgNames();
370: }
371:
372: private static class ExtCRLException extends CRLException {
373: Throwable cause;
374:
375: ExtCRLException(String message, Throwable cause) {
376: super (message);
377: this .cause = cause;
378: }
379:
380: public Throwable getCause() {
381: return cause;
382: }
383: }
384: }
|