1
package org.bouncycastle.tsp;
3
import java.io.IOException;
4
import java.math.BigInteger;
5
import java.security.MessageDigest;
6
import java.security.NoSuchAlgorithmException;
7
import java.security.NoSuchProviderException;
8
import java.security.PrivateKey;
9
import java.security.cert.CRLException;
10
import java.security.cert.CertStore;
11
import java.security.cert.CertStoreException;
12
import java.security.cert.CertificateEncodingException;
13
import java.security.cert.X509CRL;
14
import java.security.cert.X509Certificate;
15
import java.security.interfaces.DSAPrivateKey;
16
import java.security.interfaces.RSAPrivateKey;
17
import java.util.ArrayList;
18
import java.util.Collection;
19
import java.util.Date;
20
import java.util.Hashtable;
21
import java.util.Iterator;
22
import java.util.List;
25
import org.bouncycastle.asn1.ASN1Encodable;
26
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
27
import org.bouncycastle.asn1.DERBoolean;
28
import org.bouncycastle.asn1.DERGeneralizedTime;
29
import org.bouncycastle.asn1.DERInteger;
30
import org.bouncycastle.asn1.DERNull;
31
import org.bouncycastle.asn1.DERSet;
32
import org.bouncycastle.asn1.cms.Attribute;
33
import org.bouncycastle.asn1.cms.AttributeTable;
34
import org.bouncycastle.asn1.ess.ESSCertID;
35
import org.bouncycastle.asn1.ess.SigningCertificate;
36
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
37
import org.bouncycastle.asn1.tsp.Accuracy;
38
import org.bouncycastle.asn1.tsp.MessageImprint;
39
import org.bouncycastle.asn1.tsp.TSTInfo;
40
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
41
import org.bouncycastle.asn1.x509.GeneralName;
42
import org.bouncycastle.cert.jcajce.JcaX509CRLHolder;
43
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
44
import org.bouncycastle.cms.CMSAttributeTableGenerationException;
45
import org.bouncycastle.cms.CMSAttributeTableGenerator;
46
import org.bouncycastle.cms.CMSException;
47
import org.bouncycastle.cms.CMSProcessableByteArray;
48
import org.bouncycastle.cms.CMSSignedData;
49
import org.bouncycastle.cms.CMSSignedDataGenerator;
50
import org.bouncycastle.cms.CMSSignedGenerator;
51
import org.bouncycastle.cms.DefaultSignedAttributeTableGenerator;
52
import org.bouncycastle.cms.SignerInfoGenerator;
53
import org.bouncycastle.cms.SimpleAttributeTableGenerator;
54
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
55
import org.bouncycastle.jce.interfaces.GOST3410PrivateKey;
56
import org.bouncycastle.operator.OperatorCreationException;
57
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
58
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
59
import org.bouncycastle.util.CollectionStore;
60
import org.bouncycastle.util.Store;
62
public class TimeStampTokenGenerator
64
int accuracySeconds = -1;
66
int accuracyMillis = -1;
68
int accuracyMicros = -1;
70
boolean ordering = false;
72
GeneralName tsa = null;
74
private String tsaPolicyOID;
79
AttributeTable signedAttr;
80
AttributeTable unsignedAttr;
81
CertStore certsAndCrls;
83
private List certs = new ArrayList();
84
private List crls = new ArrayList();
85
private List attrCerts = new ArrayList();
86
private SignerInfoGenerator signerInfoGen;
91
public TimeStampTokenGenerator(
92
final SignerInfoGenerator signerInfoGen,
93
ASN1ObjectIdentifier tsaPolicy)
94
throws IllegalArgumentException, TSPException
96
this.signerInfoGen = signerInfoGen;
97
this.tsaPolicyOID = tsaPolicy.getId();
99
if (!signerInfoGen.hasAssociatedCertificate())
101
throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
104
TSPUtil.validateCertificate(signerInfoGen.getAssociatedCertificate());
108
final ESSCertID essCertid = new ESSCertID(MessageDigest.getInstance("SHA-1").digest(signerInfoGen.getAssociatedCertificate().getEncoded()));
110
this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator()
112
public AttributeTable getAttributes(Map parameters)
113
throws CMSAttributeTableGenerationException
115
AttributeTable table = signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);
117
return table.add(PKCSObjectIdentifiers.id_aa_signingCertificate, new SigningCertificate(essCertid));
119
}, signerInfoGen.getUnsignedAttributeTableGenerator());
122
catch (NoSuchAlgorithmException e)
124
throw new TSPException("Can't find a SHA-1 implementation.", e);
126
catch (IOException e)
128
throw new TSPException("Exception processing certificate.", e);
133
* basic creation - only the default attributes will be included here.
134
* @deprecated use SignerInfoGenerator constructor
136
public TimeStampTokenGenerator(
138
X509Certificate cert,
141
throws IllegalArgumentException, TSPException
143
this(key, cert, digestOID, tsaPolicyOID, null, null);
147
* create with a signer with extra signed/unsigned attributes.
148
* @deprecated use SignerInfoGenerator constructor
150
public TimeStampTokenGenerator(
152
X509Certificate cert,
155
AttributeTable signedAttr,
156
AttributeTable unsignedAttr)
157
throws IllegalArgumentException, TSPException
161
this.digestOID = digestOID;
162
this.tsaPolicyOID = tsaPolicyOID;
163
this.unsignedAttr = unsignedAttr;
168
Hashtable signedAttrs = null;
170
if (signedAttr != null)
172
signedAttrs = signedAttr.toHashtable();
176
signedAttrs = new Hashtable();
180
TSPUtil.validateCertificate(cert);
184
ESSCertID essCertid = new ESSCertID(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded()));
185
signedAttrs.put(PKCSObjectIdentifiers.id_aa_signingCertificate,
187
PKCSObjectIdentifiers.id_aa_signingCertificate,
188
new DERSet(new SigningCertificate(essCertid))));
190
catch (NoSuchAlgorithmException e)
192
throw new TSPException("Can't find a SHA-1 implementation.", e);
194
catch (CertificateEncodingException e)
196
throw new TSPException("Exception processing certificate.", e);
199
this.signedAttr = new AttributeTable(signedAttrs);
203
* @deprecated use addCertificates and addCRLs
204
* @param certificates
205
* @throws CertStoreException
206
* @throws TSPException
208
public void setCertificatesAndCRLs(CertStore certificates)
209
throws CertStoreException, TSPException
211
Collection c1 = certificates.getCertificates(null);
213
for (Iterator it = c1.iterator(); it.hasNext();)
217
certs.add(new JcaX509CertificateHolder((X509Certificate)it.next()));
219
catch (CertificateEncodingException e)
221
throw new TSPException("cannot encode certificate: " + e.getMessage(), e);
225
c1 = certificates.getCRLs(null);
227
for (Iterator it = c1.iterator(); it.hasNext();)
231
crls.add(new JcaX509CRLHolder((X509CRL)it.next()));
233
catch (CRLException e)
235
throw new TSPException("cannot encode CRL: " + e.getMessage(), e);
241
* Add the store of X509 Certificates to the generator.
243
* @param certStore a Store containing X509CertificateHolder objects
245
public void addCertificates(
248
certs.addAll(certStore.getMatches(null));
253
* @param crlStore a Store containing X509CRLHolder objects.
258
crls.addAll(crlStore.getMatches(null));
263
* @param attrStore a Store containing X509AttributeCertificate objects.
265
public void addAttributeCertificates(
268
attrCerts.addAll(attrStore.getMatches(null));
271
public void setAccuracySeconds(int accuracySeconds)
273
this.accuracySeconds = accuracySeconds;
276
public void setAccuracyMillis(int accuracyMillis)
278
this.accuracyMillis = accuracyMillis;
281
public void setAccuracyMicros(int accuracyMicros)
283
this.accuracyMicros = accuracyMicros;
286
public void setOrdering(boolean ordering)
288
this.ordering = ordering;
291
public void setTSA(GeneralName tsa)
296
//------------------------------------------------------------------------------
298
public TimeStampToken generate(
299
TimeStampRequest request,
300
BigInteger serialNumber,
303
throws NoSuchAlgorithmException, NoSuchProviderException, TSPException
305
if (signerInfoGen == null)
309
JcaSignerInfoGeneratorBuilder sigBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(provider).build());
311
sigBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(signedAttr));
313
if (unsignedAttr != null)
315
sigBuilder.setUnsignedAttributeGenerator(new SimpleAttributeTableGenerator(unsignedAttr));
318
signerInfoGen = sigBuilder.build(new JcaContentSignerBuilder(getSigAlgorithm(key, digestOID)).setProvider(provider).build(key), cert);
320
catch (OperatorCreationException e)
322
throw new TSPException("Error generating signing operator", e);
324
catch (CertificateEncodingException e)
326
throw new TSPException("Error encoding certificate", e);
330
return generate(request, serialNumber, genTime);
333
public TimeStampToken generate(
334
TimeStampRequest request,
335
BigInteger serialNumber,
339
if (signerInfoGen == null)
341
throw new IllegalStateException("can only use this method with SignerInfoGenerator constructor");
344
ASN1ObjectIdentifier digestAlgOID = new ASN1ObjectIdentifier(request.getMessageImprintAlgOID());
346
AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, new DERNull());
347
MessageImprint messageImprint = new MessageImprint(algID, request.getMessageImprintDigest());
349
Accuracy accuracy = null;
350
if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
352
DERInteger seconds = null;
353
if (accuracySeconds > 0)
355
seconds = new DERInteger(accuracySeconds);
358
DERInteger millis = null;
359
if (accuracyMillis > 0)
361
millis = new DERInteger(accuracyMillis);
364
DERInteger micros = null;
365
if (accuracyMicros > 0)
367
micros = new DERInteger(accuracyMicros);
370
accuracy = new Accuracy(seconds, millis, micros);
373
DERBoolean derOrdering = null;
376
derOrdering = new DERBoolean(ordering);
379
DERInteger nonce = null;
380
if (request.getNonce() != null)
382
nonce = new DERInteger(request.getNonce());
385
ASN1ObjectIdentifier tsaPolicy = new ASN1ObjectIdentifier(tsaPolicyOID);
386
if (request.getReqPolicy() != null)
388
tsaPolicy = new ASN1ObjectIdentifier(request.getReqPolicy());
391
TSTInfo tstInfo = new TSTInfo(tsaPolicy,
392
messageImprint, new DERInteger(serialNumber),
393
new DERGeneralizedTime(genTime), accuracy, derOrdering,
394
nonce, tsa, request.getExtensions());
398
CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator();
400
if (request.getCertReq())
402
// TODO: do we need to check certs non-empty?
403
signedDataGenerator.addCertificates(new CollectionStore(certs));
404
signedDataGenerator.addCRLs(new CollectionStore(crls));
405
signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts));
409
signedDataGenerator.addCRLs(new CollectionStore(crls));
412
signedDataGenerator.addSignerInfoGenerator(signerInfoGen);
414
byte[] derEncodedTSTInfo = tstInfo.getEncoded(ASN1Encodable.DER);
416
CMSSignedData signedData = signedDataGenerator.generate(new CMSProcessableByteArray(PKCSObjectIdentifiers.id_ct_TSTInfo, derEncodedTSTInfo), true);
418
return new TimeStampToken(signedData);
420
catch (CMSException cmsEx)
422
throw new TSPException("Error generating time-stamp token", cmsEx);
424
catch (IOException e)
426
throw new TSPException("Exception encoding info", e);
430
private String getSigAlgorithm(
436
if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm()))
440
else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm()))
444
else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm()))
448
else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm()))
452
else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm()))
454
enc = CMSSignedGenerator.ENCRYPTION_ECGOST3410;
457
return TSPUtil.getDigestAlgName(digestOID) + "with" + enc;