<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

TimeStampTokenGenerator

using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.Ess; using Org.BouncyCastle.Asn1.Oiw; using Org.BouncyCastle.Asn1.Pkcs; using Org.BouncyCastle.Asn1.Tsp; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Cms; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Operators; using Org.BouncyCastle.Math; using Org.BouncyCastle.Utilities.Collections; using Org.BouncyCastle.Utilities.Date; using Org.BouncyCastle.X509; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Tsp { public class TimeStampTokenGenerator { private class TableGen : CmsAttributeTableGenerator { private readonly SignerInfoGenerator infoGen; private readonly EssCertID essCertID; internal TableGen(SignerInfoGenerator infoGen, EssCertID essCertID) { this.infoGen = infoGen; this.essCertID = essCertID; } public Org.BouncyCastle.Asn1.Cms.AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters) { Org.BouncyCastle.Asn1.Cms.AttributeTable attributes = infoGen.SignedAttributeTableGenerator.GetAttributes(parameters); if (attributes[PkcsObjectIdentifiers.IdAASigningCertificate] == null) return attributes.Add(PkcsObjectIdentifiers.IdAASigningCertificate, new SigningCertificate(essCertID)); return attributes; } } private class TableGen2 : CmsAttributeTableGenerator { private readonly SignerInfoGenerator infoGen; private readonly EssCertIDv2 essCertIDv2; internal TableGen2(SignerInfoGenerator infoGen, EssCertIDv2 essCertIDv2) { this.infoGen = infoGen; this.essCertIDv2 = essCertIDv2; } public Org.BouncyCastle.Asn1.Cms.AttributeTable GetAttributes(IDictionary<CmsAttributeTableParameter, object> parameters) { Org.BouncyCastle.Asn1.Cms.AttributeTable attributes = infoGen.SignedAttributeTableGenerator.GetAttributes(parameters); if (attributes[PkcsObjectIdentifiers.IdAASigningCertificateV2] == null) return attributes.Add(PkcsObjectIdentifiers.IdAASigningCertificateV2, new SigningCertificateV2(essCertIDv2)); return attributes; } } private int accuracySeconds = -1; private int accuracyMillis = -1; private int accuracyMicros = -1; private bool ordering; private GeneralName tsa; private DerObjectIdentifier m_tsaPolicyOid; private IStore<X509Certificate> x509Certs; private IStore<X509Crl> x509Crls; private IStore<X509V2AttributeCertificate> x509AttrCerts; private Dictionary<DerObjectIdentifier, IStore<Asn1Encodable>> otherRevoc = new Dictionary<DerObjectIdentifier, IStore<Asn1Encodable>>(); private SignerInfoGenerator signerInfoGenerator; private Resolution resolution; public Resolution Resolution { get { return resolution; } set { resolution = value; } } public TimeStampTokenGenerator(AsymmetricKeyParameter key, X509Certificate cert, string digestOID, string tsaPolicyOID) : this(key, cert, digestOID, tsaPolicyOID, null, null) { } public TimeStampTokenGenerator(SignerInfoGenerator signerInfoGen, IDigestFactory digestCalculator, DerObjectIdentifier tsaPolicy, bool isIssuerSerialIncluded) { signerInfoGenerator = signerInfoGen; m_tsaPolicyOid = tsaPolicy; X509Certificate certificate = signerInfoGen.Certificate; if (certificate == null) throw new ArgumentException("SignerInfoGenerator must have an associated certificate"); X509Certificate x509Certificate = certificate; TspUtil.ValidateCertificate(x509Certificate); AlgorithmIdentifier algorithmIdentifier = (AlgorithmIdentifier)digestCalculator.AlgorithmDetails; DerObjectIdentifier algorithm = algorithmIdentifier.Algorithm; try { DerOctetString certHash = DerOctetString.WithContents(Org.BouncyCastle.X509.X509Utilities.CalculateDigest(digestCalculator, x509Certificate.GetEncoded())); IssuerSerial issuerSerial = isIssuerSerialIncluded ? Org.BouncyCastle.X509.X509Utilities.CreateIssuerSerial(x509Certificate) : null; CmsAttributeTableGenerator signedGen; if (OiwObjectIdentifiers.IdSha1.Equals(algorithm)) signedGen = new TableGen(signerInfoGen, new EssCertID(certHash, issuerSerial)); else { algorithmIdentifier = new AlgorithmIdentifier(algorithm); signedGen = new TableGen2(signerInfoGen, new EssCertIDv2(algorithmIdentifier, certHash, issuerSerial)); } signerInfoGenerator = signerInfoGen.NewBuilder().WithSignedAttributeGenerator(signedGen).Build(signerInfoGen.SignatureFactory, signerInfoGen.Certificate); } catch (Exception innerException) { throw new TspException("Exception processing certificate", innerException); } } public TimeStampTokenGenerator(AsymmetricKeyParameter key, X509Certificate cert, string digestOID, string tsaPolicyOID, Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttr, Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttr) : this(MakeInfoGenerator(key, cert, new DerObjectIdentifier(digestOID), signedAttr, unsignedAttr), Asn1DigestFactory.Get(OiwObjectIdentifiers.IdSha1), (tsaPolicyOID != null) ? new DerObjectIdentifier(tsaPolicyOID) : null, false) { } internal static SignerInfoGenerator MakeInfoGenerator(AsymmetricKeyParameter key, X509Certificate cert, DerObjectIdentifier digestOid, Org.BouncyCastle.Asn1.Cms.AttributeTable signedAttr, Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAttr) { TspUtil.ValidateCertificate(cert); IDictionary<DerObjectIdentifier, object> attrs = (signedAttr == null) ? new Dictionary<DerObjectIdentifier, object>() : signedAttr.ToDictionary(); string digestAlgName = CmsSignedHelper.GetDigestAlgName(digestOid); DerObjectIdentifier encOid = CmsSignedHelper.GetEncOid(key, digestOid.Id); Asn1SignatureFactory contentSigner = new Asn1SignatureFactory(digestAlgName + "with" + CmsSignedHelper.GetEncryptionAlgName(encOid), key); DefaultSignedAttributeTableGenerator signedGen = new DefaultSignedAttributeTableGenerator(new Org.BouncyCastle.Asn1.Cms.AttributeTable(attrs)); SimpleAttributeTableGenerator unsignedGen = new SimpleAttributeTableGenerator(unsignedAttr); return new SignerInfoGeneratorBuilder().WithSignedAttributeGenerator(signedGen).WithUnsignedAttributeGenerator(unsignedGen).Build(contentSigner, cert); } public void SetAttributeCertificates(IStore<X509V2AttributeCertificate> attributeCertificates) { x509AttrCerts = attributeCertificates; } public void SetCertificates(IStore<X509Certificate> certificates) { x509Certs = certificates; } public void SetCrls(IStore<X509Crl> crls) { x509Crls = crls; } public void AddOtherRevocationInfos(DerObjectIdentifier otherRevInfoFormat, IStore<Asn1Encodable> otherRevInfoStore) { otherRevoc[otherRevInfoFormat] = otherRevInfoStore; } 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(bool ordering) { this.ordering = ordering; } public void SetTsa(GeneralName tsa) { this.tsa = tsa; } public TimeStampToken Generate(TimeStampRequest request, BigInteger serialNumber, DateTime genTime) { return Generate(request, serialNumber, genTime, null); } public TimeStampToken Generate(TimeStampRequest request, BigInteger serialNumber, DateTime genTime, X509Extensions additionalExtensions) { TimeStampReq timeStampReq = request.TimeStampReq; MessageImprint messageImprint = timeStampReq.MessageImprint; Accuracy accuracy = null; if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0) { DerInteger seconds = null; if (accuracySeconds > 0) seconds = new DerInteger(accuracySeconds); DerInteger millis = null; if (accuracyMillis > 0) millis = new DerInteger(accuracyMillis); DerInteger micros = null; if (accuracyMicros > 0) micros = new DerInteger(accuracyMicros); accuracy = new Accuracy(seconds, millis, micros); } DerBoolean derBoolean = null; if (ordering) derBoolean = DerBoolean.GetInstance(ordering); DerInteger nonce = timeStampReq.Nonce; object derObjectIdentifier = timeStampReq.ReqPolicy; if (derObjectIdentifier == null) { derObjectIdentifier = m_tsaPolicyOid; if (derObjectIdentifier == null) throw new TspValidationException("request contains no policy", 256); } DerObjectIdentifier tsaPolicyId = (DerObjectIdentifier)derObjectIdentifier; X509Extensions x509Extensions = request.Extensions; if (additionalExtensions != null) { X509ExtensionsGenerator x509ExtensionsGenerator = new X509ExtensionsGenerator(); if (x509Extensions != null) { foreach (DerObjectIdentifier extensionOid in x509Extensions.ExtensionOids) { x509ExtensionsGenerator.AddExtension(extensionOid, x509Extensions.GetExtension(extensionOid)); } } foreach (DerObjectIdentifier extensionOid2 in additionalExtensions.ExtensionOids) { x509ExtensionsGenerator.AddExtension(extensionOid2, additionalExtensions.GetExtension(extensionOid2)); } x509Extensions = x509ExtensionsGenerator.Generate(); } DerGeneralizedTime genTime2 = new DerGeneralizedTime(WithResolution(genTime, resolution)); TstInfo tstInfo = new TstInfo(tsaPolicyId, messageImprint, new DerInteger(serialNumber), genTime2, accuracy, derBoolean, nonce, tsa, x509Extensions); try { CmsSignedDataGenerator cmsSignedDataGenerator = new CmsSignedDataGenerator(); byte[] derEncoded = tstInfo.GetDerEncoded(); if (request.CertReq) { cmsSignedDataGenerator.AddCertificates(x509Certs); cmsSignedDataGenerator.AddAttributeCertificates(x509AttrCerts); } cmsSignedDataGenerator.AddCrls(x509Crls); foreach (KeyValuePair<DerObjectIdentifier, IStore<Asn1Encodable>> item in otherRevoc) { cmsSignedDataGenerator.AddOtherRevocationInfos(item.Key, item.Value); } cmsSignedDataGenerator.AddSignerInfoGenerator(signerInfoGenerator); return new TimeStampToken(cmsSignedDataGenerator.Generate(PkcsObjectIdentifiers.IdCTTstInfo.Id, new CmsProcessableByteArray(derEncoded), true)); } catch (CmsException innerException) { throw new TspException("Error generating time-stamp token", innerException); } catch (IOException innerException2) { throw new TspException("Exception encoding info", innerException2); } } private static DateTime WithResolution(DateTime dateTime, Resolution resolution) { switch (resolution) { case Resolution.R_SECONDS: return DateTimeUtilities.WithPrecisionSecond(dateTime); case Resolution.R_TENTHS_OF_SECONDS: return DateTimeUtilities.WithPrecisionDecisecond(dateTime); case Resolution.R_HUNDREDTHS_OF_SECONDS: return DateTimeUtilities.WithPrecisionCentisecond(dateTime); case Resolution.R_MILLISECONDS: return DateTimeUtilities.WithPrecisionMillisecond(dateTime); default: throw new ArgumentException("Invalid enum value", "resolution"); } } } }