public void Timestamp(Uri timestampingAuthority, string requestedDigestAlgorithmName) { var digestAlgorithmOid = CryptoConfig.MapNameToOID(requestedDigestAlgorithmName); if (digestAlgorithmOid == null) { throw new InvalidOperationException("Unknown digest algorithm: " + requestedDigestAlgorithmName); } // Get the encrypted digest to timestamp byte[] digest; using (var cms = NativeCms.Decode(_signature.Encode(), detached: false)) { digest = cms.GetEncryptedDigest(); } // Request a timestamp and add it to the signature as an unsigned attribute var timestamp = RFC3161.RequestTimestamp(digest, digestAlgorithmOid, timestampingAuthority); // Build the certificate chain locally to ensure we store the whole thing var chain = new X509Chain(); if (!chain.Build(timestamp.SignerInfos[0].Certificate)) { throw new InvalidOperationException("Unable to build certificate chain for timestamp!"); } // Reopen the timestamp as a native cms so we can modify it byte[] rawTimestamp; using (var cms = NativeCms.Decode(timestamp.Encode(), detached: false)) { cms.AddCertificates(chain.ChainElements .Cast <X509ChainElement>() .Where(c => !timestamp.Certificates.Contains(c.Certificate)) .Select(c => c.Certificate.Export(X509ContentType.Cert))); rawTimestamp = cms.Encode(); } // Reopen the signature as a native cms so we can modify it SignedCms newSignature = new SignedCms(); using (var cms = NativeCms.Decode(_signature.Encode(), detached: false)) { cms.AddTimestamp(rawTimestamp); var newSig = cms.Encode(); newSignature.Decode(newSig); } // Reset the signature SetSignature(newSignature); }
private void SetSignature(SignedCms cms) { TrustedSigningTimeUtc = null; Payload = SignaturePayload.Decode(cms.ContentInfo.Content); _signature = cms; // Load the encrypted digest using the native APIs using (var nativeCms = NativeCms.Decode(cms.Encode(), detached: false)) { _encryptedDigest = nativeCms.GetEncryptedDigest(); } var signerInfo = _signature.SignerInfos.Cast <SignerInfo>().FirstOrDefault(); if (signerInfo != null) { Signer = Signer.FromSignerInfo(signerInfo); // Check for a timestamper var attr = signerInfo .UnsignedAttributes .Cast <CryptographicAttributeObject>() .FirstOrDefault(c => c.Oid.Value.Equals(Constants.SignatureTimeStampTokenAttributeOid.Value, StringComparison.OrdinalIgnoreCase)); if (attr != null && attr.Values.Count > 0) { var timestamp = new SignedCms(); timestamp.Decode(attr.Values[0].RawData); // Check the timestamp against the data var token = RFC3161.VerifyTimestamp(_encryptedDigest, timestamp); _timestamp = token; if (_timestamp.IsTrusted) { TrustedSigningTimeUtc = _timestamp.TimestampUtc; } } } }