001: package org.bouncycastle.tsp;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.IOException;
005: import java.math.BigInteger;
006: import java.util.Date;
007: import java.util.Hashtable;
008: import java.security.InvalidAlgorithmParameterException;
009: import java.security.MessageDigest;
010: import java.security.NoSuchAlgorithmException;
011: import java.security.NoSuchProviderException;
012: import java.security.PrivateKey;
013: import java.security.cert.CollectionCertStoreParameters;
014: import java.security.cert.X509Certificate;
015: import java.security.cert.CertStore;
016: import java.security.cert.CertStoreException;
017: import java.security.cert.CertificateEncodingException;
018:
019: import org.bouncycastle.cms.CMSProcessableByteArray;
020: import org.bouncycastle.cms.CMSSignedDataGenerator;
021: import org.bouncycastle.cms.CMSSignedData;
022: import org.bouncycastle.cms.CMSException;
023: import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
024: import org.bouncycastle.asn1.tsp.MessageImprint;
025: import org.bouncycastle.asn1.tsp.TSTInfo;
026: import org.bouncycastle.asn1.tsp.Accuracy;
027: import org.bouncycastle.asn1.ess.ESSCertID;
028: import org.bouncycastle.asn1.ess.SigningCertificate;
029: import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
030: import org.bouncycastle.asn1.x509.GeneralName;
031: import org.bouncycastle.asn1.cms.AttributeTable;
032: import org.bouncycastle.asn1.cms.Attribute;
033: import org.bouncycastle.asn1.DERObjectIdentifier;
034: import org.bouncycastle.asn1.DERGeneralizedTime;
035: import org.bouncycastle.asn1.DERInteger;
036: import org.bouncycastle.asn1.DERBoolean;
037: import org.bouncycastle.asn1.DERNull;
038: import org.bouncycastle.asn1.DEROutputStream;
039: import org.bouncycastle.asn1.DERSet;
040:
041: public class TimeStampTokenGenerator {
042: int accuracySeconds = -1;
043:
044: int accuracyMillis = -1;
045:
046: int accuracyMicros = -1;
047:
048: boolean ordering = false;
049:
050: GeneralName tsa = null;
051:
052: private String tsaPolicyOID;
053:
054: PrivateKey key;
055: X509Certificate cert;
056: String digestOID;
057: AttributeTable signedAttr;
058: AttributeTable unsignedAttr;
059: CertStore certsAndCrls;
060:
061: /**
062: * basic creation - only the default attributes will be included here.
063: */
064: public TimeStampTokenGenerator(PrivateKey key,
065: X509Certificate cert, String digestOID, String tsaPolicyOID)
066: throws IllegalArgumentException, TSPException {
067: this (key, cert, digestOID, tsaPolicyOID, null, null);
068: }
069:
070: /**
071: * create with a signer with extra signed/unsigned attributes.
072: */
073: public TimeStampTokenGenerator(PrivateKey key,
074: X509Certificate cert, String digestOID,
075: String tsaPolicyOID, AttributeTable signedAttr,
076: AttributeTable unsignedAttr)
077: throws IllegalArgumentException, TSPException {
078: this .key = key;
079: this .cert = cert;
080: this .digestOID = digestOID;
081: this .tsaPolicyOID = tsaPolicyOID;
082: this .unsignedAttr = unsignedAttr;
083:
084: TSPUtil.validateCertificate(cert);
085:
086: //
087: // add the essCertid
088: //
089: Hashtable signedAttrs = null;
090:
091: if (signedAttr != null) {
092: signedAttrs = signedAttr.toHashtable();
093: } else {
094: signedAttrs = new Hashtable();
095: }
096:
097: try {
098: ESSCertID essCertid = new ESSCertID(MessageDigest
099: .getInstance("SHA-1").digest(cert.getEncoded()));
100: signedAttrs
101: .put(
102: PKCSObjectIdentifiers.id_aa_signingCertificate,
103: new Attribute(
104: PKCSObjectIdentifiers.id_aa_signingCertificate,
105: new DERSet(new SigningCertificate(
106: essCertid))));
107: } catch (NoSuchAlgorithmException e) {
108: throw new TSPException(
109: "Can't find a SHA-1 implementation.", e);
110: } catch (CertificateEncodingException e) {
111: throw new TSPException("Exception processing certificate.",
112: e);
113: }
114:
115: this .signedAttr = new AttributeTable(signedAttrs);
116: }
117:
118: public void setCertificatesAndCRLs(CertStore certificates)
119: throws CertStoreException, TSPException {
120: this .certsAndCrls = certificates;
121: }
122:
123: public void setAccuracySeconds(int accuracySeconds) {
124: this .accuracySeconds = accuracySeconds;
125: }
126:
127: public void setAccuracyMillis(int accuracyMillis) {
128: this .accuracyMillis = accuracyMillis;
129: }
130:
131: public void setAccuracyMicros(int accuracyMicros) {
132: this .accuracyMicros = accuracyMicros;
133: }
134:
135: public void setOrdering(boolean ordering) {
136: this .ordering = ordering;
137: }
138:
139: public void setTSA(GeneralName tsa) {
140: this .tsa = tsa;
141: }
142:
143: //------------------------------------------------------------------------------
144:
145: public TimeStampToken generate(TimeStampRequest request,
146: BigInteger serialNumber, Date genTime, String provider)
147: throws NoSuchAlgorithmException, NoSuchProviderException,
148: TSPException {
149: DERObjectIdentifier digestAlgOID = new DERObjectIdentifier(
150: request.getMessageImprintAlgOID());
151:
152: AlgorithmIdentifier algID = new AlgorithmIdentifier(
153: digestAlgOID, new DERNull());
154: MessageImprint messageImprint = new MessageImprint(algID,
155: request.getMessageImprintDigest());
156:
157: Accuracy accuracy = null;
158: if (accuracySeconds > 0 || accuracyMillis > 0
159: || accuracyMicros > 0) {
160: DERInteger seconds = null;
161: if (accuracySeconds > 0) {
162: seconds = new DERInteger(accuracySeconds);
163: }
164:
165: DERInteger millis = null;
166: if (accuracyMillis > 0) {
167: millis = new DERInteger(accuracyMillis);
168: }
169:
170: DERInteger micros = null;
171: if (accuracyMicros > 0) {
172: micros = new DERInteger(accuracyMicros);
173: }
174:
175: accuracy = new Accuracy(seconds, millis, micros);
176: }
177:
178: DERBoolean derOrdering = null;
179: if (ordering) {
180: derOrdering = new DERBoolean(ordering);
181: }
182:
183: DERInteger nonce = null;
184: if (request.getNonce() != null) {
185: nonce = new DERInteger(request.getNonce());
186: }
187:
188: DERObjectIdentifier tsaPolicy = new DERObjectIdentifier(
189: tsaPolicyOID);
190: if (request.getReqPolicy() != null) {
191: tsaPolicy = new DERObjectIdentifier(request.getReqPolicy());
192: }
193:
194: TSTInfo tstInfo = new TSTInfo(tsaPolicy, messageImprint,
195: new DERInteger(serialNumber), new DERGeneralizedTime(
196: genTime), accuracy, derOrdering, nonce, tsa,
197: request.getExtensions());
198:
199: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
200: DEROutputStream dOut = new DEROutputStream(bOut);
201:
202: try {
203: CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator();
204:
205: dOut.writeObject(tstInfo);
206:
207: // TODO Check for certsAndCrls != null here?
208:
209: CertStore genCertStore;
210: if (request.getCertReq()) {
211: genCertStore = certsAndCrls;
212: } else {
213: genCertStore = CertStore.getInstance("Collection",
214: new CollectionCertStoreParameters(certsAndCrls
215: .getCRLs(null)));
216: }
217:
218: signedDataGenerator.addCertificatesAndCRLs(genCertStore);
219: signedDataGenerator.addSigner(key, cert, digestOID,
220: signedAttr, unsignedAttr);
221:
222: CMSSignedData signedData = signedDataGenerator.generate(
223: PKCSObjectIdentifiers.id_ct_TSTInfo.getId(),
224: new CMSProcessableByteArray(bOut.toByteArray()),
225: true, provider);
226:
227: return new TimeStampToken(signedData);
228: } catch (CMSException cmsEx) {
229: throw new TSPException("Error generating time-stamp token",
230: cmsEx);
231: } catch (IOException e) {
232: throw new TSPException("Exception encoding info", e);
233: } catch (CertStoreException e) {
234: throw new TSPException("Exception handling CertStore", e);
235: } catch (InvalidAlgorithmParameterException e) {
236: throw new TSPException("Exception handling CertStore CRLs",
237: e);
238: }
239: }
240: }
|