public unsafe IRfc3161TimestampToken SubmitRequest(Uri timestampUri, TimeSpan timeout) { if (timestampUri == null) { throw new ArgumentNullException(nameof(timestampUri)); } if (!timestampUri.IsAbsoluteUri) { throw new ArgumentException("Absolute URI required", nameof(timestampUri)); } if (timestampUri.Scheme != Uri.UriSchemeHttp && timestampUri.Scheme != Uri.UriSchemeHttps) { throw new ArgumentException("HTTP/HTTPS required", nameof(timestampUri)); } IntPtr requestedPolicyPtr = IntPtr.Zero; IntPtr pTsContext = IntPtr.Zero; IntPtr pTsSigner = IntPtr.Zero; IntPtr hStore = IntPtr.Zero; const Rfc3161TimestampWin32.CryptRetrieveTimeStampFlags flags = Rfc3161TimestampWin32.CryptRetrieveTimeStampFlags.TIMESTAMP_VERIFY_CONTEXT_SIGNATURE | Rfc3161TimestampWin32.CryptRetrieveTimeStampFlags.TIMESTAMP_DONT_HASH_DATA; try { requestedPolicyPtr = Marshal.StringToHGlobalAnsi(Data._requestedPolicyId?.Value); Rfc3161TimestampWin32.CRYPT_TIMESTAMP_PARA para = new Rfc3161TimestampWin32.CRYPT_TIMESTAMP_PARA() { fRequestCerts = Data._requestSignerCertificate, pszTSAPolicyId = requestedPolicyPtr, }; if (Data._extensions?.Count > 0) { throw new NotImplementedException(); fixed(byte *pbNonce = Data._nonce) { if (Data._nonce != null) { para.Nonce.cbData = (uint)Data._nonce.Length; para.Nonce.pbData = (IntPtr)pbNonce; } if (!Rfc3161TimestampWin32.CryptRetrieveTimeStamp( timestampUri.AbsoluteUri, flags, (int)timeout.TotalMilliseconds, Data._hashAlgorithm.Value, ref para, Data._hash, Data._hash.Length, ref pTsContext, ref pTsSigner, ref hStore)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } var content = (Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)Marshal.PtrToStructure(pTsContext, typeof(Rfc3161TimestampWin32.CRYPT_TIMESTAMP_CONTEXT)); byte[] encoded = new byte[content.cbEncoded]; Marshal.Copy(content.pbEncoded, encoded, 0, content.cbEncoded); var tstInfo = new Rfc3161TimestampTokenInfoNet472Wrapper(new Rfc3161TimestampTokenInfo(pTsContext)); X509Certificate2 signerCert = new X509Certificate2(pTsSigner); using (X509Store extraCerts = new X509Store(hStore)) { X509Certificate2Collection additionalCertsColl = new X509Certificate2Collection(); foreach (var cert in extraCerts.Certificates) { if (!signerCert.Equals(cert)) { additionalCertsColl.Add(cert); } } return(Rfc3161TimestampTokenFactory.Create( tstInfo, signerCert, additionalCertsColl, encoded)); } } finally { if (hStore != IntPtr.Zero) { Rfc3161TimestampWin32.CertCloseStore(hStore, 0); } if (pTsSigner != IntPtr.Zero) { Rfc3161TimestampWin32.CertFreeCertificateContext(pTsSigner); } if (pTsContext != IntPtr.Zero) { Rfc3161TimestampWin32.CryptMemFree(pTsContext); } if (requestedPolicyPtr != IntPtr.Zero) { Marshal.FreeHGlobal(requestedPolicyPtr); } } }
private static Rfc3161TimestampToken CryptVerifyTimeStampSignature(byte[] encodedToken, byte[] data) { IntPtr pTsContext = IntPtr.Zero; IntPtr pTsSigner = IntPtr.Zero; IntPtr hStore = IntPtr.Zero; try { if (!Rfc3161TimestampWin32.CryptVerifyTimeStampSignature( encodedToken, encodedToken.Length, data, data?.Length ?? 0, IntPtr.Zero, ref pTsContext, ref pTsSigner, ref hStore)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } IRfc3161TimestampTokenInfo tstInfo = new Rfc3161TimestampTokenInfoNet472Wrapper(new Rfc3161TimestampTokenInfo(pTsContext)); X509Certificate2 signerCert = new X509Certificate2(pTsSigner); using (X509Store extraCerts = new X509Store(hStore)) { X509Certificate2Collection additionalCertsColl = new X509Certificate2Collection(); foreach (var cert in extraCerts.Certificates) { if (!signerCert.Equals(cert)) { additionalCertsColl.Add(cert); } } return(new Rfc3161TimestampToken( tstInfo, signerCert, additionalCertsColl, (byte[])encodedToken.Clone())); } } finally { if (pTsContext != IntPtr.Zero) { Rfc3161TimestampWin32.CryptMemFree(pTsContext); } if (pTsSigner != IntPtr.Zero) { Rfc3161TimestampWin32.CertFreeCertificateContext(pTsSigner); } if (hStore != IntPtr.Zero) { Rfc3161TimestampWin32.CertCloseStore(hStore, 0); } } }