/// <summary> /// Timestamps data present in the TimestampRequest. /// </summary> internal async Task <SignedCms> GetTimestampAsync(TimestampRequest request, ILogger logger, CancellationToken token) { token.ThrowIfCancellationRequested(); if (request == null) { throw new ArgumentNullException(nameof(request)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } // Allows us to track the request. var nonce = GenerateNonce(); var rfc3161TimestampRequest = Rfc3161TimestampRequestFactory.Create( request.HashedMessage, request.HashAlgorithm.ConvertToSystemSecurityHashAlgorithmName(), requestedPolicyId: null, nonce: nonce, requestSignerCertificates: true, extensions: null); // Request a timestamp // The response status need not be checked here as lower level api will throw if the response is invalid IRfc3161TimestampToken timestampToken = await rfc3161TimestampRequest.SubmitRequestAsync( _timestamperUrl, RequestTimeout); // quick check for response validity var normalizedNonce = rfc3161TimestampRequest.GetNonce(); ValidateTimestampResponse(normalizedNonce, request.HashedMessage, timestampToken); var timestampCms = timestampToken.AsSignedCms(); ValidateTimestampCms(request.SigningSpecifications, timestampCms, timestampToken); // If the timestamp signed CMS already has a complete chain for the signing certificate, // it's ready to be added to the signature to be timestamped. // However, a timestamp service is not required to include all certificates in a complete // chain for the signing certificate in the SignedData.certificates collection. // Some timestamp services include all certificates except the root in the // SignedData.certificates collection. var signerInfo = timestampCms.SignerInfos[0]; using (var chain = CertificateChainUtility.GetCertificateChain( signerInfo.Certificate, timestampCms.Certificates, logger, CertificateType.Timestamp)) { return(EnsureCertificatesInCertificatesCollection(timestampCms, chain)); } }
public static IRfc3161TimestampToken Create( IRfc3161TimestampTokenInfo tstInfo, X509Certificate2 signerCertificate, X509Certificate2Collection additionalCerts, byte[] encoded) { if (tstInfo == null) { throw new ArgumentNullException(nameof(tstInfo)); } if (signerCertificate == null) { throw new ArgumentNullException(nameof(signerCertificate)); } if (additionalCerts == null) { throw new ArgumentNullException(nameof(additionalCerts)); } if (encoded == null) { throw new ArgumentNullException(nameof(encoded)); } #if IS_SIGNING_SUPPORTED IRfc3161TimestampToken iRfc3161TimestampToken = null; #if IS_DESKTOP iRfc3161TimestampToken = new Rfc3161TimestampTokenNet472Wrapper( tstInfo, signerCertificate, additionalCerts, encoded); #else iRfc3161TimestampToken = new Rfc3161TimestampTokenNetstandard21Wrapper( tstInfo, signerCertificate, additionalCerts, encoded); #endif return(iRfc3161TimestampToken); #else throw new NotSupportedException(); #endif }
private static void ValidateTimestampResponse(byte[] nonce, byte[] messageHash, IRfc3161TimestampToken timestampToken) { if (!nonce.SequenceEqual(timestampToken.TokenInfo.GetNonce())) { throw new TimestampException(NuGetLogCode.NU3026, Strings.TimestampFailureNonceMismatch); } if (!timestampToken.TokenInfo.HasMessageHash(messageHash)) { throw new TimestampException(NuGetLogCode.NU3019, Strings.SignError_TimestampIntegrityCheckFailed); } }
private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms timestampCms, IRfc3161TimestampToken timestampToken) { var signerInfo = timestampCms.SignerInfos[0]; try { signerInfo.CheckSignature(verifySignatureOnly: true); } catch (Exception e) { throw new TimestampException(NuGetLogCode.NU3021, Strings.SignError_TimestampSignatureValidationFailed, e); } if (signerInfo.Certificate == null) { throw new TimestampException(NuGetLogCode.NU3020, Strings.SignError_TimestampNoCertificate); } if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate)) { var certificateSignatureAlgorithm = GetNameOrOidString(signerInfo.Certificate.SignatureAlgorithm); var supportedSignatureAlgorithms = string.Join(", ", spec.AllowedSignatureAlgorithms); var errorMessage = string.Format(CultureInfo.CurrentCulture, Strings.TimestampCertificateUnsupportedSignatureAlgorithm, certificateSignatureAlgorithm, supportedSignatureAlgorithms); throw new TimestampException(NuGetLogCode.NU3022, errorMessage); } if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate)) { throw new TimestampException(NuGetLogCode.NU3023, Strings.SignError_TimestampCertificateFailsPublicKeyLengthRequirement); } if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value)) { var digestAlgorithm = GetNameOrOidString(signerInfo.DigestAlgorithm); var supportedSignatureAlgorithms = string.Join(", ", spec.AllowedHashAlgorithms); var errorMessage = string.Format(CultureInfo.CurrentCulture, Strings.TimestampSignatureUnsupportedDigestAlgorithm, digestAlgorithm, supportedSignatureAlgorithms); throw new TimestampException(NuGetLogCode.NU3024, errorMessage); } if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate)) { throw new TimestampException(NuGetLogCode.NU3025, Strings.SignError_TimestampNotYetValid); } if (!CertificateUtility.IsDateInsideValidityPeriod(signerInfo.Certificate, timestampToken.TokenInfo.Timestamp)) { throw new TimestampException(NuGetLogCode.NU3036, Strings.SignError_TimestampGeneralizedTimeInvalid); } }