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

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; public 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.signedGen.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 essCertID; public TableGen2(SignerInfoGenerator infoGen, EssCertIDv2 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.signedGen.GetAttributes(parameters); if (attributes[PkcsObjectIdentifiers.IdAASigningCertificateV2] == null) return attributes.Add(PkcsObjectIdentifiers.IdAASigningCertificateV2, new SigningCertificateV2(essCertID)); return attributes; } } private int accuracySeconds = -1; private int accuracyMillis = -1; private int accuracyMicros = -1; private bool ordering; private GeneralName tsa; private DerObjectIdentifier 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; tsaPolicyOID = tsaPolicy; X509Certificate certificate = signerInfoGen.certificate; if (certificate == null) throw new ArgumentException("SignerInfoGenerator must have an associated certificate"); X509Certificate x509Certificate = certificate; TspUtil.ValidateCertificate(x509Certificate); DerObjectIdentifier algorithm = ((AlgorithmIdentifier)digestCalculator.AlgorithmDetails).Algorithm; try { DerOctetString certHash = DerOctetString.WithContents(Org.BouncyCastle.X509.X509Utilities.CalculateDigest(digestCalculator, x509Certificate.GetEncoded())); IssuerSerial issuerSerial = null; if (isIssuerSerialIncluded) issuerSerial = new IssuerSerial(new GeneralNames(new GeneralName(x509Certificate.IssuerDN)), x509Certificate.CertificateStructure.SerialNumber); if (OiwObjectIdentifiers.IdSha1.Equals(algorithm)) { EssCertID essCertID = new EssCertID(certHash, issuerSerial); signerInfoGenerator = signerInfoGen.NewBuilder().WithSignedAttributeGenerator(new TableGen(signerInfoGen, essCertID)).Build(signerInfoGen.contentSigner, signerInfoGen.certificate); } else { EssCertIDv2 essCertID2 = new EssCertIDv2(new AlgorithmIdentifier(algorithm), certHash, issuerSerial); signerInfoGenerator = signerInfoGen.NewBuilder().WithSignedAttributeGenerator(new TableGen2(signerInfoGen, essCertID2)).Build(signerInfoGen.contentSigner, 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); return new SignerInfoGeneratorBuilder().WithSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new Org.BouncyCastle.Asn1.Cms.AttributeTable(attrs))).WithUnsignedAttributeGenerator(new SimpleAttributeTableGenerator(unsignedAttr)).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) { MessageImprint messageImprint = new MessageImprint(request.MessageImprintAlgID, request.MessageImprint.HashedMessage); 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 = null; if (request.Nonce != null) nonce = new DerInteger(request.Nonce); DerObjectIdentifier derObjectIdentifier = tsaPolicyOID; if (request.ReqPolicy != null) derObjectIdentifier = new DerObjectIdentifier(request.ReqPolicy); if (derObjectIdentifier != null) { 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(derObjectIdentifier, 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); } } throw new TspValidationException("request contains no policy", 256); } 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 InvalidOperationException(); } } } }