001: package org.bouncycastle.x509;
002:
003: import org.bouncycastle.asn1.ASN1Encodable;
004: import org.bouncycastle.asn1.ASN1EncodableVector;
005: import org.bouncycastle.asn1.DERBitString;
006: import org.bouncycastle.asn1.DERGeneralizedTime;
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.AttCertIssuer;
012: import org.bouncycastle.asn1.x509.Attribute;
013: import org.bouncycastle.asn1.x509.AttributeCertificate;
014: import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
015: import org.bouncycastle.asn1.x509.V2AttributeCertificateInfoGenerator;
016: import org.bouncycastle.asn1.x509.X509ExtensionsGenerator;
017:
018: import java.io.IOException;
019: import java.math.BigInteger;
020: import java.security.GeneralSecurityException;
021: import java.security.InvalidKeyException;
022: import java.security.NoSuchAlgorithmException;
023: import java.security.NoSuchProviderException;
024: import java.security.PrivateKey;
025: import java.security.SecureRandom;
026: import java.security.SignatureException;
027: import java.security.cert.CertificateEncodingException;
028: import java.util.Date;
029: import java.util.Iterator;
030:
031: /**
032: * class to produce an X.509 Version 2 AttributeCertificate.
033: */
034: public class X509V2AttributeCertificateGenerator {
035: private V2AttributeCertificateInfoGenerator acInfoGen;
036: private DERObjectIdentifier sigOID;
037: private AlgorithmIdentifier sigAlgId;
038: private String signatureAlgorithm;
039: private X509ExtensionsGenerator extGenerator;
040:
041: public X509V2AttributeCertificateGenerator() {
042: acInfoGen = new V2AttributeCertificateInfoGenerator();
043: extGenerator = new X509ExtensionsGenerator();
044: }
045:
046: /**
047: * reset the generator
048: */
049: public void reset() {
050: acInfoGen = new V2AttributeCertificateInfoGenerator();
051: extGenerator.reset();
052: }
053:
054: /**
055: * Set the Holder of this Attribute Certificate
056: */
057: public void setHolder(AttributeCertificateHolder holder) {
058: acInfoGen.setHolder(holder.holder);
059: }
060:
061: /**
062: * Set the issuer
063: */
064: public void setIssuer(AttributeCertificateIssuer issuer) {
065: acInfoGen.setIssuer(AttCertIssuer.getInstance(issuer.form));
066: }
067:
068: /**
069: * set the serial number for the certificate.
070: */
071: public void setSerialNumber(BigInteger serialNumber) {
072: acInfoGen.setSerialNumber(new DERInteger(serialNumber));
073: }
074:
075: public void setNotBefore(Date date) {
076: acInfoGen.setStartDate(new DERGeneralizedTime(date));
077: }
078:
079: public void setNotAfter(Date date) {
080: acInfoGen.setEndDate(new DERGeneralizedTime(date));
081: }
082:
083: /**
084: * Set the signature algorithm. This can be either a name or an OID, names
085: * are treated as case insensitive.
086: *
087: * @param signatureAlgorithm string representation of the algorithm name.
088: */
089: public void setSignatureAlgorithm(String signatureAlgorithm) {
090: this .signatureAlgorithm = signatureAlgorithm;
091:
092: try {
093: sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
094: } catch (Exception e) {
095: throw new IllegalArgumentException(
096: "Unknown signature type requested");
097: }
098:
099: sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
100:
101: acInfoGen.setSignature(sigAlgId);
102: }
103:
104: /**
105: * add an attribute
106: */
107: public void addAttribute(X509Attribute attribute) {
108: acInfoGen.addAttribute(Attribute.getInstance(attribute
109: .toASN1Object()));
110: }
111:
112: public void setIssuerUniqueId(boolean[] iui) {
113: // [TODO] convert boolean array to bit string
114: //acInfoGen.setIssuerUniqueID(iui);
115: throw new RuntimeException("not implemented (yet)");
116: }
117:
118: /**
119: * add a given extension field for the standard extensions tag
120: * @throws IOException
121: */
122: public void addExtension(String oid, boolean critical,
123: ASN1Encodable value) throws IOException {
124: extGenerator.addExtension(new DERObjectIdentifier(oid),
125: critical, value);
126: }
127:
128: /**
129: * add a given extension field for the standard extensions tag
130: * The value parameter becomes the contents of the octet string associated
131: * with the extension.
132: */
133: public void addExtension(String oid, boolean critical, byte[] value) {
134: extGenerator.addExtension(new DERObjectIdentifier(oid),
135: critical, value);
136: }
137:
138: /**
139: * generate an X509 certificate, based on the current issuer and subject,
140: * using the passed in provider for the signing.
141: * @deprecated use generate()
142: */
143: public X509AttributeCertificate generateCertificate(PrivateKey key,
144: String provider) throws NoSuchProviderException,
145: SecurityException, SignatureException, InvalidKeyException {
146: return generateCertificate(key, provider, null);
147: }
148:
149: /**
150: * generate an X509 certificate, based on the current issuer and subject,
151: * using the passed in provider for the signing and the supplied source
152: * of randomness, if required.
153: * @deprecated use generate()
154: */
155: public X509AttributeCertificate generateCertificate(PrivateKey key,
156: String provider, SecureRandom random)
157: throws NoSuchProviderException, SecurityException,
158: SignatureException, InvalidKeyException {
159: try {
160: return generate(key, provider, random);
161: } catch (NoSuchProviderException e) {
162: throw e;
163: } catch (SignatureException e) {
164: throw e;
165: } catch (InvalidKeyException e) {
166: throw e;
167: } catch (GeneralSecurityException e) {
168: throw new SecurityException(
169: "exception creating certificate: " + e);
170: }
171: }
172:
173: /**
174: * generate an X509 certificate, based on the current issuer and subject,
175: * using the passed in provider for the signing.
176: */
177: public X509AttributeCertificate generate(PrivateKey key,
178: String provider) throws CertificateEncodingException,
179: IllegalStateException, NoSuchProviderException,
180: SignatureException, InvalidKeyException,
181: NoSuchAlgorithmException {
182: return generate(key, provider, null);
183: }
184:
185: /**
186: * generate an X509 certificate, based on the current issuer and subject,
187: * using the passed in provider for the signing and the supplied source
188: * of randomness, if required.
189: */
190: public X509AttributeCertificate generate(PrivateKey key,
191: String provider, SecureRandom random)
192: throws CertificateEncodingException, IllegalStateException,
193: NoSuchProviderException, NoSuchAlgorithmException,
194: SignatureException, InvalidKeyException {
195: if (!extGenerator.isEmpty()) {
196: acInfoGen.setExtensions(extGenerator.generate());
197: }
198:
199: AttributeCertificateInfo acInfo = acInfoGen
200: .generateAttributeCertificateInfo();
201:
202: ASN1EncodableVector v = new ASN1EncodableVector();
203:
204: v.add(acInfo);
205: v.add(sigAlgId);
206:
207: try {
208: v
209: .add(new DERBitString(X509Util.calculateSignature(
210: sigOID, signatureAlgorithm, provider, key,
211: random, acInfo)));
212:
213: return new X509V2AttributeCertificate(
214: new AttributeCertificate(new DERSequence(v)));
215: } catch (IOException e) {
216: throw new ExtCertificateEncodingException(
217: "constructed invalid certificate", e);
218: }
219: }
220:
221: /**
222: * Return an iterator of the signature names supported by the generator.
223: *
224: * @return an iterator containing recognised names.
225: */
226: public Iterator getSignatureAlgNames() {
227: return X509Util.getAlgNames();
228: }
229: }
|