diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-06-01 03:08:23 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-06-01 03:08:23 +0400 |
commit | 9d86fa64cab222f265c18994eab1d7a5db786da7 (patch) | |
tree | d133f3cb8f4f335e38c4ca5d56a32a84dc470c86 /pkix/src/main/jdk1.1/org/bouncycastle/tsp | |
parent | 1f388cb05faef261ab0fc6d3b898d3a32c00e94a (diff) |
other jdk import
Diffstat (limited to 'pkix/src/main/jdk1.1/org/bouncycastle/tsp')
-rw-r--r-- | pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampToken.java | 496 | ||||
-rw-r--r-- | pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampTokenGenerator.java | 472 |
2 files changed, 968 insertions, 0 deletions
diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampToken.java b/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampToken.java new file mode 100644 index 00000000..bc4a631a --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampToken.java @@ -0,0 +1,496 @@ +package org.bouncycastle.tsp; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertStore; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Date; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.cms.IssuerAndSerialNumber; +import org.bouncycastle.asn1.ess.ESSCertID; +import org.bouncycastle.asn1.ess.ESSCertIDv2; +import org.bouncycastle.asn1.ess.SigningCertificate; +import org.bouncycastle.asn1.ess.SigningCertificateV2; +import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.tsp.TSTInfo; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.IssuerSerial; +import org.bouncycastle.asn1.x509.X509Name; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessable; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.SignerId; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationVerifier; +import org.bouncycastle.jce.PrincipalUtil; +import org.bouncycastle.jce.X509Principal; +import org.bouncycastle.operator.DigestCalculator; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.util.Arrays; +import org.bouncycastle.util.Store; + +public class TimeStampToken +{ + CMSSignedData tsToken; + + SignerInformation tsaSignerInfo; + + Date genTime; + + TimeStampTokenInfo tstInfo; + + CertID certID; + + public TimeStampToken(ContentInfo contentInfo) + throws TSPException, IOException + { + this(getSignedData(contentInfo)); + } + + private static CMSSignedData getSignedData(ContentInfo contentInfo) + throws TSPException + { + try + { + return new CMSSignedData(contentInfo); + } + catch (CMSException e) + { + throw new TSPException("TSP parsing error: " + e.getMessage(), e.getCause()); + } + } + + public TimeStampToken(CMSSignedData signedData) + throws TSPException, IOException + { + this.tsToken = signedData; + + if (!this.tsToken.getSignedContentTypeOID().equals(PKCSObjectIdentifiers.id_ct_TSTInfo.getId())) + { + throw new TSPValidationException("ContentInfo object not for a time stamp."); + } + + Collection signers = tsToken.getSignerInfos().getSigners(); + + if (signers.size() != 1) + { + throw new IllegalArgumentException("Time-stamp token signed by " + + signers.size() + + " signers, but it must contain just the TSA signature."); + } + + tsaSignerInfo = (SignerInformation)signers.iterator().next(); + + try + { + CMSProcessable content = tsToken.getSignedContent(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + content.write(bOut); + + ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(bOut.toByteArray())); + + this.tstInfo = new TimeStampTokenInfo(TSTInfo.getInstance(aIn.readObject())); + + Attribute attr = tsaSignerInfo.getSignedAttributes().get(PKCSObjectIdentifiers.id_aa_signingCertificate); + + if (attr != null) + { + SigningCertificate signCert = SigningCertificate.getInstance(attr.getAttrValues().getObjectAt(0)); + + this.certID = new CertID(ESSCertID.getInstance(signCert.getCerts()[0])); + } + else + { + attr = tsaSignerInfo.getSignedAttributes().get(PKCSObjectIdentifiers.id_aa_signingCertificateV2); + + if (attr == null) + { + throw new TSPValidationException("no signing certificate attribute found, time stamp invalid."); + } + + SigningCertificateV2 signCertV2 = SigningCertificateV2.getInstance(attr.getAttrValues().getObjectAt(0)); + + this.certID = new CertID(ESSCertIDv2.getInstance(signCertV2.getCerts()[0])); + } + } + catch (CMSException e) + { + throw new TSPException(e.getMessage(), e.getUnderlyingException()); + } + } + + public TimeStampTokenInfo getTimeStampInfo() + { + return tstInfo; + } + + public SignerId getSID() + { + return tsaSignerInfo.getSID(); + } + + public AttributeTable getSignedAttributes() + { + return tsaSignerInfo.getSignedAttributes(); + } + + public AttributeTable getUnsignedAttributes() + { + return tsaSignerInfo.getUnsignedAttributes(); + } + + /** + * @deprecated use getCertificates() or getCRLs() + */ + public CertStore getCertificatesAndCRLs( + String type, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, CMSException + { + return tsToken.getCertificatesAndCRLs(type, provider); + } + + public Store getCertificates() + { + return tsToken.getCertificates(); + } + + public Store getCRLs() + { + return tsToken.getCRLs(); + } + + public Store getAttributeCertificates() + { + return tsToken.getAttributeCertificates(); + } + + /** + * Validate the time stamp token. + * <p> + * To be valid the token must be signed by the passed in certificate and + * the certificate must be the one referred to by the SigningCertificate + * attribute included in the hashed attributes of the token. The + * certificate must also have the ExtendedKeyUsageExtension with only + * KeyPurposeId.id_kp_timeStamping and have been valid at the time the + * timestamp was created. + * </p> + * <p> + * A successful call to validate means all the above are true. + * </p> + * @deprecated + */ + public void validate( + X509Certificate cert, + String provider) + throws TSPException, TSPValidationException, + CertificateExpiredException, CertificateNotYetValidException, NoSuchProviderException + { + try + { + if (!Arrays.constantTimeAreEqual(certID.getCertHash(), MessageDigest.getInstance(certID.getHashAlgorithmName()).digest(cert.getEncoded()))) + { + throw new TSPValidationException("certificate hash does not match certID hash."); + } + + if (certID.getIssuerSerial() != null) + { + if (!certID.getIssuerSerial().getSerial().getValue().equals(cert.getSerialNumber())) + { + throw new TSPValidationException("certificate serial number does not match certID for signature."); + } + + GeneralName[] names = certID.getIssuerSerial().getIssuer().getNames(); + X509Principal principal = PrincipalUtil.getIssuerX509Principal(cert); + boolean found = false; + + for (int i = 0; i != names.length; i++) + { + if (names[i].getTagNo() == 4 && new X509Principal(X509Name.getInstance(names[i].getName())).equals(principal)) + { + found = true; + break; + } + } + + if (!found) + { + throw new TSPValidationException("certificate name does not match certID for signature. "); + } + } + + TSPUtil.validateCertificate(cert); + + cert.checkValidity(tstInfo.getGenTime()); + + if (!tsaSignerInfo.verify(cert, provider)) + { + throw new TSPValidationException("signature not created by certificate."); + } + } + catch (CMSException e) + { + if (e.getUnderlyingException() != null) + { + throw new TSPException(e.getMessage(), e.getUnderlyingException()); + } + else + { + throw new TSPException("CMS exception: " + e, e); + } + } + catch (NoSuchAlgorithmException e) + { + throw new TSPException("cannot find algorithm: " + e, e); + } + catch (CertificateEncodingException e) + { + throw new TSPException("problem processing certificate: " + e, e); + } + } + + /** + * Validate the time stamp token. + * <p> + * To be valid the token must be signed by the passed in certificate and + * the certificate must be the one referred to by the SigningCertificate + * attribute included in the hashed attributes of the token. The + * certificate must also have the ExtendedKeyUsageExtension with only + * KeyPurposeId.id_kp_timeStamping and have been valid at the time the + * timestamp was created. + * </p> + * <p> + * A successful call to validate means all the above are true. + * </p> + * + * @param sigVerifier the content verifier create the objects required to verify the CMS object in the timestamp. + * @throws TSPException if an exception occurs in processing the token. + * @throws TSPValidationException if the certificate or signature fail to be valid. + * @throws IllegalArgumentException if the sigVerifierProvider has no associated certificate. + */ + public void validate( + SignerInformationVerifier sigVerifier) + throws TSPException, TSPValidationException + { + if (!sigVerifier.hasAssociatedCertificate()) + { + throw new IllegalArgumentException("verifier provider needs an associated certificate"); + } + + try + { + X509CertificateHolder certHolder = sigVerifier.getAssociatedCertificate(); + DigestCalculator calc = sigVerifier.getDigestCalculator(certID.getHashAlgorithm()); + + OutputStream cOut = calc.getOutputStream(); + + cOut.write(certHolder.getEncoded()); + cOut.close(); + + if (!Arrays.constantTimeAreEqual(certID.getCertHash(), calc.getDigest())) + { + throw new TSPValidationException("certificate hash does not match certID hash."); + } + + if (certID.getIssuerSerial() != null) + { + IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(certHolder.toASN1Structure()); + + if (!certID.getIssuerSerial().getSerial().equals(issuerSerial.getSerialNumber())) + { + throw new TSPValidationException("certificate serial number does not match certID for signature."); + } + + GeneralName[] names = certID.getIssuerSerial().getIssuer().getNames(); + boolean found = false; + + for (int i = 0; i != names.length; i++) + { + if (names[i].getTagNo() == 4 && X500Name.getInstance(names[i].getName()).equals(X500Name.getInstance(issuerSerial.getName()))) + { + found = true; + break; + } + } + + if (!found) + { + throw new TSPValidationException("certificate name does not match certID for signature. "); + } + } + + TSPUtil.validateCertificate(certHolder); + + if (!certHolder.isValidOn(tstInfo.getGenTime())) + { + throw new TSPValidationException("certificate not valid when time stamp created."); + } + + if (!tsaSignerInfo.verify(sigVerifier)) + { + throw new TSPValidationException("signature not created by certificate."); + } + } + catch (CMSException e) + { + if (e.getUnderlyingException() != null) + { + throw new TSPException(e.getMessage(), e.getUnderlyingException()); + } + else + { + throw new TSPException("CMS exception: " + e, e); + } + } + catch (IOException e) + { + throw new TSPException("problem processing certificate: " + e, e); + } + catch (OperatorCreationException e) + { + throw new TSPException("unable to create digest: " + e.getMessage(), e); + } + } + + /** + * Return true if the signature on time stamp token is valid. + * <p> + * Note: this is a much weaker proof of correctness than calling validate(). + * </p> + * + * @param sigVerifier the content verifier create the objects required to verify the CMS object in the timestamp. + * @return true if the signature matches, false otherwise. + * @throws TSPException if the signature cannot be processed or the provider cannot match the algorithm. + */ + public boolean isSignatureValid( + SignerInformationVerifier sigVerifier) + throws TSPException + { + try + { + return tsaSignerInfo.verify(sigVerifier); + } + catch (CMSException e) + { + if (e.getUnderlyingException() != null) + { + throw new TSPException(e.getMessage(), e.getUnderlyingException()); + } + else + { + throw new TSPException("CMS exception: " + e, e); + } + } + } + + /** + * Return the underlying CMSSignedData object. + * + * @return the underlying CMS structure. + */ + public CMSSignedData toCMSSignedData() + { + return tsToken; + } + + /** + * Return a ASN.1 encoded byte stream representing the encoded object. + * + * @throws IOException if encoding fails. + */ + public byte[] getEncoded() + throws IOException + { + return tsToken.getEncoded(); + } + + // perhaps this should be done using an interface on the ASN.1 classes... + private class CertID + { + private ESSCertID certID; + private ESSCertIDv2 certIDv2; + + CertID(ESSCertID certID) + { + this.certID = certID; + this.certIDv2 = null; + } + + CertID(ESSCertIDv2 certID) + { + this.certIDv2 = certID; + this.certID = null; + } + + public String getHashAlgorithmName() + { + if (certID != null) + { + return "SHA-1"; + } + else + { + if (NISTObjectIdentifiers.id_sha256.equals(certIDv2.getHashAlgorithm().getAlgorithm())) + { + return "SHA-256"; + } + return certIDv2.getHashAlgorithm().getAlgorithm().getId(); + } + } + + public AlgorithmIdentifier getHashAlgorithm() + { + if (certID != null) + { + return new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1); + } + else + { + return certIDv2.getHashAlgorithm(); + } + } + + public byte[] getCertHash() + { + if (certID != null) + { + return certID.getCertHash(); + } + else + { + return certIDv2.getCertHash(); + } + } + + public IssuerSerial getIssuerSerial() + { + if (certID != null) + { + return certID.getIssuerSerial(); + } + else + { + return certIDv2.getIssuerSerial(); + } + } + } +} diff --git a/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampTokenGenerator.java b/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampTokenGenerator.java new file mode 100644 index 00000000..f3093159 --- /dev/null +++ b/pkix/src/main/jdk1.1/org/bouncycastle/tsp/TimeStampTokenGenerator.java @@ -0,0 +1,472 @@ +package org.bouncycastle.tsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.cert.CRLException; +import java.security.cert.CertStore; +import java.security.cert.CertStoreException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bouncycastle.asn1.ASN1Boolean; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.ASN1GeneralizedTime; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.cms.Attribute; +import org.bouncycastle.asn1.cms.AttributeTable; +import org.bouncycastle.asn1.ess.ESSCertID; +import org.bouncycastle.asn1.ess.SigningCertificate; +import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.bouncycastle.asn1.tsp.Accuracy; +import org.bouncycastle.asn1.tsp.MessageImprint; +import org.bouncycastle.asn1.tsp.TSTInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.cert.jcajce.JcaX509CRLHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; +import org.bouncycastle.cms.CMSAttributeTableGenerationException; +import org.bouncycastle.cms.CMSAttributeTableGenerator; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.bouncycastle.cms.CMSSignedGenerator; +import org.bouncycastle.cms.DefaultSignedAttributeTableGenerator; +import org.bouncycastle.cms.SignerInfoGenerator; +import org.bouncycastle.cms.SimpleAttributeTableGenerator; +import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.bouncycastle.jce.interfaces.GOST3410PrivateKey; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.bouncycastle.util.CollectionStore; +import org.bouncycastle.util.Store; + +public class TimeStampTokenGenerator +{ + int accuracySeconds = -1; + + int accuracyMillis = -1; + + int accuracyMicros = -1; + + boolean ordering = false; + + GeneralName tsa = null; + + private ASN1ObjectIdentifier tsaPolicyOID; + + PrivateKey key; + X509Certificate cert; + String digestOID; + AttributeTable signedAttr; + AttributeTable unsignedAttr; + + private List certs = new ArrayList(); + private List crls = new ArrayList(); + private List attrCerts = new ArrayList(); + private SignerInfoGenerator signerInfoGen; + + /** + * + */ + public TimeStampTokenGenerator( + final SignerInfoGenerator signerInfoGen, + ASN1ObjectIdentifier tsaPolicy) + throws IllegalArgumentException, TSPException + { + this.signerInfoGen = signerInfoGen; + this.tsaPolicyOID = tsaPolicy; + + if (!signerInfoGen.hasAssociatedCertificate()) + { + throw new IllegalArgumentException("SignerInfoGenerator must have an associated certificate"); + } + + TSPUtil.validateCertificate(signerInfoGen.getAssociatedCertificate()); + + try + { + final ESSCertID essCertid = new ESSCertID(MessageDigest.getInstance("SHA-1").digest(signerInfoGen.getAssociatedCertificate().getEncoded())); + + this.signerInfoGen = new SignerInfoGenerator(signerInfoGen, new CMSAttributeTableGenerator() + { + public AttributeTable getAttributes(Map parameters) + throws CMSAttributeTableGenerationException + { + AttributeTable table = signerInfoGen.getSignedAttributeTableGenerator().getAttributes(parameters); + + return table.add(PKCSObjectIdentifiers.id_aa_signingCertificate, new SigningCertificate(essCertid)); + } + }, signerInfoGen.getUnsignedAttributeTableGenerator()); + + } + catch (NoSuchAlgorithmException e) + { + throw new TSPException("Can't find a SHA-1 implementation.", e); + } + catch (IOException e) + { + throw new TSPException("Exception processing certificate.", e); + } + } + + /** + * basic creation - only the default attributes will be included here. + * @deprecated use SignerInfoGenerator constructor + */ + public TimeStampTokenGenerator( + PrivateKey key, + X509Certificate cert, + String digestOID, + String tsaPolicyOID) + throws IllegalArgumentException, TSPException + { + this(key, cert, digestOID, tsaPolicyOID, null, null); + } + + /** + * basic creation - only the default attributes will be included here. + * @deprecated use SignerInfoGenerator constructor + */ + public TimeStampTokenGenerator( + PrivateKey key, + X509Certificate cert, + ASN1ObjectIdentifier digestOID, + String tsaPolicyOID) + throws IllegalArgumentException, TSPException + { + this(key, cert, digestOID.getId(), tsaPolicyOID, null, null); + } + + /** + * create with a signer with extra signed/unsigned attributes. + * @deprecated use SignerInfoGenerator constructor + */ + public TimeStampTokenGenerator( + PrivateKey key, + X509Certificate cert, + String digestOID, + String tsaPolicyOID, + AttributeTable signedAttr, + AttributeTable unsignedAttr) + throws IllegalArgumentException, TSPException + { + this.key = key; + this.cert = cert; + this.digestOID = digestOID; + this.tsaPolicyOID = new ASN1ObjectIdentifier(tsaPolicyOID); + this.unsignedAttr = unsignedAttr; + + // + // add the essCertid + // + Hashtable signedAttrs = null; + + if (signedAttr != null) + { + signedAttrs = signedAttr.toHashtable(); + } + else + { + signedAttrs = new Hashtable(); + } + + + TSPUtil.validateCertificate(cert); + + try + { + ESSCertID essCertid = new ESSCertID(MessageDigest.getInstance("SHA-1").digest(cert.getEncoded())); + signedAttrs.put(PKCSObjectIdentifiers.id_aa_signingCertificate, + new Attribute( + PKCSObjectIdentifiers.id_aa_signingCertificate, + new DERSet(new SigningCertificate(essCertid)))); + } + catch (NoSuchAlgorithmException e) + { + throw new TSPException("Can't find a SHA-1 implementation.", e); + } + catch (CertificateEncodingException e) + { + throw new TSPException("Exception processing certificate.", e); + } + + this.signedAttr = new AttributeTable(signedAttrs); + } + + /** + * @deprecated use addCertificates and addCRLs + * @param certificates + * @throws CertStoreException + * @throws TSPException + */ + public void setCertificatesAndCRLs(CertStore certificates) + throws CertStoreException, TSPException + { + Collection c1 = certificates.getCertificates(null); + + for (Iterator it = c1.iterator(); it.hasNext();) + { + try + { + certs.add(new JcaX509CertificateHolder((X509Certificate)it.next())); + } + catch (CertificateEncodingException e) + { + throw new TSPException("cannot encode certificate: " + e.getMessage(), e); + } + } + + c1 = certificates.getCRLs(null); + + for (Iterator it = c1.iterator(); it.hasNext();) + { + try + { + crls.add(new JcaX509CRLHolder((X509CRL)it.next())); + } + catch (CRLException e) + { + throw new TSPException("cannot encode CRL: " + e.getMessage(), 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)); + } + + 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; + } + + //------------------------------------------------------------------------------ + + public TimeStampToken generate( + TimeStampRequest request, + BigInteger serialNumber, + Date genTime, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, TSPException + { + if (signerInfoGen == null) + { + try + { + JcaSignerInfoGeneratorBuilder sigBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(provider).build()); + + sigBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(signedAttr)); + + if (unsignedAttr != null) + { + sigBuilder.setUnsignedAttributeGenerator(new SimpleAttributeTableGenerator(unsignedAttr)); + } + + signerInfoGen = sigBuilder.build(new JcaContentSignerBuilder(getSigAlgorithm(key, digestOID)).setProvider(provider).build(key), cert); + } + catch (OperatorCreationException e) + { + throw new TSPException("Error generating signing operator", e); + } + catch (CertificateEncodingException e) + { + throw new TSPException("Error encoding certificate", e); + } + } + + return generate(request, serialNumber, genTime); + } + + public TimeStampToken generate( + TimeStampRequest request, + BigInteger serialNumber, + Date genTime) + throws TSPException + { + if (signerInfoGen == null) + { + throw new IllegalStateException("can only use this method with SignerInfoGenerator constructor"); + } + + ASN1ObjectIdentifier digestAlgOID = request.getMessageImprintAlgOID(); + + AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, new DERNull()); + 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.addCRLs(new CollectionStore(crls)); + signedDataGenerator.addAttributeCertificates(new CollectionStore(attrCerts)); + } + else + { + signedDataGenerator.addCRLs(new CollectionStore(crls)); + } + + 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); + } + } + + private String getSigAlgorithm( + PrivateKey key, + String digestOID) + { + String enc = null; + + if (key instanceof RSAPrivateKey || "RSA".equalsIgnoreCase(key.getAlgorithm())) + { + enc = "RSA"; + } + else if (key instanceof DSAPrivateKey || "DSA".equalsIgnoreCase(key.getAlgorithm())) + { + enc = "DSA"; + } + else if ("ECDSA".equalsIgnoreCase(key.getAlgorithm()) || "EC".equalsIgnoreCase(key.getAlgorithm())) + { + enc = "ECDSA"; + } + else if (key instanceof GOST3410PrivateKey || "GOST3410".equalsIgnoreCase(key.getAlgorithm())) + { + enc = "GOST3410"; + } + else if ("ECGOST3410".equalsIgnoreCase(key.getAlgorithm())) + { + enc = CMSSignedGenerator.ENCRYPTION_ECGOST3410; + } + + return TSPUtil.getDigestAlgName(digestOID) + "with" + enc; + } +} |