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

TimeStampToken

public class TimeStampToken
using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Cms; using Org.BouncyCastle.Asn1.Ess; using Org.BouncyCastle.Asn1.Nist; 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.Security; using Org.BouncyCastle.Security.Certificates; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; using Org.BouncyCastle.X509; using System; using System.Collections.Generic; using System.IO; namespace Org.BouncyCastle.Tsp { public class TimeStampToken { private class CertID { private EssCertID certID; private EssCertIDv2 certIDv2; public IssuerSerial IssuerSerial { get { if (certID == null) return certIDv2.IssuerSerial; return certID.IssuerSerial; } } internal CertID(EssCertID certID) { this.certID = certID; certIDv2 = null; } internal CertID(EssCertIDv2 certID) { certIDv2 = certID; this.certID = null; } public string GetHashAlgorithmName() { if (certID != null) return "SHA-1"; if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.Algorithm)) return "SHA-256"; return certIDv2.HashAlgorithm.Algorithm.Id; } public AlgorithmIdentifier GetHashAlgorithm() { if (certID == null) return certIDv2.HashAlgorithm; return new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1); } public byte[] GetCertHash() { if (certID == null) return certIDv2.GetCertHash(); return certID.GetCertHash(); } } private readonly CmsSignedData tsToken; private readonly SignerInformation tsaSignerInfo; private readonly TimeStampTokenInfo tstInfo; private readonly CertID certID; public TimeStampTokenInfo TimeStampInfo => tstInfo; public SignerID SignerID => tsaSignerInfo.SignerID; public Org.BouncyCastle.Asn1.Cms.AttributeTable SignedAttributes => tsaSignerInfo.SignedAttributes; public Org.BouncyCastle.Asn1.Cms.AttributeTable UnsignedAttributes => tsaSignerInfo.UnsignedAttributes; public TimeStampToken(Org.BouncyCastle.Asn1.Cms.ContentInfo contentInfo) : this(new CmsSignedData(contentInfo)) { } public TimeStampToken(CmsSignedData signedData) { tsToken = signedData; if (!tsToken.SignedContentType.Equals(PkcsObjectIdentifiers.IdCTTstInfo)) throw new TspValidationException("ContentInfo object not for a time stamp."); IList<SignerInformation> signers = tsToken.GetSignerInfos().GetSigners(); if (signers.Count != 1) throw new ArgumentException("Time-stamp token signed by " + signers.Count.ToString() + " signers, but it must contain just the TSA signature."); IEnumerator<SignerInformation> enumerator = signers.GetEnumerator(); enumerator.MoveNext(); tsaSignerInfo = enumerator.Current; try { CmsProcessable signedContent = tsToken.SignedContent; MemoryStream memoryStream = new MemoryStream(); signedContent.Write(memoryStream); tstInfo = new TimeStampTokenInfo(TstInfo.GetInstance(Asn1Object.FromByteArray(memoryStream.ToArray()))); Org.BouncyCastle.Asn1.Cms.Attribute attribute = tsaSignerInfo.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificate]; if (attribute != null) { if (attribute.AttrValues[0] is SigningCertificateV2) { SigningCertificateV2 instance = SigningCertificateV2.GetInstance(attribute.AttrValues[0]); certID = new CertID(EssCertIDv2.GetInstance(instance.GetCerts()[0])); } else { SigningCertificate instance2 = SigningCertificate.GetInstance(attribute.AttrValues[0]); certID = new CertID(EssCertID.GetInstance(instance2.GetCerts()[0])); } } else { attribute = tsaSignerInfo.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2]; if (attribute == null) throw new TspValidationException("no signing certificate attribute found, time stamp invalid."); SigningCertificateV2 instance3 = SigningCertificateV2.GetInstance(attribute.AttrValues[0]); certID = new CertID(EssCertIDv2.GetInstance(instance3.GetCerts()[0])); } } catch (CmsException ex) { throw new TspException(ex.Message, ex.InnerException); } } public IStore<X509V2AttributeCertificate> GetAttributeCertificates() { return tsToken.GetAttributeCertificates(); } public IStore<X509Certificate> GetCertificates() { return tsToken.GetCertificates(); } public IStore<X509Crl> GetCrls() { return tsToken.GetCrls(); } public void Validate(X509Certificate cert) { try { byte[] b = DigestUtilities.CalculateDigest(certID.GetHashAlgorithmName(), cert.GetEncoded()); if (!Arrays.FixedTimeEquals(certID.GetCertHash(), b)) throw new TspValidationException("certificate hash does not match certID hash."); IssuerSerial issuerSerial = certID.IssuerSerial; if (issuerSerial != null) { if (!issuerSerial.Serial.HasValue(cert.SerialNumber)) throw new TspValidationException("certificate serial number does not match certID for signature."); GeneralName[] names = certID.IssuerSerial.Issuer.GetNames(); X509Name issuerDN = cert.IssuerDN; bool flag = false; for (int i = 0; i != names.Length; i++) { if (names[i].TagNo == 4 && X509Name.GetInstance(names[i].Name).Equivalent(issuerDN)) { flag = true; break; } } if (!flag) throw new TspValidationException("certificate name does not match certID for signature. "); } TspUtil.ValidateCertificate(cert); cert.CheckValidity(tstInfo.GenTime); if (!tsaSignerInfo.Verify(cert)) throw new TspValidationException("signature not created by certificate."); } catch (CmsException ex) { if (ex.InnerException != null) throw new TspException(ex.Message, ex.InnerException); throw new TspException("CMS exception: " + ex?.ToString(), ex); } catch (CertificateEncodingException ex2) { throw new TspException("problem processing certificate: " + ex2?.ToString(), ex2); } catch (SecurityUtilityException ex3) { throw new TspException("cannot find algorithm: " + ex3.Message, ex3); } } public CmsSignedData ToCmsSignedData() { return tsToken; } public byte[] GetEncoded() { return tsToken.GetEncoded("DL"); } public byte[] GetEncoded(string encoding) { return tsToken.GetEncoded(encoding); } } }