private static void ProcessResponse( Rfc3161RequestResponseStatus expectedStatus, Rfc3161TimestampRequest request, byte[] inputBytes, int paddingByteCount) { Rfc3161TimestampToken token; int bytesRead; Rfc3161RequestResponseStatus status; bool result = request.TryProcessResponse(inputBytes, out token, out status, out bytesRead); Assert.Equal(expectedStatus, status); if (expectedStatus == Rfc3161RequestResponseStatus.Accepted) { Assert.True(result, "request.TryProcessResponse return value"); } else { Assert.False(result, "request.TryProcessResponse return value"); } if (expectedStatus == Rfc3161RequestResponseStatus.DoesNotParse) { Assert.Equal(0, bytesRead); } else { Assert.Equal(inputBytes.Length - paddingByteCount, bytesRead); } switch (expectedStatus) { case Rfc3161RequestResponseStatus.Accepted: case Rfc3161RequestResponseStatus.HashMismatch: case Rfc3161RequestResponseStatus.NonceMismatch: case Rfc3161RequestResponseStatus.UnexpectedCertificates: case Rfc3161RequestResponseStatus.RequestedCertificatesMissing: case Rfc3161RequestResponseStatus.VersionTooNew: Assert.NotNull(token); break; default: Assert.Null(token); break; } if (result) { Rfc3161TimestampToken token2 = request.ProcessResponse(inputBytes, out int bytesRead2); Assert.Equal(bytesRead, bytesRead2); Assert.NotNull(token2); Assert.NotSame(token, token2); } else { Assert.Throws <CryptographicException>(() => request.ProcessResponse(inputBytes, out bytesRead)); } }
public static void TryDecode_Fails_Empty() { Assert.False( Rfc3161TimestampToken.TryDecode( ReadOnlyMemory <byte> .Empty, out Rfc3161TimestampToken token, out int bytesRead), "Rfc3161TimestampToken.TryDecode"); Assert.Equal(0, bytesRead); Assert.Null(token); }
public static void TryDecode_Fails_SignedCmsOfData() { Assert.False( Rfc3161TimestampToken.TryDecode( SignedDocuments.RsaPkcs1OneSignerIssuerAndSerialNumber, out Rfc3161TimestampToken token, out int bytesRead), "Rfc3161TimestampToken.TryDecode"); Assert.Equal(0, bytesRead); Assert.Null(token); }
internal static bool TryProcessResponse( this Rfc3161TimestampRequest request, ReadOnlyMemory <byte> inputBytes, out Rfc3161TimestampToken token, out TimestampRequestTests.Rfc3161RequestResponseStatus status, out int bytesRead) { object[] parameters = { inputBytes, null, null, null, false }; object result = s_tryProcesses.Invoke(request, parameters); token = (Rfc3161TimestampToken)parameters[1]; status = (TimestampRequestTests.Rfc3161RequestResponseStatus) Enum.ToObject(typeof(TimestampRequestTests.Rfc3161RequestResponseStatus), parameters[2]); bytesRead = (int)parameters[3]; return((bool)result); }
public static void TryDecode_Fails_EnvelopedCms() { byte[] encodedMessage = ("3082010c06092a864886f70d010703a081fe3081fb0201003181c83081c5020100302e301a311830160603550403130f5253" + "414b65795472616e7366657231021031d935fb63e8cfab48a0bf7b397b67c0300d06092a864886f70d010101050004818013" + "dc0eb2984a445d04a1f6246b8fe41f1d24507548d449d454d5bb5e0638d75ed101bf78c0155a5d208eb746755fbccbc86923" + "8443760a9ae94770d6373e0197be23a6a891f0c522ca96b3e8008bf23547474b7e24e7f32e8134df3862d84f4dea2470548e" + "c774dd74f149a56cdd966e141122900d00ad9d10ea1848541294a1302b06092a864886f70d010701301406082a864886f70d" + "030704089c8119f6cf6b174c8008bcea3a10d0737eb9").HexToByteArray(); Assert.False( Rfc3161TimestampToken.TryDecode( encodedMessage, out Rfc3161TimestampToken token, out int bytesRead), "Rfc3161TimestampToken.TryDecode"); Assert.Equal(0, bytesRead); Assert.Null(token); }
private static void CustomBuild_CertMatch( CertLoader loader, DateTimeOffset referenceTime, SigningCertificateOption v1Option, SigningCertificateOption v2Option, HashAlgorithmName v2AlgorithmName = default, X509IncludeOption includeOption = default, SubjectIdentifierType identifierType = SubjectIdentifierType.IssuerAndSerialNumber) { byte[] tokenBytes = BuildCustomToken( loader, referenceTime, v1Option, v2Option, v2AlgorithmName, includeOption, identifierType); Rfc3161TimestampToken token; Assert.True(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead)); Assert.Equal(tokenBytes.Length, bytesRead); Assert.NotNull(token); Assert.Equal(referenceTime, token.TokenInfo.Timestamp); using (X509Certificate2 cert = Certificates.ValidLookingTsaCert.GetCertificate()) { Assert.True( token.VerifySignatureForHash( token.TokenInfo.GetMessageHash().Span, token.TokenInfo.HashAlgorithmId, out X509Certificate2 signer, new X509Certificate2Collection(cert))); Assert.Equal(cert, signer); } }
public static void TryDecode_Fails_MalformedToken() { ContentInfo contentInfo = new ContentInfo( new Oid(Oids.TstInfo, Oids.TstInfo), new byte[] { 1 }); SignedCms cms = new SignedCms(contentInfo); using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey()) { cms.ComputeSignature(new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert)); } Assert.False( Rfc3161TimestampToken.TryDecode( cms.Encode(), out Rfc3161TimestampToken token, out int bytesRead), "Rfc3161TimestampToken.TryDecode"); Assert.Equal(0, bytesRead); Assert.Null(token); }
private static void CustomBuild_CertMismatch( CertLoader loader, DateTimeOffset referenceTime, SigningCertificateOption v1Option, SigningCertificateOption v2Option, HashAlgorithmName v2AlgorithmName = default, X509IncludeOption includeOption = default, SubjectIdentifierType identifierType = SubjectIdentifierType.IssuerAndSerialNumber) { byte[] tokenBytes = BuildCustomToken( loader, referenceTime, v1Option, v2Option, v2AlgorithmName, includeOption, identifierType); Rfc3161TimestampToken token; bool willParse = includeOption == X509IncludeOption.None; if (willParse && identifierType == SubjectIdentifierType.IssuerAndSerialNumber) { // Because IASN matches against the ESSCertId(V2) directly it will reject the token. switch (v1Option) { case SigningCertificateOption.ValidHashWithInvalidName: case SigningCertificateOption.ValidHashWithInvalidSerial: case SigningCertificateOption.InvalidHashWithInvalidName: case SigningCertificateOption.InvalidHashWithInvalidSerial: willParse = false; break; } switch (v2Option) { case SigningCertificateOption.ValidHashWithInvalidName: case SigningCertificateOption.ValidHashWithInvalidSerial: case SigningCertificateOption.InvalidHashWithInvalidName: case SigningCertificateOption.InvalidHashWithInvalidSerial: willParse = false; break; } } if (willParse) { Assert.True(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead)); Assert.NotNull(token); Assert.Equal(tokenBytes.Length, bytesRead); using (X509Certificate2 cert = loader.GetCertificate()) { Assert.False( token.VerifySignatureForHash( token.TokenInfo.GetMessageHash().Span, token.TokenInfo.HashAlgorithmId, out X509Certificate2 signer, new X509Certificate2Collection(cert))); Assert.Null(signer); } } else { Assert.False(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead)); Assert.Null(token); Assert.Equal(0, bytesRead); } }
private static void TestParseDocument( ReadOnlyMemory <byte> tokenBytes, TimestampTokenTestData testData, int?expectedBytesRead) { int bytesRead; Rfc3161TimestampToken token; Assert.True( Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out bytesRead), "Rfc3161TimestampToken.TryDecode"); if (expectedBytesRead != null) { Assert.Equal(expectedBytesRead.Value, bytesRead); } Assert.NotNull(token); TimestampTokenInfoTests.AssertEqual(testData, token.TokenInfo); SignedCms signedCms = token.AsSignedCms(); Assert.NotNull(signedCms); Assert.Equal(Oids.TstInfo, signedCms.ContentInfo.ContentType.Value); Assert.Equal( testData.TokenInfoBytes.ByteArrayToHex(), signedCms.ContentInfo.Content.ByteArrayToHex()); if (testData.EmbeddedSigningCertificate != null) { Assert.NotNull(signedCms.SignerInfos[0].Certificate); Assert.Equal( testData.EmbeddedSigningCertificate.Value.ByteArrayToHex(), signedCms.SignerInfos[0].Certificate.RawData.ByteArrayToHex()); // Assert.NoThrow signedCms.CheckSignature(true); } else { Assert.Null(signedCms.SignerInfos[0].Certificate); using (var signerCert = new X509Certificate2(testData.ExternalCertificateBytes)) { // Assert.NoThrow signedCms.CheckSignature( new X509Certificate2Collection(signerCert), true); } } X509Certificate2 returnedCert; ReadOnlySpan <byte> messageContentSpan = testData.MessageContent.Span; X509Certificate2Collection candidates = null; if (testData.EmbeddedSigningCertificate != null) { Assert.True( token.VerifySignatureForData(messageContentSpan, out returnedCert), "token.VerifySignatureForData(correct)"); Assert.NotNull(returnedCert); Assert.Equal(signedCms.SignerInfos[0].Certificate, returnedCert); } else { candidates = new X509Certificate2Collection { new X509Certificate2(testData.ExternalCertificateBytes), }; Assert.False( token.VerifySignatureForData(messageContentSpan, out returnedCert), "token.VerifySignatureForData(correct, no cert)"); Assert.Null(returnedCert); Assert.True( token.VerifySignatureForData(messageContentSpan, out returnedCert, candidates), "token.VerifySignatureForData(correct, certs)"); Assert.NotNull(returnedCert); Assert.Equal(candidates[0], returnedCert); } X509Certificate2 previousCert = returnedCert; Assert.False( token.VerifySignatureForData(messageContentSpan.Slice(1), out returnedCert, candidates), "token.VerifySignatureForData(incorrect)"); Assert.Null(returnedCert); byte[] messageHash = testData.HashBytes.ToArray(); Assert.False( token.VerifySignatureForHash(messageHash, HashAlgorithmName.MD5, out returnedCert, candidates), "token.VerifyHash(correct, MD5)"); Assert.Null(returnedCert); Assert.False( token.VerifySignatureForHash(messageHash, new Oid(Oids.Md5), out returnedCert, candidates), "token.VerifyHash(correct, Oid(MD5))"); Assert.Null(returnedCert); Assert.True( token.VerifySignatureForHash(messageHash, new Oid(testData.HashAlgorithmId), out returnedCert, candidates), "token.VerifyHash(correct, Oid(algId))"); Assert.NotNull(returnedCert); Assert.Equal(previousCert, returnedCert); messageHash[0] ^= 0xFF; Assert.False( token.VerifySignatureForHash(messageHash, new Oid(testData.HashAlgorithmId), out returnedCert, candidates), "token.VerifyHash(incorrect, Oid(algId))"); Assert.Null(returnedCert); }
internal static bool?CheckRFC3161TimestampInternal(SignerInfo signerInfo, DateTimeOffset?notBefore, DateTimeOffset?notAfter) { bool found = false; byte[] signatureBytes = null; foreach (CryptographicAttributeObject attr in signerInfo.UnsignedAttributes) { if (attr.Oid.Value == CertificateHelper.SignatureTimeStampOin.Value) { foreach (AsnEncodedData attrInst in attr.Values) { byte[] attrData = attrInst.RawData; // New API starts here: if (!Rfc3161TimestampToken.TryDecode(attrData, out var token, out var bytesRead)) { return(false); } if (bytesRead != attrData.Length) { return(false); } signatureBytes = signatureBytes ?? signerInfo.GetSignature(); // Check that the token was issued based on the SignerInfo's signature value if (!token.VerifySignatureForSignerInfo(signerInfo, out _)) { return(false); } var timestamp = token.TokenInfo.Timestamp; // Check that the signed timestamp is within the provided policy range // (which may be (signerInfo.Certificate.NotBefore, signerInfo.Certificate.NotAfter); // or some other policy decision) if (timestamp < notBefore.GetValueOrDefault(timestamp) || timestamp > notAfter.GetValueOrDefault(timestamp)) { return(false); } var tokenSignerCert = token.AsSignedCms().SignerInfos[0].Certificate; // Implicit policy decision: Tokens required embedded certificates (since this method has // no resolver) if (tokenSignerCert == null) { return(false); } found = true; } } } // If we found any attributes and none of them returned an early false, then the SignerInfo is // conformant to policy. if (found) { return(true); } // Inconclusive, as no signed timestamps were found return(null); }