public async Task Verify_AuthorSignedTimestampedPackage_SuccessAsync() { // Arrange var nupkg = new SimpleTestPackageContext(); X509Certificate2 defaultAuthorCertificate = await _testFixture.GetDefaultAuthorSigningCertificateAsync(); TimestampService timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); using (TestDirectory dir = TestDirectory.Create()) using (var authorCertificate = new X509Certificate2(defaultAuthorCertificate)) { string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( authorCertificate, nupkg, dir, 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 GetTrustResultAsync_WithNoSigningCertificate_Throws() { var package = new SimpleTestPackageContext(); using (var directory = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var packageFilePath = await SignedArchiveTestUtility.CreateSignedAndTimeStampedPackageAsync(testCertificate, package, directory); using (var packageReader = new PackageArchiveReader(packageFilePath)) { var signature = (await packageReader.GetSignaturesAsync(CancellationToken.None)).Single(); var signatureWithNoCertificates = GenerateSignatureWithNoCertificates(signature); var provider = new SignatureTrustAndValidityVerificationProvider(); var result = await provider.GetTrustResultAsync( packageReader, signatureWithNoCertificates, SignedPackageVerifierSettings.Default, CancellationToken.None); var issue = result.Issues.FirstOrDefault(log => log.Code == NuGetLogCode.NU3010); Assert.NotNull(issue); Assert.Equal("The primary signature does not have a signing certificate.", issue.Message); } } }
public async Task Signature_HasNoTimestamp() { // Arrange var nupkg = new SimpleTestPackageContext(); var testLogger = new TestLogger(); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { // Act var signedPackagePath = await SignedArchiveTestUtility.CreateSignedPackageAsync(testCertificate, nupkg, dir); // Assert using (var stream = File.OpenRead(signedPackagePath)) using (var reader = new PackageArchiveReader(stream)) { var signatures = await reader.GetSignaturesAsync(CancellationToken.None); signatures.Count.Should().Be(1); var signature = signatures[0]; signature.Timestamps.Should().BeEmpty(); } } }
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 Install_TamperedPackage_FailsAsync() { // Arrange var nupkg = new SimpleTestPackageContext("A", "1.0.0"); using (var context = new SimpleTestPathContext()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, context.WorkingDirectory); SignedArchiveTestUtility.TamperWithPackage(signedPackagePath); var args = new string[] { nupkg.Id, "-Version", nupkg.Version, "-DirectDownload", "-NoCache", "-Source", context.WorkingDirectory, "-OutputDirectory", Path.Combine(context.WorkingDirectory, "packages") }; // Act var result = RunInstall(_nugetExePath, context, expectedExitCode: 1, additionalArgs: args); // Assert result.ExitCode.Should().Be(1); result.Errors.Should().Contain(string.Format(_NU3008, SigningTestUtility.AddSignatureLogPrefix(_NU3008Message, nupkg.Identity, context.WorkingDirectory))); result.AllOutput.Should().Contain($"WARNING: {string.Format(_NU3027, SigningTestUtility.AddSignatureLogPrefix(_NU3027Message, nupkg.Identity, context.WorkingDirectory))}"); } }
public async Task Install_RepoSignedPackage_SucceedsAsync() { // Arrange var nupkg = new SimpleTestPackageContext("A", "1.0.0"); using (var context = new SimpleTestPathContext()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { await SignedArchiveTestUtility.RepositorySignPackageAsync(testCertificate, nupkg, context.WorkingDirectory, new Uri("https://v3serviceIndex.test/api/index.json")); var args = new string[] { nupkg.Id, "-Version", nupkg.Version, "-DirectDownload", "-NoCache", "-Source", context.WorkingDirectory, "-OutputDirectory", Path.Combine(context.WorkingDirectory, "packages") }; // Act var result = RunInstall(_nugetExePath, context, expectedExitCode: 0, additionalArgs: args); // Assert result.ExitCode.Should().Be(0); result.AllOutput.Should().Contain($"WARNING: {string.Format(_NU3027, SigningTestUtility.AddSignatureLogPrefix(_NU3027Message, nupkg.Identity, context.WorkingDirectory))}"); } }
public async Task Install_UntrustedCertSignedPackage_WarnsAsync() { // Arrange var nupkg = new SimpleTestPackageContext("A", "1.0.0"); using (var context = new SimpleTestPathContext()) using (var testCertificate = new X509Certificate2(_testFixture.UntrustedSelfIssuedCertificateInCertificateStore)) { await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, context.WorkingDirectory); var args = new string[] { nupkg.Id, "-Version", nupkg.Version, "-DirectDownload", "-NoCache", "-Source", context.WorkingDirectory, "-OutputDirectory", Path.Combine(context.WorkingDirectory, "packages") }; // Act var result = RunInstall(_nugetExePath, context, expectedExitCode: 0, additionalArgs: args); // Assert result.ExitCode.Should().Be(0); result.AllOutput.Should().Contain($"WARNING: {string.Format(_NU3018, SigningTestUtility.AddSignatureLogPrefix(_NU3018Message, nupkg.Identity, context.WorkingDirectory))}"); result.AllOutput.Should().Contain($"WARNING: {string.Format(_NU3027, SigningTestUtility.AddSignatureLogPrefix(_NU3027Message, nupkg.Identity, context.WorkingDirectory))}"); } }
private static async Task <MemoryStream> CreateSignedPackageAsync( X509Certificate2 certificate, Stream unsignedPackage = null) { if (unsignedPackage == null) { var packageContext = new SimpleTestPackageContext(); unsignedPackage = packageContext.CreateAsStream(); } var signatureProvider = new X509SignatureProvider(timestampProvider: null); var overwrite = true; using (var request = new AuthorSignPackageRequest(certificate, HashAlgorithmName.SHA256)) using (var outputPackageStream = new MemoryStream()) using (var options = new SigningOptions( new Lazy <Stream>(() => unsignedPackage), new Lazy <Stream>(() => outputPackageStream), overwrite, signatureProvider, NullLogger.Instance)) { await SigningUtility.SignAsync(options, request, CancellationToken.None); var isSigned = await SignedArchiveTestUtility.IsSignedAsync(options.OutputPackageStream); Assert.True(isSigned); return(new MemoryStream(outputPackageStream.ToArray())); } }
public async Task DotnetTrust_AuthorAction_RelativePathConfileFile_Succeeds(bool allowUntrustedRoot) { // Arrange var nugetConfigFileName = "NuGet.Config"; var package = new SimpleTestPackageContext(); using (SimpleTestPathContext pathContext = _msbuildFixture.CreateSimpleTestPathContext()) using (MemoryStream zipStream = await package.CreateAsStreamAsync()) using (TrustedTestCert <TestCertificate> trustedTestCert = SigningTestUtility.GenerateTrustedTestCertificate()) { string certFingerprint = SignatureTestUtility.GetFingerprint(trustedTestCert.Source.Cert, HashAlgorithmName.SHA256); string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(trustedTestCert.Source.Cert, package, pathContext.PackageSource); var config = $@"<?xml version=""1.0"" encoding=""utf-8""?> <configuration> <packageSources> <!--To inherit the global NuGet package sources remove the <clear/> line below --> <clear /> <add key=""NuGetSource"" value=""{pathContext.PackageSource}"" /> </packageSources> <config> <add key=""signaturevalidationmode"" value=""accept"" /> </config> <trustedSigners> </trustedSigners> </configuration>"; SettingsTestUtils.CreateConfigurationFile(nugetConfigFileName, pathContext.WorkingDirectory, config); var nugetConfigPath = Path.Combine(pathContext.WorkingDirectory, nugetConfigFileName); var allowUntrustedRootArg = allowUntrustedRoot ? "--allow-untrusted-root" : string.Empty; var allowUntruestedRootValue = allowUntrustedRoot ? "true" : "false"; // Act CommandRunnerResult resultAdd = _msbuildFixture.RunDotnet( pathContext.SolutionRoot, $"nuget trust author nuget {signedPackagePath} {allowUntrustedRootArg} --configfile ..{Path.DirectorySeparatorChar}{nugetConfigFileName}"); // Assert resultAdd.Success.Should().BeTrue(); resultAdd.AllOutput.Should().Contain(string.Format(CultureInfo.CurrentCulture, _successfulAddTrustedSigner, "author", "nuget")); string expectedResult = SettingsTestUtils.RemoveWhitespace($@"<?xml version=""1.0"" encoding=""utf-8""?> <configuration> <packageSources> <!--To inherit the global NuGet package sources remove the < clear /> line below--> <clear/> <add key = ""NuGetSource"" value = ""{pathContext.PackageSource}""/> </packageSources > <config> <add key = ""signaturevalidationmode"" value = ""accept""/> </config> < trustedSigners> <author name = ""nuget""> <certificate fingerprint = ""{certFingerprint}"" hashAlgorithm = ""SHA256"" allowUntrustedRoot = ""{allowUntruestedRootValue}""/> </author> </trustedSigners> </configuration>"); SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath)).Should().Be(expectedResult); } }
public async Task SignAsync_WhenRepositoryCountersigningPrimarySignature_SucceedsAsync() { using (var test = await Test.CreateAsync(_testFixture.TrustedTestCertificate.Source.Cert)) { await SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None); using (var package = new PackageArchiveReader(test.Options.OutputPackageStream)) { var primarySignature = await package.GetPrimarySignatureAsync(CancellationToken.None); Assert.IsType <AuthorPrimarySignature>(primarySignature); } using (var countersignatureOptions = SigningOptions.CreateFromFilePaths( test.OutputFile.FullName, test.GetNewTempFilePath(), overwrite: false, signatureProvider: new X509SignatureProvider(timestampProvider: null), logger: NullLogger.Instance)) { await SigningUtility.SignAsync(countersignatureOptions, test.RepositoryRequest, CancellationToken.None); var isRepositoryCountersigned = await SignedArchiveTestUtility.IsRepositoryCountersignedAsync(countersignatureOptions.OutputPackageStream); Assert.True(isRepositoryCountersigned); } } }
public async Task Signer_VerifyOnTamperedPackage_FileDeletedAsync(string policyString) { // Arrange var nupkg = new SimpleTestPackageContext(); var policy = GetSettingsPolicy(policyString); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, dir); SignedArchiveTestUtility.TamperWithPackage(signedPackagePath); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { // Act var result = await verifier.VerifySignaturesAsync(packageReader, policy, CancellationToken.None); var resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); var totalErrorIssues = resultsWithErrors.SelectMany(r => r.GetErrorIssues()); // Assert result.IsValid.Should().BeFalse(); resultsWithErrors.Count().Should().Be(1); totalErrorIssues.Count().Should().Be(1); totalErrorIssues.First().Code.Should().Be(NuGetLogCode.NU3008); totalErrorIssues.First().Message.Should().Be(_packageTamperedError); } } }
public async Task Signature_HasTimestampAsync() { // Arrange var nupkg = new SimpleTestPackageContext(); var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); using (var cert = new X509Certificate2(_trustedTestCert.Source.Cert)) using (var dir = TestDirectory.Create()) { // Act var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( cert, nupkg, dir, timestampService.Url); // Assert using (var stream = File.OpenRead(signedPackagePath)) using (var reader = new PackageArchiveReader(stream)) { var signature = await reader.GetPrimarySignatureAsync(CancellationToken.None); signature.Should().NotBeNull(); signature.Timestamps.Should().NotBeEmpty(); } } }
public async Task GetTrustResultAsync_WithSignedAndCountersignedPackage_Succeeds() { // Arrange var nupkg = new SimpleTestPackageContext(); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) using (var trusted = SigningTestUtility.GenerateTrustedTestCertificate()) using (var counterCertificate = new X509Certificate2(trusted.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( testCertificate, nupkg, dir); var repositorySignedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync( counterCertificate, signedPackagePath, dir, new Uri("https://v3ServiceIndex.test/api/index")); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(repositorySignedPackagePath)) { // Act var result = await verifier.VerifySignaturesAsync(packageReader, SignedPackageVerifierSettings.GetVerifyCommandDefaultPolicy(), CancellationToken.None); var resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); // Assert result.Valid.Should().BeTrue(); resultsWithErrors.Count().Should().Be(0); } } }
public async Task VerifySignaturesAsync_ValidCertificateAndTimestamp_Success() { // Arrange var nupkg = new SimpleTestPackageContext(); var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.CreateSignedAndTimeStampedPackageAsync( testCertificate, nupkg, dir, timestampService.Url); var verifier = new PackageSignatureVerifier(_trustProviders, SignedPackageVerifierSettings.VerifyCommandDefaultPolicy); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { // Act var result = await verifier.VerifySignaturesAsync(packageReader, CancellationToken.None); var resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); // Assert result.Valid.Should().BeTrue(); resultsWithErrors.Count().Should().Be(0); } } }
public async Task GetTrustResultAsync_VerifyWithCertificateInAllowList_Success() { // Arrange var nupkg = new SimpleTestPackageContext(); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var certificateFingerprintString = SignatureTestUtility.GetFingerprint(testCertificate, HashAlgorithmName.SHA256); var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, dir); var allowListHashes = new[] { certificateFingerprintString, "abc" }; var allowList = allowListHashes.Select(hash => new CertificateHashAllowListEntry(VerificationTarget.Primary, hash)).ToList(); var trustProviders = new[] { new AllowListVerificationProvider(allowList) }; var verifier = new PackageSignatureVerifier(trustProviders, _settings); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { // Act var result = await verifier.VerifySignaturesAsync(packageReader, CancellationToken.None); // Assert result.Valid.Should().BeTrue(); } } }
public async Task VerifySignaturesAsync_ValidCertificateAndTimestampWithDifferentHashAlgorithms_Success() { var packageContext = new SimpleTestPackageContext(); var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); using (var directory = TestDirectory.Create()) using (var certificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( certificate, packageContext, directory, timestampService.Url, signatureHashAlgorithm : HashAlgorithmName.SHA512); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { var result = await verifier.VerifySignaturesAsync(packageReader, _verifyCommandSettings, CancellationToken.None); var resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); result.Valid.Should().BeTrue(); resultsWithErrors.Count().Should().Be(0); } } }
public async Task Timestamps_WithTwoAttributesAndOneValueEach_ReturnsTwoTimestamps() { var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); var nupkg = new SimpleTestPackageContext(); using (var packageStream = await nupkg.CreateAsStreamAsync()) using (var testCertificate = new X509Certificate2(_testFixture.TrustedTestCertificate.Source.Cert)) { AuthorPrimarySignature authorSignature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync( testCertificate, packageStream, timestampProvider); SignedCms updatedSignedCms = ModifyUnsignedAttributes(authorSignature.SignedCms, attributeTable => { BcAttribute attribute = attributeTable[PkcsObjectIdentifiers.IdAASignatureTimeStampToken]; Asn1Encodable value = attribute.AttrValues.ToArray().Single(); AttributeTable updatedAttributes = attributeTable.Add(PkcsObjectIdentifiers.IdAASignatureTimeStampToken, value); return(updatedAttributes); }); AssertTimestampAttributeAndValueCounts(updatedSignedCms, expectedAttributesCount: 2, expectedValuesCount: 2); var updatedAuthorSignature = new AuthorPrimarySignature(updatedSignedCms); Assert.Equal(2, updatedAuthorSignature.Timestamps.Count); } }
internal async Task CountersignAsync() { PrimarySignature primarySignature; using (var archiveReader = new PackageArchiveReader(SignedPackage)) { primarySignature = await archiveReader.GetPrimarySignatureAsync(CancellationToken.None); } using (var request = new UnknownSignPackageRequest( new X509Certificate2(Certificate), HashAlgorithmName.SHA256)) { var cmsSigner = SigningUtility.CreateCmsSigner(request, NullLogger.Instance); var signedCms = primarySignature.SignedCms; signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner); primarySignature = PrimarySignature.Load(signedCms.Encode()); } using (var originalPackage = new MemoryStream(Zip.ToByteArray(), writable: false)) using (var signedPackage = new MemoryStream()) using (var archive = new SignedPackageArchive(originalPackage, signedPackage)) using (var signatureStream = new MemoryStream(primarySignature.GetBytes())) { await archive.AddSignatureAsync(signatureStream, CancellationToken.None); SignedPackage = new MemoryStream(signedPackage.ToArray(), writable: false); } var isSigned = await SignedArchiveTestUtility.IsSignedAsync(SignedPackage); Assert.True(isSigned); }
public async Task VerifySignaturesAsync_SettingsRequireTimestamp_NoTimestamp_Fails() { // Arrange var nupkg = new SimpleTestPackageContext(); var setting = new SignedPackageVerifierSettings( allowUnsigned: false, allowUntrusted: false, allowUntrustedSelfSignedCertificate: false, allowIgnoreTimestamp: false, allowMultipleTimestamps: true, allowNoTimestamp: false, allowUnknownRevocation: false); using (var dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var signedPackagePath = await SignedArchiveTestUtility.CreateSignedPackageAsync(testCertificate, nupkg, dir); var verifier = new PackageSignatureVerifier(_trustProviders, setting); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { // Act var result = await verifier.VerifySignaturesAsync(packageReader, CancellationToken.None); var resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); var totalErrorIssues = resultsWithErrors.SelectMany(r => r.GetErrorIssues()); // Assert result.Valid.Should().BeFalse(); resultsWithErrors.Count().Should().Be(1); totalErrorIssues.Count().Should().Be(1); totalErrorIssues.First().Code.Should().Be(NuGetLogCode.NU3027); } } }
public async Task GetCertificateChain_WithUnknownSignature_ReturnsCertificatesAsync() { using (var directory = TestDirectory.Create()) using (var certificate = _fixture.GetDefaultCertificate()) { var packageContext = new SimpleTestPackageContext(); var unsignedPackageFile = await packageContext.CreateAsFileAsync(directory, "Package.nupkg"); var signedPackageFile = await SignedArchiveTestUtility.SignPackageFileWithBasicSignedCmsAsync( directory, unsignedPackageFile, certificate); using (var packageReader = new PackageArchiveReader(signedPackageFile.FullName)) { var signature = await packageReader.GetPrimarySignatureAsync(CancellationToken.None); using (var certificates = SignatureUtility.GetCertificateChain(signature)) { Assert.Equal(1, certificates.Count); Assert.Equal(certificate.RawData, certificates[0].RawData); } } } }
private async Task <string> CreateSignedPackageAsync(TestDirectory dir, SigningTestType signature, X509Certificate2 authorcert, X509Certificate2 repocert) { var nupkg = new SimpleTestPackageContext(); var signedPackagePath = ""; if (signature == SigningTestType.Author || signature == SigningTestType.RepositoryCountersigned) { signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(authorcert, nupkg, dir); } if (signature == SigningTestType.RepositoryPrimary) { signedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync(repocert, nupkg, dir, new Uri(@"https://api.v3serviceIndex.test/json"), packageOwners : new List <string>() { "owner1", "owner2", "owner3" }); } if (signature == SigningTestType.RepositoryCountersigned) { signedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync(repocert, signedPackagePath, dir, new Uri(@"https://api.v3serviceIndex.test/json"), packageOwners : new List <string>() { "owner1", "owner2", "owner3" }); } return(signedPackagePath); }
public async Task VerifySignaturesAsync_ValidCertificate_SuccessAsync() { // Arrange var nupkg = new SimpleTestPackageContext(); using (TestDirectory dir = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, dir); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(signedPackagePath)) { // Act VerifySignaturesResult result = await verifier.VerifySignaturesAsync(packageReader, _verifyCommandSettings, CancellationToken.None); IEnumerable <PackageVerificationResult> resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); // Assert result.IsValid.Should().BeTrue(); resultsWithErrors.Count().Should().Be(0); } } }
public async Task Install_AuthorSignedPackage_SucceedsAsync() { // Arrange var nupkg = new SimpleTestPackageContext("A", "1.0.0"); using (var context = new SimpleTestPathContext()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, context.WorkingDirectory); var args = new string[] { nupkg.Id, "-Version", nupkg.Version, "-DirectDownload", "-NoCache", "-Source", context.WorkingDirectory, "-OutputDirectory", Path.Combine(context.WorkingDirectory, "packages") }; // Act var result = RunInstall(_nugetExePath, context, expectedExitCode: 0, additionalArgs: args); // Assert result.ExitCode.Should().Be(0); result.AllOutput.Should().Contain($"WARNING: {_NU3027}"); } }
public async Task GetTrustResultAsync_WithInvalidSignature_Throws() { var package = new SimpleTestPackageContext(); var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); using (var directory = TestDirectory.Create()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { var packageFilePath = await SignedArchiveTestUtility.CreateSignedAndTimeStampedPackageAsync( testCertificate, package, directory, timestampService.Url); using (var packageReader = new PackageArchiveReader(packageFilePath)) { var signature = await packageReader.GetSignatureAsync(CancellationToken.None); var invalidSignature = SignedArchiveTestUtility.GenerateInvalidSignature(signature); var provider = new SignatureTrustAndValidityVerificationProvider(); var result = await provider.GetTrustResultAsync( packageReader, invalidSignature, SignedPackageVerifierSettings.Default, CancellationToken.None); var issue = result.Issues.FirstOrDefault(log => log.Code == NuGetLogCode.NU3012); Assert.NotNull(issue); Assert.Equal("Primary signature validation failed.", issue.Message); } } }
public async Task GetTimestampAsync_AssertCompleteChain_SuccessAsync() { var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); var nupkg = new SimpleTestPackageContext(); using (var authorCert = new X509Certificate2(_trustedTestCert.Source.Cert)) using (var packageStream = await nupkg.CreateAsStreamAsync()) { // Act AuthorPrimarySignature signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(authorCert, packageStream, timestampProvider); var authorSignedCms = signature.SignedCms; var timestamp = signature.Timestamps.First(); var timestampCms = timestamp.SignedCms; IX509CertificateChain certificateChain; var chainBuildSuccess = true; // rebuild the chain to get the list of certificates using (var chainHolder = new X509ChainHolder()) { var chain = chainHolder.Chain; var policy = chain.ChainPolicy; policy.ApplicationPolicy.Add(new Oid(Oids.TimeStampingEku)); policy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid; policy.RevocationFlag = X509RevocationFlag.ExcludeRoot; policy.RevocationMode = X509RevocationMode.Online; var timestampSignerCertificate = timestampCms.SignerInfos[0].Certificate; chainBuildSuccess = chain.Build(timestampSignerCertificate); certificateChain = CertificateChainUtility.GetCertificateChain(chain); } using (certificateChain) { // Assert authorSignedCms.Should().NotBeNull(); authorSignedCms.Detached.Should().BeFalse(); authorSignedCms.ContentInfo.Should().NotBeNull(); authorSignedCms.SignerInfos.Count.Should().Be(1); authorSignedCms.SignerInfos[0].UnsignedAttributes.Count.Should().Be(1); authorSignedCms.SignerInfos[0].UnsignedAttributes[0].Oid.Value.Should().Be(Oids.SignatureTimeStampTokenAttribute); timestampCms.Should().NotBeNull(); timestampCms.Detached.Should().BeFalse(); timestampCms.ContentInfo.Should().NotBeNull(); chainBuildSuccess.Should().BeTrue(); certificateChain.Count.Should().Be(timestampCms.Certificates.Count); foreach (var cert in certificateChain) { timestampCms.Certificates.Contains(cert).Should().BeTrue(); } } } }
public async Task TrustedSignersCommand_AddTrustedSigner_WithRepositoryCountersignedPackage_AddsItSuccesfullyToConfigAsync(bool allowUntrustedRoot, string owners) { // Arrange var nugetConfigFileName = "NuGet.Config"; var config = @"<?xml version=""1.0"" encoding=""utf-8""?> <configuration> </configuration>"; // Arrange var package = new SimpleTestPackageContext(); using (var dir = TestDirectory.Create()) using (var zipStream = await package.CreateAsStreamAsync()) using (var authorTrustedTestCert = SigningTestUtility.GenerateTrustedTestCertificate()) using (var repoTrustedTestCert = SigningTestUtility.GenerateTrustedTestCertificate()) { var certFingerprint = SignatureTestUtility.GetFingerprint(repoTrustedTestCert.Source.Cert, HashAlgorithmName.SHA256); var repoServiceIndex = "https://serviceindex.test/v3/index.json"; var authorSignedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(authorTrustedTestCert.Source.Cert, package, dir); var signedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync(repoTrustedTestCert.Source.Cert, authorSignedPackagePath, dir, new Uri(repoServiceIndex)); SettingsTestUtils.CreateConfigurationFile(nugetConfigFileName, dir, config); var nugetConfigPath = Path.Combine(dir, nugetConfigFileName); var allowUntrustedRootArg = allowUntrustedRoot ? "-AllowUntrustedRoot" : string.Empty; var ownersArgs = string.Empty; var expectedOwners = string.Empty; if (owners != null) { ownersArgs = $"-Owners {owners}"; expectedOwners = $"<owners>{owners}</owners>"; } // Act var commandResult = CommandRunner.Run( _nugetExePath, dir, $"trusted-signers add {signedPackagePath} -Name signer -Repository {allowUntrustedRootArg} {ownersArgs} -Config {nugetConfigPath}", waitForExit: true); // Assert commandResult.Success.Should().BeTrue(); commandResult.AllOutput.Should().Contain(string.Format(CultureInfo.CurrentCulture, _successfulAddTrustedSigner, "repository", "signer")); var expectedResult = SettingsTestUtils.RemoveWhitespace($@"<?xml version=""1.0"" encoding=""utf-8""?> <configuration> <trustedSigners> <repository name=""signer"" serviceIndex=""{repoServiceIndex}""> <certificate fingerprint=""{certFingerprint}"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""{allowUntrustedRoot.ToString().ToLower()}"" /> {expectedOwners} </repository> </trustedSigners> </configuration>"); SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath)).Should().Be(expectedResult); } }
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.")); } } }
public async Task Restore_TamperedPackage_FailsAsync() { // Arrange var nupkg = new SimpleTestPackageContext("A", "1.0.0"); using (var pathContext = new SimpleTestPathContext()) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { // Set up solution, project, and packages var solution = new SimpleTestSolutionContext(pathContext.SolutionRoot); var projectA = SimpleTestProjectContext.CreateNETCore( "a", pathContext.SolutionRoot, NuGetFramework.Parse("NETStandard2.0")); var packageX = new SimpleTestPackageContext("X", "9.0.0"); var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, packageX, pathContext.PackageSource); SignedArchiveTestUtility.TamperWithPackage(signedPackagePath); projectA.AddPackageToAllFrameworks(packageX); solution.Projects.Add(projectA); solution.Create(pathContext.SolutionRoot); var args = new string[] { projectA.ProjectPath, "-Source", pathContext.PackageSource }; // Act var result = RunRestore(_nugetExePath, pathContext, expectedExitCode: 1, additionalArgs: args); var reader = new LockFileFormat(); var lockFile = reader.Read(projectA.AssetsFileOutputPath); var errors = lockFile.LogMessages.Where(m => m.Level == LogLevel.Error); var warnings = lockFile.LogMessages.Where(m => m.Level == LogLevel.Warning); // Assert result.ExitCode.Should().Be(1); result.Errors.Should().Contain(_NU3008); result.AllOutput.Should().Contain($"WARNING: {_NU3027}"); errors.Count().Should().Be(1); errors.First().Code.Should().Be(NuGetLogCode.NU3008); errors.First().Message.Should().Be(_NU3008Message); errors.First().LibraryId.Should().Be(packageX.ToString()); warnings.Count().Should().Be(1); warnings.First().Code.Should().Be(NuGetLogCode.NU3027); warnings.First().Message.Should().Be(_NU3027Message); warnings.First().LibraryId.Should().Be("X.9.0.0"); } }
public async Task VerifySignaturesAsync_WithExpiredPrimarySignature_ValidCountersignature_AndPrimarySignatureExpiredAtCountersignTime_FailsAsync() { // Arrange var nupkg = new SimpleTestPackageContext(); TimestampService timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); var settings = new SignedPackageVerifierSettings( allowUnsigned: false, allowIllegal: false, allowUntrusted: false, allowIgnoreTimestamp: true, allowMultipleTimestamps: true, allowNoTimestamp: true, allowUnknownRevocation: true, reportUnknownRevocation: true, verificationTarget: VerificationTarget.All, signaturePlacement: SignaturePlacement.Any, repositoryCountersignatureVerificationBehavior: SignatureVerificationBehavior.IfExists, revocationMode: RevocationMode.Online); using (TestDirectory dir = TestDirectory.Create()) using (TrustedTestCert <TestCertificate> trustedCertificate = _testFixture.CreateTrustedTestCertificateThatWillExpireSoon()) using (var willExpireCert = new X509Certificate2(trustedCertificate.Source.Cert)) using (var repoTestCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) { string signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync( willExpireCert, nupkg, dir); await SignatureTestUtility.WaitForCertificateExpirationAsync(willExpireCert); string countersignedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync( repoTestCertificate, signedPackagePath, dir, TestServiceIndexUrl, timestampService.Url); var verifier = new PackageSignatureVerifier(_trustProviders); using (var packageReader = new PackageArchiveReader(countersignedPackagePath)) { // Act VerifySignaturesResult result = await verifier.VerifySignaturesAsync(packageReader, settings, CancellationToken.None); IEnumerable <PackageVerificationResult> resultsWithErrors = result.Results.Where(r => r.GetErrorIssues().Any()); // Assert result.IsValid.Should().BeFalse(); resultsWithErrors.Count().Should().Be(1); } } }
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")); } } }