/// <summary> /// SignedCms containing a time stamp authority token reponse /// </summary> /// <param name="timestampCms">SignedCms from Time Stamp Authority</param> public Timestamp(SignedCms timestampCms) { SignedCms = timestampCms ?? throw new ArgumentNullException(nameof(timestampCms)); if (Rfc3161TimestampVerificationUtility.TryReadTSTInfoFromSignedCms(timestampCms, out var tstInfo)) { try { SignedCms.CheckSignature(verifySignatureOnly: true); } catch (Exception ex) { throw new TimestampException(NuGetLogCode.NU3021, Strings.VerifyError_TimestampSignatureValidationFailed, ex); } TstInfo = tstInfo; GeneralizedTime = tstInfo.Timestamp; var accuracyInMilliseconds = Rfc3161TimestampVerificationUtility.GetAccuracyInMilliseconds(tstInfo); UpperLimit = tstInfo.Timestamp.AddMilliseconds(accuracyInMilliseconds); LowerLimit = tstInfo.Timestamp.AddMilliseconds(-accuracyInMilliseconds); } else { throw new TimestampException(NuGetLogCode.NU3021, Strings.VerifyError_TimestampSignatureValidationFailed); } }
internal static double GetAccuracyInMilliseconds(Rfc3161TimestampTokenInfo tstInfo) { double accuracyInMilliseconds; if (!tstInfo.AccuracyInMicroseconds.HasValue) { if (StringComparer.Ordinal.Equals(tstInfo.PolicyId, Oids.BaselineTimestampPolicy)) { accuracyInMilliseconds = 1000; } else { accuracyInMilliseconds = 0; } } else { accuracyInMilliseconds = tstInfo.AccuracyInMicroseconds.Value * _millisecondsPerMicrosecond; } if (accuracyInMilliseconds < 0) { throw new InvalidDataException(Strings.TimestampInvalid); } return(accuracyInMilliseconds); }
public Rfc3161TimestampRequest( byte[] messageHash, HashAlgorithmName hashAlgorithm, Oid requestedPolicyId = null, byte[] nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) { if (messageHash == null) { throw new ArgumentNullException(nameof(messageHash)); } int expectedSize; string algorithmIdentifier; if (!ResolveAlgorithm(hashAlgorithm, out expectedSize, out algorithmIdentifier)) { throw new ArgumentOutOfRangeException( nameof(hashAlgorithm), hashAlgorithm, "Hash algorithm is not supported by this method"); } if (messageHash.Length != expectedSize) { throw new ArgumentException("Hash is not the correct size for the identified algorithm", nameof(messageHash)); } if (requestedPolicyId != null && !Rfc3161TimestampUtils.IsLegalOid(requestedPolicyId.Value)) { throw new ArgumentException("Value is not a legal object identifier", nameof(requestedPolicyId)); } if (nonce != null && nonce.Length == 0) { throw new ArgumentException("Nonce must be null or non-empty", nameof(nonce)); } var data = new DataType { _version = 1, _hash = (byte[])messageHash.Clone(), _hashAlgorithm = OpportunisticOid(algorithmIdentifier), _nonce = (byte[])nonce?.Clone(), _requestSignerCertificate = requestSignerCertificates, _extensions = Rfc3161TimestampTokenInfo.ShallowCopy(extensions, preserveNull: true), }; if (requestedPolicyId != null) { data._requestedPolicyId = new Oid(requestedPolicyId.Value, requestedPolicyId.FriendlyName); } RawData = Encode(data); }
internal static bool TryReadTSTInfoFromSignedCms( SignedCms timestampCms, out Rfc3161TimestampTokenInfo tstInfo) { tstInfo = null; if (timestampCms.ContentInfo.ContentType.Value.Equals(Oids.TSTInfoContentType)) { tstInfo = new Rfc3161TimestampTokenInfo(timestampCms.ContentInfo.Content); return(true); } // return false if the signedCms object does not contain the right ContentType return(false); }
public Rfc3161TimestampRequest( byte[] messageHash, Oid hashAlgorithmId, Oid requestedPolicyId = null, byte[] nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) { if (messageHash == null) { throw new ArgumentNullException(nameof(messageHash)); } if (hashAlgorithmId == null) { throw new ArgumentNullException(nameof(hashAlgorithmId)); } if (!Rfc3161TimestampUtils.IsLegalOid(hashAlgorithmId.Value)) { throw new ArgumentException("Value is not a legal object identifier", nameof(hashAlgorithmId)); } if (requestedPolicyId != null && !Rfc3161TimestampUtils.IsLegalOid(requestedPolicyId.Value)) { throw new ArgumentException("Value is not a legal object identifier", nameof(requestedPolicyId)); } if (nonce != null && nonce.Length == 0) { throw new ArgumentException("Nonce must be null or non-empty", nameof(nonce)); } DataType data = new DataType { _version = 1, _hash = (byte[])messageHash.Clone(), _hashAlgorithm = new Oid(hashAlgorithmId.Value, hashAlgorithmId.FriendlyName), _nonce = (byte[])nonce?.Clone(), _requestSignerCertificate = requestSignerCertificates, _extensions = Rfc3161TimestampTokenInfo.ShallowCopy(extensions, preserveNull: true), }; if (requestedPolicyId != null) { data._requestedPolicyId = new Oid(requestedPolicyId.Value, requestedPolicyId.FriendlyName); } _data = data; RawData = Encode(data); }
internal Rfc3161TimestampToken( Rfc3161TimestampTokenInfo tstInfo, X509Certificate2 signerCertificate, X509Certificate2Collection additionalCerts, byte[] encoded) { Debug.Assert(tstInfo != null); Debug.Assert(signerCertificate != null); Debug.Assert(additionalCerts != null); TokenInfo = tstInfo; SignerCertificate = signerCertificate; AdditionalCerts = additionalCerts; _encoded = encoded; }
internal static bool ValidateSignerCertificateAgainstTimestamp( X509Certificate2 signerCertificate, Rfc3161TimestampTokenInfo tstInfo) { var tstInfoGenTime = tstInfo.Timestamp; var accuracyInMilliseconds = GetAccuracyInMilliseconds(tstInfo); var timestampUpperGenTime = tstInfoGenTime.AddMilliseconds(accuracyInMilliseconds); var timestampLowerGenTime = tstInfoGenTime.Subtract(TimeSpan.FromMilliseconds(accuracyInMilliseconds)); DateTimeOffset signerCertExpiry = DateTime.SpecifyKind(signerCertificate.NotAfter, DateTimeKind.Local); DateTimeOffset signerCertBegin = DateTime.SpecifyKind(signerCertificate.NotBefore, DateTimeKind.Local); return(timestampUpperGenTime < signerCertExpiry && timestampLowerGenTime > signerCertBegin); }
public Rfc3161TimestampTokenInfoNet472Wrapper(Rfc3161TimestampTokenInfo timestampTokenInfo) { _rfc3161TimestampTokenInfo = timestampTokenInfo; }
public Rfc3161TimestampTokenInfoNet472Wrapper(byte[] timestampTokenInfo) { _rfc3161TimestampTokenInfo = new Rfc3161TimestampTokenInfo(timestampTokenInfo); }
public X509ExtensionCollection GetExtensions() => Rfc3161TimestampTokenInfo.ShallowCopy(Data._extensions, preserveNull: false);
private static Rfc3161TimestampToken CryptVerifyTimeStampSignature(byte[] encodedToken, byte[] data) { var pTsContext = IntPtr.Zero; var pTsSigner = IntPtr.Zero; var 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()); } var tstInfo = new Rfc3161TimestampTokenInfo(pTsContext); var signerCert = new X509Certificate2(pTsSigner); using (var extraCerts = new X509Store(hStore)) { var 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); } } }
public unsafe Rfc3161TimestampToken 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); Rfc3161TimestampTokenInfo tstInfo = 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, 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); } } }