Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java')
-rw-r--r--pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java380
1 files changed, 380 insertions, 0 deletions
diff --git a/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java b/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java
new file mode 100644
index 00000000..f3783f80
--- /dev/null
+++ b/pkix/src/main/java/org/spongycastle/tsp/TimeStampTokenGenerator.java
@@ -0,0 +1,380 @@
+package org.spongycastle.tsp;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.spongycastle.asn1.ASN1Boolean;
+import org.spongycastle.asn1.ASN1Encoding;
+import org.spongycastle.asn1.ASN1GeneralizedTime;
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.cms.AttributeTable;
+import org.spongycastle.asn1.ess.ESSCertID;
+import org.spongycastle.asn1.ess.ESSCertIDv2;
+import org.spongycastle.asn1.ess.SigningCertificate;
+import org.spongycastle.asn1.ess.SigningCertificateV2;
+import org.spongycastle.asn1.oiw.OIWObjectIdentifiers;
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.tsp.Accuracy;
+import org.spongycastle.asn1.tsp.MessageImprint;
+import org.spongycastle.asn1.tsp.TSTInfo;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.GeneralName;
+import org.spongycastle.asn1.x509.GeneralNames;
+import org.spongycastle.asn1.x509.IssuerSerial;
+import org.spongycastle.cert.X509CertificateHolder;
+import org.spongycastle.cms.CMSAttributeTableGenerationException;
+import org.spongycastle.cms.CMSAttributeTableGenerator;
+import org.spongycastle.cms.CMSException;
+import org.spongycastle.cms.CMSProcessableByteArray;
+import org.spongycastle.cms.CMSSignedData;
+import org.spongycastle.cms.CMSSignedDataGenerator;
+import org.spongycastle.cms.SignerInfoGenerator;
+import org.spongycastle.operator.DigestCalculator;
+import org.spongycastle.util.CollectionStore;
+import org.spongycastle.util.Store;
+
+/**
+ * Currently the class supports ESSCertID by if a digest calculator based on SHA1 is passed in, otherwise it uses
+ * ESSCertIDv2. In the event you need to pass both types, you will need to override the SignedAttributeGenerator
+ * for the SignerInfoGeneratorBuilder you are using. For the default for ESSCertIDv2 the code will look something
+ * like the following:
+ * <pre>
+ * final ESSCertID essCertid = new ESSCertID(certHashSha1, issuerSerial);
+ * final ESSCertIDv2 essCertidV2 = new ESSCertIDv2(certHashSha256, issuerSerial);
+ *
+ * signerInfoGenBuilder.setSignedAttributeGenerator(new CMSAttributeTableGenerator()
+ * {
+ * public AttributeTable getAttributes(Map parameters)
+ * throws CMSAttributeTableGenerationException
+ * {
+ * CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator();
+ *
+ * AttributeTable table = attrGen.getAttributes(parameters);
+ *
+ * table = table.add(PKCSObjectIdentifiers.id_aa_signingCertificate, new SigningCertificate(essCertid));
+ * table = table.add(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new SigningCertificateV2(essCertidV2));
+ *
+ * return table;
+ * }
+ * });
+ * </pre>
+ */
+public class TimeStampTokenGenerator
+{
+ int accuracySeconds = -1;
+
+ int accuracyMillis = -1;
+
+ int accuracyMicros = -1;
+
+ boolean ordering = false;
+
+ GeneralName tsa = null;
+
+ private ASN1ObjectIdentifier tsaPolicyOID;
+
+ private List certs = new ArrayList();
+ private List crls = new ArrayList();
+ private List attrCerts = new ArrayList();
+ private Map otherRevoc = new HashMap();
+ private SignerInfoGenerator signerInfoGen;
+
+ /**
+ * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
+ * the signer's associated certificate using the sha1DigestCalculator. If alternate values are required
+ * for id-aa-signingCertificate they should be added to the signerInfoGen object before it is passed in,
+ * otherwise a standard digest based value will be added.
+ *
+ * @param signerInfoGen the generator for the signer we are using.
+ * @param digestCalculator calculator for to use for digest of certificate.
+ * @param tsaPolicy tasPolicy to send.
+ * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated certificate for the signer,
+ * @throws TSPException if the signer certificate cannot be processed.
+ */
+ public TimeStampTokenGenerator(
+ final SignerInfoGenerator signerInfoGen,
+ DigestCalculator digestCalculator,
+ ASN1ObjectIdentifier tsaPolicy)
+ throws IllegalArgumentException, TSPException
+ {
+ this(signerInfoGen, digestCalculator, tsaPolicy, false);
+ }
+
+ /**
+ * Basic Constructor - set up a calculator based on signerInfoGen with a ESSCertID calculated from
+ * the signer's associated certificate using the sha1DigestCalculator. If alternate values are required
+ * for id-aa-signingCertificate they should be added to the signerInfoGen object before it is passed in,
+ * otherwise a standard digest based value will be added.
+ *
+ * @param signerInfoGen the generator for the signer we are using.
+ * @param digestCalculator calculator for to use for digest of certificate.
+ * @param tsaPolicy tasPolicy to send.
+ * @param isIssuerSerialIncluded should issuerSerial be included in the ESSCertIDs, true if yes, by default false.
+ * @throws IllegalArgumentException if calculator is not SHA-1 or there is no associated certificate for the signer,
+ * @throws TSPException if the signer certificate cannot be processed.
+ */
+ public TimeStampTokenGenerator(
+ final SignerInfoGenerator signerInfoGen,
+ DigestCalculator digestCalculator,
+ ASN1ObjectIdentifier tsaPolicy,
+ boolean isIssuerSerialIncluded)
+ throws IllegalArgumentException, TSPException
+ {
+ this.signerInfoGen = signerInfoGen;
+ this.tsaPolicyOID = tsaPolicy;
+
+ if (!signerInfoGen.hasAssociatedCertificate())
+ {
+ throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate");
+ }
+
+ X509CertificateHolder assocCert = signerInfoGen.getAssociatedCertificate();
+ TSPUtil.validateCertificate(assocCert);
+
+ try
+ {
+ OutputStream dOut = digestCalculator.getOutputStream();
+
+ dOut.write(assocCert.getEncoded());
+
+ dOut.close();
+
+ if (digestCalculator.getAlgorithmIdentifier().getAlgorithm().equals(OIWObjectIdentifiers.idSHA1))
+ {
+ final ESSCertID essCertid = new ESSCertID(digestCalculator.getDigest(),
+ isIssuerSerialIncluded ? new IssuerSerial(new GeneralNames(new GeneralName(assocCert.getIssuer())), assocCert.getSerialNumber())
+ : null);
+
+ this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator()
+ {
+ public AttributeTable getAttributes(Map parameters)
+ throws CMSAttributeTableGenerationException
+ {
+ AttributeTable table = signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);
+
+ if (table.get(PKCSObjectIdentifiers.id_aa_signingCertificate) == null)
+ {
+ return table.add(PKCSObjectIdentifiers.id_aa_signingCertificate, new SigningCertificate(essCertid));
+ }
+
+ return table;
+ }
+ }, signerInfoGen.getUnsignedAttributeTableGenerator());
+ }
+ else
+ {
+ AlgorithmIdentifier digAlgID = new AlgorithmIdentifier(digestCalculator.getAlgorithmIdentifier().getAlgorithm());
+ final ESSCertIDv2 essCertid = new ESSCertIDv2(digAlgID, digestCalculator.getDigest(),
+ isIssuerSerialIncluded ? new IssuerSerial(new GeneralNames(new GeneralName(assocCert.getIssuer())), new ASN1Integer(assocCert.getSerialNumber()))
+ : null);
+
+ this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator()
+ {
+ public AttributeTable getAttributes(Map parameters)
+ throws CMSAttributeTableGenerationException
+ {
+ AttributeTable table = signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters);
+
+ if (table.get(PKCSObjectIdentifiers.id_aa_signingCertificateV2) == null)
+ {
+ return table.add(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new SigningCertificateV2(essCertid));
+ }
+
+ return table;
+ }
+ }, signerInfoGen.getUnsignedAttributeTableGenerator());
+ }
+ }
+ catch (IOException e)
+ {
+ throw new TSPException("Exception processing certificate.", e);
+ }
+ }
+
+ /**
+ * Add the store of X509 Certificates to the generator.
+ *
+ * @param certStore a Store containing X509CertificateHolder objects
+ */
+ public void addCertificates(
+ Store certStore)
+ {
+ certs.addAll(certStore.getMatches(null));
+ }
+
+ /**
+ *
+ * @param crlStore a Store containing X509CRLHolder objects.
+ */
+ public void addCRLs(
+ Store crlStore)
+ {
+ crls.addAll(crlStore.getMatches(null));
+ }
+
+ /**
+ *
+ * @param attrStore a Store containing X509AttributeCertificate objects.
+ */
+ public void addAttributeCertificates(
+ Store attrStore)
+ {
+ attrCerts.addAll(attrStore.getMatches(null));
+ }
+
+ /**
+ * Add a Store of otherRevocationData to the CRL set to be included with the generated TimeStampToken.
+ *
+ * @param otherRevocationInfoFormat the OID specifying the format of the otherRevocationInfo data.
+ * @param otherRevocationInfos a Store of otherRevocationInfo data to add.
+ */
+ public void addOtherRevocationInfo(
+ ASN1ObjectIdentifier otherRevocationInfoFormat,
+ Store otherRevocationInfos)
+ {
+ otherRevoc.put(otherRevocationInfoFormat, otherRevocationInfos.getMatches(null));
+ }
+
+ public void setAccuracySeconds(int accuracySeconds)
+ {
+ this.accuracySeconds = accuracySeconds;
+ }
+
+ public void setAccuracyMillis(int accuracyMillis)
+ {
+ this.accuracyMillis = accuracyMillis;
+ }
+
+ public void setAccuracyMicros(int accuracyMicros)
+ {
+ this.accuracyMicros = accuracyMicros;
+ }
+
+ public void setOrdering(boolean ordering)
+ {
+ this.ordering = ordering;
+ }
+
+ public void setTSA(GeneralName tsa)
+ {
+ this.tsa = tsa;
+ }
+
+ /**
+ * Generate a TimeStampToken for the passed in request and serialNumber marking it with the passed in genTime.
+ *
+ * @param request the originating request.
+ * @param serialNumber serial number for the TimeStampToken
+ * @param genTime token generation time.
+ * @return a TimeStampToken
+ * @throws TSPException
+ */
+ public TimeStampToken generate(
+ TimeStampRequest request,
+ BigInteger serialNumber,
+ Date genTime)
+ throws TSPException
+ {
+ ASN1ObjectIdentifier digestAlgOID = request.getMessageImprintAlgOID();
+
+ AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DERNull.INSTANCE);
+ MessageImprint messageImprint = new MessageImprint(algID, request.getMessageImprintDigest());
+
+ Accuracy accuracy = null;
+ if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
+ {
+ ASN1Integer seconds = null;
+ if (accuracySeconds > 0)
+ {
+ seconds = new ASN1Integer(accuracySeconds);
+ }
+
+ ASN1Integer millis = null;
+ if (accuracyMillis > 0)
+ {
+ millis = new ASN1Integer(accuracyMillis);
+ }
+
+ ASN1Integer micros = null;
+ if (accuracyMicros > 0)
+ {
+ micros = new ASN1Integer(accuracyMicros);
+ }
+
+ accuracy = new Accuracy(seconds, millis, micros);
+ }
+
+ ASN1Boolean derOrdering = null;
+ if (ordering)
+ {
+ derOrdering = new ASN1Boolean(ordering);
+ }
+
+ ASN1Integer nonce = null;
+ if (request.getNonce() != null)
+ {
+ nonce = new ASN1Integer(request.getNonce());
+ }
+
+ ASN1ObjectIdentifier tsaPolicy = tsaPolicyOID;
+ if (request.getReqPolicy() != null)
+ {
+ tsaPolicy = request.getReqPolicy();
+ }
+
+ TSTInfo tstInfo = new TSTInfo(tsaPolicy,
+ messageImprint, new ASN1Integer(serialNumber),
+ new ASN1GeneralizedTime(genTime), accuracy, derOrdering,
+ nonce, tsa, request.getExtensions());
+
+ try
+ {
+ CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator();
+
+ if (request.getCertReq())
+ {
+ // TODO: do we need to check certs non-empty?
+ signedDataGenerator.addCertificates(new CollectionStore(certs));
+ signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts));
+ }
+
+ signedDataGenerator.addCRLs(new CollectionStore(crls));
+
+ if (!otherRevoc.isEmpty())
+ {
+ for (Iterator it = otherRevoc.keySet().iterator(); it.hasNext();)
+ {
+ ASN1ObjectIdentifier format = (ASN1ObjectIdentifier)it.next();
+
+ signedDataGenerator.addOtherRevocationInfo(format, new CollectionStore((Collection)otherRevoc.get(format)));
+ }
+ }
+
+ signedDataGenerator.addSignerInfoGenerator(signerInfoGen);
+
+ byte[] derEncodedTSTInfo = tstInfo.getEncoded(ASN1Encoding.DER);
+
+ CMSSignedData signedData = signedDataGenerator.generate(new CMSProcessableByteArray(PKCSObjectIdentifiers.id_ct_TSTInfo, derEncodedTSTInfo), true);
+
+ return new TimeStampToken(signedData);
+ }
+ catch (CMSException cmsEx)
+ {
+ throw new TSPException("Error generating time-stamp token", cmsEx);
+ }
+ catch (IOException e)
+ {
+ throw new TSPException("Exception encoding info", e);
+ }
+ }
+}