public async Task <TimestampServiceWithUnavailableRevocation> CreateTimestampServiceWithUnavailableRevocationAsync() { var testServer = await _testServer.Value; var rootCa = CertificateAuthority.Create(testServer.Url); var rootCertificate = rootCa.Certificate.ToX509Certificate2(); var trust = new TrustedTestCert <X509Certificate2>( rootCertificate, certificate => certificate, StoreName.Root, StoreLocation.LocalMachine); var timestampService = TimestampService.Create(rootCa); var disposable = new DisposableList <IDisposable> { rootCertificate, trust }; Task WaitForResponseExpirationAsync() { return(rootCa.OcspResponder.WaitForResponseExpirationAsync(timestampService.Certificate)); } return(new TimestampServiceWithUnavailableRevocation( testServer, timestampService, WaitForResponseExpirationAsync, disposable)); }
public async Task GetTimestampAsync_TimestampGeneralizedTimeOutsideCertificateValidityPeriod_FailAsync() { // Arrange var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { IssuedCertificateNotBefore = DateTimeOffset.UtcNow.AddHours(-1), IssuedCertificateNotAfter = DateTimeOffset.UtcNow.AddHours(1), GeneralizedTime = DateTimeOffset.UtcNow.AddHours(3) }; var timestampService = TimestampService.Create(certificateAuthority, options); VerifyTimestampData( testServer, timestampService, async(timestampProvider, request) => { var exception = await Assert.ThrowsAsync <TimestampException>( () => timestampProvider.GetTimestampAsync(request, NullLogger.Instance, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3036, exception.Code); Assert.Contains( "The timestamp's generalized time is outside the timestamping certificate's validity period.", exception.Message); }); }
public async Task GetTimestamp_WhenRevocationInformationUnavailable_Success() { var testServer = await _testFixture.GetSigningTestServerAsync(); var ca = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var ca2 = ca.CreateIntermediateCertificateAuthority(); var timestampService = TimestampService.Create(ca2); // Only register the AIA responder. Do not register the OCSP responder. using (testServer.RegisterResponder(ca2)) { VerifyTimestampData( testServer, timestampService, (timestampProvider, request) => { var logger = new TestLogger(); var timestamp = timestampProvider.GetTimestamp(request, logger, CancellationToken.None); Assert.NotNull(timestamp); Assert.Equal(0, logger.Errors); Assert.Equal(2, logger.Warnings); AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning); AssertRevocationStatusUnknown(logger.LogMessages, LogLevel.Warning); }); } }
public async Task GetTimestampAsync_WhenCertificateSignatureAlgorithmIsSha1_ThrowsAsync() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var timestampServiceOptions = new TimestampServiceOptions() { SignatureHashAlgorithm = new Oid(Oids.Sha1) }; var issueCertificateOptions = IssueCertificateOptions.CreateDefaultForTimestampService(); issueCertificateOptions.SignatureAlgorithmName = "SHA1WITHRSA"; var timestampService = TimestampService.Create(certificateAuthority, timestampServiceOptions, issueCertificateOptions); VerifyTimestampData( testServer, timestampService, async(timestampProvider, request) => { var exception = await Assert.ThrowsAsync <TimestampException>( () => timestampProvider.GetTimestampAsync(request, NullLogger.Instance, CancellationToken.None)); Assert.Equal( "The timestamp certificate has an unsupported signature algorithm (SHA1RSA). The following algorithms are supported: SHA256RSA, SHA384RSA, SHA512RSA.", exception.Message); }); }
public async Task GetTimestamp_WithFailureReponse_Throws() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { ReturnFailure = true }; var timestampService = TimestampService.Create(certificateAuthority, options); VerifyTimestampData( testServer, timestampService, (timestampProvider, request) => { var exception = Assert.Throws <CryptographicException>( () => timestampProvider.GetTimestamp(request, NullLogger.Instance, CancellationToken.None)); Assert.StartsWith( "The timestamp signature and/or certificate could not be verified or is malformed.", exception.Message); }); }
public async Task GetTimestampCertificateChain_WithNoSigningCertificateUsage_Throws() { ISigningTestServer testServer = await _testFixture.GetSigningTestServerAsync(); CertificateAuthority rootCa = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SigningCertificateUsage = SigningCertificateUsage.None }; TimestampService timestampService = TimestampService.Create(rootCa, options); using (testServer.RegisterResponder(timestampService)) { var nupkg = new SimpleTestPackageContext(); using (var certificate = new X509Certificate2(_testFixture.TrustedTestCertificate.Source.Cert)) using (TestDirectory directory = TestDirectory.Create()) { string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, nupkg, directory, timestampService.Url); // Act CommandRunnerResult result = RunVerifyCommand(signedPackagePath); // Assert result.Success.Should().BeFalse(because: result.AllOutput); result.AllOutput.Should().Contain("Either the signing-certificate or signing-certificate-v2 attribute must be present."); result.AllOutput.Should().NotContain(_successfullyVerified); } } }
public async Task SignCommand_SignPackageWithUnsuportedTimestampHashAlgorithm_ShouldNotModifyPackageAsync() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SignatureHashAlgorithm = new Oid(Oids.Sha1) }; var timestampService = TimestampService.Create(certificateAuthority, options); using (testServer.RegisterResponder(timestampService)) using (var directory = TestDirectory.Create()) { var packageContext = new SimpleTestPackageContext(); var packageFile = packageContext.CreateAsFile(directory, fileName: Guid.NewGuid().ToString()); var originalFile = File.ReadAllBytes(packageFile.FullName); using (var certificate = _testFixture.UntrustedSelfIssuedCertificateInCertificateStore) { var result = CommandRunner.Run( _nugetExePath, directory, $"sign {packageFile.FullName} -CertificateFingerprint {certificate.Thumbprint} -Timestamper {timestampService.Url}", waitForExit: true); Assert.False(result.Success); Assert.Contains("The timestamp certificate has an unsupported signature algorithm.", result.AllOutput); var resultingFile = File.ReadAllBytes(packageFile.FullName); Assert.Equal(resultingFile, originalFile); } } }
public async Task VerifyAsync_WithRevokedTimestampCertificate_ReturnsSuspect() { var testServer = await _fixture.GetSigningTestServerAsync(); var certificateAuthority = await _fixture.GetDefaultTrustedCertificateAuthorityAsync(); var timestampService = await _fixture.GetDefaultTrustedTimestampServiceAsync(); var revokedTimestampService = TimestampService.Create(certificateAuthority); using (testServer.RegisterResponder(revokedTimestampService)) using (var test = await Test.CreateAuthorSignedRepositoryCountersignedPackageAsync( _fixture.TrustedTestCertificate.Source.Cert, _fixture.TrustedRepositoryCertificate.Source.Cert, timestampService.Url, revokedTimestampService.Url)) using (var packageReader = new PackageArchiveReader(test.PackageFile.FullName)) { await certificateAuthority.OcspResponder.WaitForResponseExpirationAsync(revokedTimestampService.Certificate); certificateAuthority.Revoke( revokedTimestampService.Certificate, RevocationReason.KeyCompromise, DateTimeOffset.UtcNow.AddHours(-1)); var status = await _verifier.VerifyAsync(packageReader, CancellationToken.None); Assert.Equal(SignatureVerificationStatus.Suspect, status); } }
public async Task <RevokableTimestampService> CreateRevokableTimestampServiceAsync() { var testServer = await _testServer.Value; var rootCa = await _rootCertificateAuthority.Value; var timestampService = TimestampService.Create(rootCa); var responders = testServer.RegisterDefaultResponders(timestampService); var revocationDate = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromHours(1)); void Revoke() { rootCa.Revoke(timestampService.Certificate, RevocationReason.Unspecified, revocationDate); } Task WaitForResponseExpirationAsync() { return(rootCa.OcspResponder.WaitForResponseExpirationAsync(timestampService.Certificate)); } return(new RevokableTimestampService( timestampService.Url, Revoke, WaitForResponseExpirationAsync, responders)); }
public async Task GetTimestamp_WhenSignatureHashAlgorithmIsSha1_Throws() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SignatureHashAlgorithm = new Oid(Oids.Sha1) }; var timestampService = TimestampService.Create(certificateAuthority, options); VerifyTimestampData( testServer, timestampService, (timestampProvider, request) => { var exception = Assert.Throws <TimestampException>( () => timestampProvider.GetTimestamp(request, NullLogger.Instance, CancellationToken.None)); Assert.Equal( "The timestamp certificate has an unsupported signature algorithm.", exception.Message); }); }
public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestampWithTooLargeRange_FailsAsync() { ISigningTestServer testServer = await _testFixture.GetSigningTestServerAsync(); CertificateAuthority ca = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var accuracy = new BcAccuracy(seconds: new DerInteger(30), millis: null, micros: null); var serviceOptions = new TimestampServiceOptions() { Accuracy = accuracy }; TimestampService timestampService = TimestampService.Create(ca, serviceOptions); AsymmetricCipherKeyPair keyPair = SigningTestUtility.GenerateKeyPair(publicKeyLength: 2048); DateTimeOffset now = DateTimeOffset.UtcNow; var issueOptions = new IssueCertificateOptions() { KeyPair = keyPair, NotAfter = now.AddSeconds(10), NotBefore = now.AddSeconds(-2), SubjectName = new X509Name("CN=NuGet Test Expired Certificate") }; BcX509Certificate bcCertificate = ca.IssueCertificate(issueOptions); using (testServer.RegisterResponder(timestampService)) using (TestDirectory directory = TestDirectory.Create()) using (X509Certificate2 certificate = CertificateUtilities.GetCertificateWithPrivateKey(bcCertificate, keyPair)) { var packageContext = new SimpleTestPackageContext(); string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, packageContext, directory, timestampService.Url); await SignatureTestUtility.WaitForCertificateExpirationAsync(certificate); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { VerifySignaturesResult results = await verifier.VerifySignaturesAsync(packageReader, _verifyCommandSettings, CancellationToken.None); PackageVerificationResult result = results.Results.Single(); Assert.False(results.IsValid); Assert.Equal(SignatureVerificationStatus.Disallowed, result.Trust); Assert.Equal(1, result.Issues.Count(issue => issue.Level == LogLevel.Error)); Assert.Equal(0, result.Issues.Count(issue => issue.Level == LogLevel.Warning)); Assert.Contains(result.Issues, issue => issue.Code == NuGetLogCode.NU3037 && issue.Level == LogLevel.Error && issue.Message.Contains("validity period has expired.")); } } }
private async Task <TimestampService> CreateDefaultTrustedTimestampServiceAsync() { var testServer = await _testServer.Value; var ca = await _defaultTrustedCertificateAuthority.Value; var timestampService = TimestampService.Create(ca); _responders.Add(testServer.RegisterResponder(timestampService)); return(timestampService); }
public async Task RejectsUntrustedTimestampingCertificate() { // Arrange var testServer = await _fixture.GetTestServerAsync(); var untrustedRootCa = CertificateAuthority.Create(testServer.Url); var untrustedRootCertficate = new X509Certificate2(untrustedRootCa.Certificate.GetEncoded()); var timestampService = TimestampService.Create(untrustedRootCa); using (testServer.RegisterDefaultResponders(timestampService)) { byte[] packageBytes; using (var temporaryTrust = new TrustedTestCert <X509Certificate2>( untrustedRootCertficate, x => x, StoreName.Root, StoreLocation.LocalMachine)) { packageBytes = await _fixture.GenerateSignedPackageBytesAsync( TestResources.SignedPackageLeaf1, await _fixture.GetSigningCertificateAsync(), timestampService.Url, _output); } TestUtility.RequireSignedPackage(_corePackageService, TestResources.SignedPackageLeafId, await _fixture.GetSigningCertificateThumbprintAsync()); _packageStream = new MemoryStream(packageBytes); _message = new SignatureValidationMessage( TestResources.SignedPackageLeafId, TestResources.SignedPackageLeaf1Version, new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"), Guid.NewGuid()); // Act var result = await _target.ValidateAsync( _packageKey, _packageStream, _message, _token); // Assert VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid); var issue = Assert.Single(result.Issues); var clientIssue = Assert.IsType <ClientSigningVerificationFailure>(issue); Assert.Equal("NU3028", clientIssue.ClientCode); Assert.Equal( "A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.", clientIssue.ClientMessage); } }
public async Task GetTimestampCertificateChain_WithMismatchedEssCertIdCertificateHash_ReturnsChain( SigningCertificateUsage signingCertificateUsage) { ISigningTestServer testServer = await _fixture.GetSigningTestServerAsync(); CertificateAuthority rootCa = await _fixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SigningCertificateUsage = signingCertificateUsage, SigningCertificateV1Hash = new byte[SHA1HashLength] }; TimestampService timestampService = TimestampService.Create(rootCa, options); using (testServer.RegisterResponder(timestampService)) { var nupkg = new SimpleTestPackageContext(); using (var certificate = new X509Certificate2(_fixture.TrustedTestCertificate.Source.Cert)) using (var directory = TestDirectory.Create()) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, nupkg, directory, timestampService.Url); using (FileStream stream = File.OpenRead(signedPackagePath)) using (var reader = new PackageArchiveReader(stream)) { PrimarySignature signature = await reader.GetPrimarySignatureAsync(CancellationToken.None); using (IX509CertificateChain actualChain = SignatureUtility.GetTimestampCertificateChain(signature)) { Assert.NotEmpty(actualChain); IReadOnlyList <Org.BouncyCastle.X509.X509Certificate> expectedChain = GetExpectedCertificateChain(timestampService); Assert.Equal(expectedChain.Count, actualChain.Count); for (var i = 0; i < expectedChain.Count; ++i) { Org.BouncyCastle.X509.X509Certificate expectedCertificate = expectedChain[i]; X509Certificate2 actualCertificate = actualChain[i]; Assert.True( expectedCertificate.GetEncoded().SequenceEqual(actualCertificate.RawData), $"The certificate at index {i} in the chain is unexpected."); } } } } } }
public async Task Timestamp_Verify_WithOfflineRevocation_ReturnsCorrectFlagsAndLogsAsync() { var nupkg = new SimpleTestPackageContext(); using (var testServer = await SigningTestServer.CreateAsync()) using (var responders = new DisposableList <IDisposable>()) using (var packageStream = await nupkg.CreateAsStreamAsync()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var ca = CreateOfflineRevocationCA(testServer, responders); var timestampService = TimestampService.Create(ca); responders.Add(testServer.RegisterResponder(timestampService)); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); var signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(testCertificate, packageStream, timestampProvider); var timestamp = signature.Timestamps.First(); var settings = new SignedPackageVerifierSettings( allowUnsigned: false, allowUntrusted: false, allowIllegal: false, allowIgnoreTimestamp: false, allowMultipleTimestamps: false, allowNoTimestamp: false, allowUnknownRevocation: false, reportUnknownRevocation: true, verificationTarget: VerificationTarget.All, signaturePlacement: SignaturePlacement.Any, repositoryCountersignatureVerificationBehavior: SignatureVerificationBehavior.Always, revocationMode: RevocationMode.Online); var logs = new List <SignatureLog>(); var result = timestamp.Verify(signature, settings, HashAlgorithmName.SHA256, logs); result.HasFlag(SignatureVerificationStatusFlags.UnknownRevocation).Should().BeTrue(); var errors = logs.Where(l => l.Level == LogLevel.Error); errors.Count().Should().Be(RuntimeEnvironmentHelper.IsWindows ? 2 : 1); if (RuntimeEnvironmentHelper.IsWindows) { errors.Should().Contain(w => w.Code == NuGetLogCode.NU3028 && w.Message.Contains("The revocation function was unable to check revocation because the revocation server could not be reached.")); errors.Should().Contain(w => w.Code == NuGetLogCode.NU3028 && w.Message.Contains("The revocation function was unable to check revocation for the certificate.")); } else { errors.Should().Contain(w => w.Code == NuGetLogCode.NU3028 && w.Message.Contains("unable to get certificate CRL")); } } }
public async Task <CustomTimestampService> CreateCustomTimestampServiceAsync(TimestampServiceOptions options) { var testServer = await _testServer.Value; var rootCa = await _rootCertificateAuthority.Value; var timestampService = TimestampService.Create(rootCa, options); var responders = testServer.RegisterDefaultResponders(timestampService); return(new CustomTimestampService( timestampService.Url, responders)); }
public async Task <UntrustedTimestampService> CreateUntrustedTimestampServiceAsync() { var testServer = await _testServer.Value; var untrustedRootCa = CertificateAuthority.Create(testServer.Url); var untrustedRootCertificate = untrustedRootCa.Certificate.ToX509Certificate2(); var timestampService = TimestampService.Create(untrustedRootCa); var responders = testServer.RegisterDefaultResponders(timestampService); return(new UntrustedTimestampService( untrustedRootCertificate, timestampService.Url, responders)); }
public async Task DotnetSign_SignPackageWithUnsuportedTimestampHashAlgorithm_FailsAsync() { // Arrange using (SimpleTestPathContext pathContext = _msbuildFixture.CreateSimpleTestPathContext()) { await SimpleTestPackageUtility.CreatePackagesAsync( pathContext.PackageSource, new SimpleTestPackageContext("PackageA", "1.0.0")); string packageFilePath = Path.Combine(pathContext.PackageSource, "PackageA.1.0.0.nupkg"); byte[] originalFile = File.ReadAllBytes(packageFilePath); ISigningTestServer testServer = await _signFixture.GetSigningTestServerAsync(); CertificateAuthority certificateAuthority = await _signFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SignatureHashAlgorithm = new Oid(Oids.Sha1) }; TimestampService timestampService = TimestampService.Create(certificateAuthority, options); IX509StoreCertificate storeCertificate = _signFixture.UntrustedSelfIssuedCertificateInCertificateStore; using (testServer.RegisterResponder(timestampService)) { // Act CommandRunnerResult result = _msbuildFixture.RunDotnet( pathContext.PackageSource, $"nuget sign {packageFilePath} " + $"--certificate-fingerprint {storeCertificate.Certificate.Thumbprint} " + $"--timestamper {timestampService.Url}", ignoreExitCode: true); // Assert result.Success.Should().BeFalse(because: result.AllOutput); result.AllOutput.Should().Contain(_timestampUnsupportedDigestAlgorithmCode); Assert.Contains("The timestamp signature has an unsupported digest algorithm (SHA1). The following algorithms are supported: SHA256, SHA384, SHA512.", result.AllOutput); byte[] resultingFile = File.ReadAllBytes(packageFilePath); Assert.Equal(resultingFile, originalFile); } } }
public async Task GetTimestampCertificateChain_WithShortEssCertIdCertificateHash_Throws( SigningCertificateUsage signingCertificateUsage) { ISigningTestServer testServer = await _fixture.GetSigningTestServerAsync(); CertificateAuthority rootCa = await _fixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SigningCertificateUsage = signingCertificateUsage, SigningCertificateV1Hash = new byte[SHA1HashLength - 1] }; TimestampService timestampService = TimestampService.Create(rootCa, options); using (testServer.RegisterResponder(timestampService)) { var nupkg = new SimpleTestPackageContext(); using (var certificate = new X509Certificate2(_fixture.TrustedTestCertificate.Source.Cert)) using (var directory = TestDirectory.Create()) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, nupkg, directory, timestampService.Url); using (FileStream stream = File.OpenRead(signedPackagePath)) using (var reader = new PackageArchiveReader(stream)) { PrimarySignature signature = await reader.GetPrimarySignatureAsync(CancellationToken.None); var exception = Assert.Throws <SignatureException>( () => SignatureUtility.GetTimestampCertificateChain(signature)); Assert.Equal( "A certificate referenced by the signing-certificate attribute could not be found.", exception.Message); } } } }
public async Task TimestampData_WhenTimestampSigningCertificateRevoked_Throws() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var timestampService = TimestampService.Create(certificateAuthority); certificateAuthority.Revoke(timestampService.Certificate, CrlReason.KeyCompromise, DateTimeOffset.UtcNow); VerifyTimestampData( testServer, timestampService, (timestampProvider, request) => { var exception = Assert.Throws <TimestampException>( () => timestampProvider.TimestampData(request, NullLogger.Instance, CancellationToken.None)); Assert.Equal("Certificate chain validation failed.", exception.Message); }); }
public async Task GetTimestamp_WhenSigningCertificateNotReturned_Throws() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { ReturnSigningCertificate = false }; var timestampService = TimestampService.Create(certificateAuthority, options); VerifyTimestampData( testServer, timestampService, (timestampProvider, request) => { var exception = Assert.Throws <CryptographicException>( () => timestampProvider.GetTimestamp(request, NullLogger.Instance, CancellationToken.None)); Assert.StartsWith("Cannot find object or property.", exception.Message); }); }
public async Task TimestampData_WhenTimestampSigningCertificateRevoked_Throws() { var testServer = await _testFixture.GetSigningTestServerAsync(); var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var timestampService = TimestampService.Create(certificateAuthority); certificateAuthority.Revoke(timestampService.Certificate, CrlReason.KeyCompromise, DateTimeOffset.UtcNow); using (testServer.RegisterResponder(timestampService)) { var logger = new TestLogger(); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); var data = "Test data to be signed and timestamped"; using (var authorCert = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedCms = SigningTestUtility.GenerateSignedCms(authorCert, Encoding.ASCII.GetBytes(data)); var signatureValue = signedCms.Encode(); var request = new TimestampRequest { SigningSpec = SigningSpecifications.V1, TimestampHashAlgorithm = Common.HashAlgorithmName.SHA256, SignatureValue = signatureValue }; var exception = Assert.Throws <TimestampException>( () => timestampProvider.TimestampData(request, logger, CancellationToken.None)); Assert.Equal( "The timestamp service's certificate chain could not be built: The certificate is revoked.", exception.Message); } } }
public async Task GetTimestampCertificateChain_WithMismatchedEssCertIdCertificateHash_ReturnsChain( SigningCertificateUsage signingCertificateUsage) { ISigningTestServer testServer = await _testFixture.GetSigningTestServerAsync(); CertificateAuthority rootCa = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var options = new TimestampServiceOptions() { SigningCertificateUsage = signingCertificateUsage, SigningCertificateV1Hash = new byte[SHA1HashLength] }; TimestampService timestampService = TimestampService.Create(rootCa, options); using (testServer.RegisterResponder(timestampService)) { var nupkg = new SimpleTestPackageContext(); using (var certificate = new X509Certificate2(_testFixture.TrustedTestCertificate.Source.Cert)) using (TestDirectory directory = TestDirectory.Create()) { string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, nupkg, directory, timestampService.Url); // Act CommandRunnerResult result = RunVerifyCommand(signedPackagePath); // Assert result.Success.Should().BeTrue(because: result.AllOutput); result.AllOutput.Should().Contain(_successfullyVerified); Regex.Matches(result.AllOutput, _noTimestamperWarning).Count.Should().Be(0); } } }
public async Task AcceptsTrustedTimestampingCertificateWithUnavailableRevocation() { // Arrange var testServer = await _fixture.GetTestServerAsync(); var trustedRootCa = CertificateAuthority.Create(testServer.Url); var trustedRootCertficate = new X509Certificate2(trustedRootCa.Certificate.GetEncoded()); var timestampService = TimestampService.Create(trustedRootCa); using (var trust = new TrustedTestCert <X509Certificate2>( trustedRootCertficate, x => x, StoreName.Root, StoreLocation.LocalMachine)) { byte[] packageBytes; using (testServer.RegisterDefaultResponders(timestampService)) { packageBytes = await _fixture.GenerateSignedPackageBytesAsync( TestResources.SignedPackageLeaf1, await _fixture.GetSigningCertificateAsync(), timestampService.Url, _output); } // Wait one second for the OCSP response cached by the operating system during signing to get stale. // This can be mitigated by leaving the OCSP unavailable during signing once this work item is done: // https://github.com/NuGet/Home/issues/6508 await Task.Delay(TimeSpan.FromSeconds(1)); TestUtility.RequireSignedPackage(_corePackageService, TestResources.SignedPackageLeafId, await _fixture.GetSigningCertificateThumbprintAsync()); _packageStream = new MemoryStream(packageBytes); _message = new SignatureValidationMessage( TestResources.SignedPackageLeafId, TestResources.SignedPackageLeaf1Version, new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"), Guid.NewGuid()); SignatureValidatorResult result; using (testServer.RegisterResponders(timestampService, addOcsp: false)) { // Act result = await _target.ValidateAsync( _packageKey, _packageStream, _message, _token); } // Assert VerifyPackageSigningStatus(result, ValidationStatus.Succeeded, PackageSigningStatus.Valid); Assert.Empty(result.Issues); var allMessages = string.Join(Environment.NewLine, _logger.Messages); Assert.Contains("NU3028: The revocation function was unable to check revocation because the revocation server was offline.", allMessages); Assert.Contains("NU3028: The revocation function was unable to check revocation for the certificate.", allMessages); } }
public async Task Timestamp_Verify_WithOfflineRevocation_ReturnsCorrectFlagsAndLogsAsync() { var nupkg = new SimpleTestPackageContext(); using (var testServer = await SigningTestServer.CreateAsync()) using (var responders = new DisposableList <IDisposable>()) using (var packageStream = await nupkg.CreateAsStreamAsync()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { CertificateAuthority rootCa = CertificateAuthority.Create(testServer.Url); CertificateAuthority intermediateCa = rootCa.CreateIntermediateCertificateAuthority(); responders.Add(testServer.RegisterResponder(intermediateCa)); responders.Add(testServer.RegisterResponder(rootCa)); StoreLocation storeLocation = CertificateStoreUtilities.GetTrustedCertificateStoreLocation(); using (var trustedServerRoot = TrustedTestCert.Create( new X509Certificate2(rootCa.Certificate.GetEncoded()), StoreName.Root, storeLocation)) { var timestampService = TimestampService.Create(intermediateCa); responders.Add(testServer.RegisterResponder(timestampService)); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); AuthorPrimarySignature signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(testCertificate, packageStream, timestampProvider); var timestamp = signature.Timestamps.First(); var settings = new SignedPackageVerifierSettings( allowUnsigned: false, allowUntrusted: false, allowIllegal: false, allowIgnoreTimestamp: false, allowMultipleTimestamps: false, allowNoTimestamp: false, allowUnknownRevocation: false, reportUnknownRevocation: true, verificationTarget: VerificationTarget.All, signaturePlacement: SignaturePlacement.Any, repositoryCountersignatureVerificationBehavior: SignatureVerificationBehavior.Always, revocationMode: RevocationMode.Online); var logs = new List <SignatureLog>(); var result = timestamp.Verify(signature, settings, HashAlgorithmName.SHA256, logs); result.HasFlag(SignatureVerificationStatusFlags.UnknownRevocation).Should().BeTrue(); var errors = logs.Where(l => l.Level == LogLevel.Error); if (RuntimeEnvironmentHelper.IsMacOSX) { errors.Count().Should().Be(1); } else { errors.Count().Should().Be(2); SigningTestUtility.AssertOfflineRevocationOnlineMode(errors, LogLevel.Error, NuGetLogCode.NU3028); } SigningTestUtility.AssertRevocationStatusUnknown(errors, LogLevel.Error, NuGetLogCode.NU3028); } } }
public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestampWithTooLargeRange_Fails() { var testServer = await _testFixture.GetSigningTestServerAsync(); var ca = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync(); var accuracy = new BcAccuracy(seconds: new DerInteger(30), millis: null, micros: null); var serviceOptions = new TimestampServiceOptions() { Accuracy = accuracy }; var timestampService = TimestampService.Create(ca, serviceOptions); var keyPair = SigningTestUtility.GenerateKeyPair(publicKeyLength: 2048); var now = DateTimeOffset.UtcNow; var issueOptions = new IssueCertificateOptions() { KeyPair = keyPair, NotAfter = now.AddSeconds(10), NotBefore = now.AddSeconds(-2), SubjectName = new X509Name("CN=NuGet Test Expired Certificate") }; var bcCertificate = ca.IssueCertificate(issueOptions); using (testServer.RegisterResponder(timestampService)) using (var certificate = new X509Certificate2(bcCertificate.GetEncoded())) using (var directory = TestDirectory.Create()) { certificate.PrivateKey = DotNetUtilities.ToRSA(keyPair.Private as RsaPrivateCrtKeyParameters); var packageContext = new SimpleTestPackageContext(); var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, packageContext, directory, timestampService.Url); var waitDuration = (issueOptions.NotAfter - DateTimeOffset.UtcNow).Add(TimeSpan.FromSeconds(1)); // Wait for the certificate to expire. Trust of the signature will require a valid timestamp. if (waitDuration > TimeSpan.Zero) { await Task.Delay(waitDuration); } Assert.True(DateTime.UtcNow > issueOptions.NotAfter); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { var results = await verifier.VerifySignaturesAsync(packageReader, _verifyCommandSettings, CancellationToken.None); var result = results.Results.Single(); Assert.False(results.Valid); Assert.Equal(SignatureVerificationStatus.Illegal, result.Trust); Assert.Equal(1, result.Issues.Count(issue => issue.Level == LogLevel.Error)); Assert.Equal(0, result.Issues.Count(issue => issue.Level == LogLevel.Warning)); Assert.Contains(result.Issues, issue => issue.Code == NuGetLogCode.NU3011 && issue.Level == LogLevel.Error && issue.Message.Contains("validity period has expired.")); } } }