示例#1
0
        public void GetCertificateChain_WithRepositoryCountersignature_ReturnsCertificates()
        {
            var primarySignature           = PrimarySignature.Load(SigningTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            using (var certificates = SignatureUtility.GetCertificateChain(primarySignature, repositoryCountersignature))
            {
                Assert.Equal(3, certificates.Count);
                Assert.Equal("8d8cc5bdf9e5f86b971d7fb961fe24b999486483", certificates[0].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("c8ae47bfd632870a15e3775784affd2bdc96cbf1", certificates[1].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("d4e8185475a062de3518d1aa693f13c4283f81ff", certificates[2].Thumbprint, StringComparer.OrdinalIgnoreCase);
            }
        }
        public void GetHashString_ReturnsCorrectHashForSupportedAlgorithms()
        {
            using (var certificate = SigningTestUtility.GetCertificate("leaf.crt"))
            {
                var sha256Fingerprint = CertificateUtility.GetHashString(certificate, Common.HashAlgorithmName.SHA256);
                var sha384Fingerprint = CertificateUtility.GetHashString(certificate, Common.HashAlgorithmName.SHA384);
                var sha512Fingerprint = CertificateUtility.GetHashString(certificate, Common.HashAlgorithmName.SHA512);

                Assert.Equal("9893F4B40FD236F16C189AD8F01D8B92FE682DFA6E768354ED25F4741BF51C73", sha256Fingerprint);
                Assert.Equal("6471116F2B2A4DBA7B021A208408F53FBA2BCA1661ED006112E82850AA9DFD06EC9B5C9A50B4D2E6890B756781503FE5", sha384Fingerprint);
                Assert.Equal("5B00A6B778AF9DC19BB62BFA688556FEC0A35AEFFB63DACD8D4EF2F227EC0EF43DA8B27F3E12F8C3485D128F32E4E7CA20136AF3BB3DF21A4B47AE54137698F3", sha512Fingerprint);
            }
        }
示例#3
0
        public void GetTimestampCertificateChain_WithRepositoryCountersignatureTimestamp_ReturnsCertificates()
        {
            var primarySignature           = PrimarySignature.Load(SigningTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            using (var certificates = SignatureUtility.GetTimestampCertificateChain(primarySignature, repositoryCountersignature))
            {
                Assert.Equal(3, certificates.Count);
                Assert.Equal("96b479acf63394f3bcc9928c396264afd60909ed", certificates[0].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("fa4e4ca3d9a26b92a73bb875f964972983b55ccd", certificates[1].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("88b288ff6d3d826469a9ef7816166a7def221885", certificates[2].Thumbprint, StringComparer.OrdinalIgnoreCase);
            }
        }
        public void IsSigned_WithCentralDirectoryHeaderUsingUtf8_ReturnsFalse()
        {
            var zipBytes = SigningTestUtility.GetResourceBytes("SignatureFileEntry.zip");

            zipBytes[35] = 0x08;

            using (var test = new Test(zipBytes))
            {
                var isSigned = SignedPackageArchiveUtility.IsSigned(test.Reader);

                Assert.False(isSigned);
            }
        }
示例#5
0
        public void GetTimestampCertificateChain_WithUnrelatedRepositoryCountersignature_Throws()
        {
            var primarySignature           = PrimarySignature.Load(SigningTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            primarySignature = RemoveRepositoryCountersignature(primarySignature);

            var exception = Assert.Throws <ArgumentException>(
                () => SignatureUtility.GetTimestampCertificateChain(primarySignature, repositoryCountersignature));

            Assert.Equal("repositoryCountersignature", exception.ParamName);
            Assert.StartsWith("The primary signature and repository countersignature are unrelated.", exception.Message);
        }
示例#6
0
        private static void VerifyAttributes(
            System.Security.Cryptography.CryptographicAttributeObjectCollection attributes,
            SignPackageRequest request)
        {
            var pkcs9SigningTimeAttributeFound         = false;
            var commitmentTypeIndicationAttributeFound = false;
            var signingCertificateV2AttributeFound     = false;

            foreach (var attribute in attributes)
            {
                Assert.Equal(1, attribute.Values.Count);

                switch (attribute.Oid.Value)
                {
                case "1.2.840.113549.1.9.5":     // PKCS #9 signing time
                    Assert.IsType <Pkcs9SigningTime>(attribute.Values[0]);

                    pkcs9SigningTimeAttributeFound = true;
                    break;

                case Oids.CommitmentTypeIndication:
                    var qualifier = CommitmentTypeQualifier.Read(attribute.Values[0].RawData);
                    var expectedCommitmentType = AttributeUtility.GetSignatureTypeOid(request.SignatureType);

                    Assert.Equal(expectedCommitmentType, qualifier.CommitmentTypeIdentifier.Value);

                    commitmentTypeIndicationAttributeFound = true;
                    break;

                case Oids.SigningCertificateV2:
                    var signingCertificateV2 = SigningCertificateV2.Read(attribute.Values[0].RawData);

                    Assert.Equal(1, signingCertificateV2.Certificates.Count);

                    var essCertIdV2 = signingCertificateV2.Certificates[0];

                    Assert.Equal(SigningTestUtility.GetHash(request.Certificate, request.SignatureHashAlgorithm), essCertIdV2.CertificateHash);
                    Assert.Equal(request.SignatureHashAlgorithm.ConvertToOidString(), essCertIdV2.HashAlgorithm.Algorithm.Value);
                    Assert.Equal(request.Certificate.IssuerName.Name, essCertIdV2.IssuerSerial.GeneralNames[0].DirectoryName.Name);
                    SigningTestUtility.VerifySerialNumber(request.Certificate, essCertIdV2.IssuerSerial);
                    Assert.Null(signingCertificateV2.Policies);

                    signingCertificateV2AttributeFound = true;
                    break;
                }
            }

            Assert.True(pkcs9SigningTimeAttributeFound);
            Assert.True(commitmentTypeIndicationAttributeFound);
            Assert.True(signingCertificateV2AttributeFound);
        }
示例#7
0
        public async Task VerifySignaturesAsync_ExpiredCertificateAndTimestamp_Success()
        {
            var ca = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync();

            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var keyPair      = SigningTestUtility.GenerateKeyPair(publicKeyLength: 2048);
            var now          = DateTimeOffset.UtcNow;
            var issueOptions = new IssueCertificateOptions(keyPair.Public)
            {
                NotAfter    = now.AddSeconds(10),
                NotBefore   = now.AddSeconds(-2),
                SubjectName = new X509Name("CN=NuGet Test Expired Certificate")
            };
            var bcCertificate = ca.IssueCertificate(issueOptions);

            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.CreateSignedAndTimeStampedPackageAsync(
                        certificate,
                        packageContext,
                        directory,
                        timestampService.Url);

                    var notAfter     = certificate.NotAfter.ToUniversalTime();
                    var waitDuration = (notAfter - DateTimeOffset.UtcNow).Add(TimeSpan.FromSeconds(1));

                    // Wait for the certificate to expire.  Trust of the signature will require a valid timestamp.
                    await Task.Delay(waitDuration);

                    Assert.True(DateTime.UtcNow > notAfter);

                    var verifier = new PackageSignatureVerifier(_trustProviders, SignedPackageVerifierSettings.VerifyCommandDefaultPolicy);

                    using (var packageReader = new PackageArchiveReader(signedPackagePath))
                    {
                        var result = await verifier.VerifySignaturesAsync(packageReader, CancellationToken.None);

                        var trustProvider = result.Results.Single();

                        Assert.True(result.Valid);
                        Assert.Equal(SignatureVerificationStatus.Trusted, trustProvider.Trust);
                        Assert.Equal(0, trustProvider.Issues.Count(issue => issue.Level == LogLevel.Error));
                        Assert.Equal(0, trustProvider.Issues.Count(issue => issue.Level == LogLevel.Warning));
                    }
                }
        }
示例#8
0
        public async Task DotnetTrust_CertificateFingerPrintAction_WithExistingSigner_AppendSucceeds(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())
                    {
                        var certFingerprint   = SignatureTestUtility.GetFingerprint(trustedTestCert.Source.Cert, HashAlgorithmName.SHA256);
                        var repoServiceIndex  = "https://serviceindex.test/v3/index.json";
                        var signedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync(trustedTestCert.Source.Cert, package, pathContext.PackageSource, new Uri(repoServiceIndex));

                        var config = @"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
    <trustedSigners>
        <author name=""MyCompanyCert"">
            <certificate fingerprint=""abcdefg"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
    </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";
                        var authorName = "MyCompanyCert";

                        // Act
                        CommandRunnerResult resultAdd = _msbuildFixture.RunDotnet(
                            pathContext.SolutionRoot,
                            $"nuget trust certificate {authorName} {certFingerprint} {allowUntrustedRootArg}  --algorithm SHA256 --configfile {nugetConfigPath}");

                        // Assert
                        resultAdd.Success.Should().BeTrue();
                        resultAdd.AllOutput.Should().Contain(string.Format(CultureInfo.CurrentCulture, "Successfully updated the trusted signer '{0}'.", authorName));

                        string expectedResult = SettingsTestUtils.RemoveWhitespace($@"<?xml version=""1.0"" encoding=""utf-8""?>
                <configuration>
                    < trustedSigners>
                        <author name = ""{authorName}"">
                                < certificate fingerprint = ""abcdefg"" hashAlgorithm = ""SHA256"" allowUntrustedRoot = ""false""/>
                                < certificate fingerprint = ""{certFingerprint}"" hashAlgorithm = ""SHA256"" allowUntrustedRoot = ""{allowUntruestedRootValue}""/>
                        </author>
                    </trustedSigners>
                </configuration>");

                        SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath)).Should().Be(expectedResult);
                    }
        }
示例#9
0
        public async Task DotnetTrust_RepositoryAction_Succeeds(bool allowUntrustedRoot, string owners)
        {
            // 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())
                    {
                        var certFingerprint   = SignatureTestUtility.GetFingerprint(trustedTestCert.Source.Cert, HashAlgorithmName.SHA256);
                        var repoServiceIndex  = "https://serviceindex.test/v3/index.json";
                        var signedPackagePath = await SignedArchiveTestUtility.RepositorySignPackageAsync(trustedTestCert.Source.Cert, package, pathContext.PackageSource, new Uri(repoServiceIndex));

                        var config = $@"<?xml version=""1.0"" encoding=""utf-8""?>
                <configuration>
                </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";
                        var ownersArgs     = string.Empty;
                        var expectedOwners = string.Empty;

                        if (owners != null)
                        {
                            ownersArgs     = $"--owners {owners}";
                            expectedOwners = $"<owners>{owners}</owners>";
                        }

                        // Act
                        CommandRunnerResult resultAdd = _msbuildFixture.RunDotnet(
                            pathContext.SolutionRoot,
                            $"nuget trust repository nuget {signedPackagePath}  {allowUntrustedRootArg} {ownersArgs} --configfile {nugetConfigPath}");

                        // Assert
                        resultAdd.Success.Should().BeTrue();
                        resultAdd.AllOutput.Should().Contain(string.Format(CultureInfo.CurrentCulture, _successfulAddTrustedSigner, "repository", "nuget"));

                        string expectedResult = SettingsTestUtils.RemoveWhitespace($@"<?xml version=""1.0"" encoding=""utf-8""?>
                <configuration>
                    < trustedSigners>
                        <repository name = ""nuget"" serviceIndex=""https://serviceindex.test/v3/index.json"">
                                < certificate fingerprint = ""{certFingerprint}"" hashAlgorithm = ""SHA256"" allowUntrustedRoot = ""{allowUntruestedRootValue}""/>{expectedOwners}
                        </repository>
                    </trustedSigners>
                </configuration>");

                        SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath)).Should().Be(expectedResult);
                    }
        }
        public void IsSigned_WithIncorrectSignatureFileNameInCentralDirectoryHeader_ReturnsFalse()
        {
            var zipBytes = SigningTestUtility.GetResourceBytes("SignatureFileEntry.zip");
            var fileName = Encoding.ASCII.GetBytes(SigningSpecifications.V1.SignaturePath.ToUpper());

            Array.Copy(fileName, sourceIndex: 0, destinationArray: zipBytes, destinationIndex: 0x5a, length: fileName.Length);

            using (var test = new Test(zipBytes))
            {
                var isSigned = SignedPackageArchiveUtility.IsSigned(test.Reader);

                Assert.False(isSigned);
            }
        }
示例#11
0
        public async Task SignAsync_WhenPackageIsZip64_ThrowsAsync()
        {
            using (var test = SignTest.Create(
                       _fixture.GetDefaultCertificate(),
                       HashAlgorithmName.SHA256,
                       SigningTestUtility.GetResourceBytes("CentralDirectoryHeaderWithZip64ExtraField.zip")))
            {
                var exception = await Assert.ThrowsAsync <SignatureException>(
                    () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None));

                Assert.Equal(NuGetLogCode.NU3006, exception.Code);
                Assert.Equal("Signed Zip64 packages are not supported.", exception.Message);
            }
        }
        public async Task Restore_TamperedPackageInPackagesConfig_FailsWithErrorAsync()
        {
            // Arrange
            var packagesConfigContent = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                        "<packages>" +
                                        "  <package id=\"X\" version=\"9.0.0\" targetFramework=\"net461\" />" +
                                        "</packages>";

            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 = new SimpleTestProjectContext(
                        "a",
                        ProjectStyle.PackagesConfig,
                        pathContext.SolutionRoot);

                    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 packagesConfigPath = Path.Combine(Directory.GetParent(projectA.ProjectPath).FullName, "packages.config");

                    File.WriteAllBytes(packagesConfigPath, Encoding.ASCII.GetBytes(packagesConfigContent));

                    var args = new string[]
                    {
                        projectA.ProjectPath,
                        "-Source",
                        pathContext.PackageSource,
                        "-PackagesDirectory",
                        "./packages"
                    };

                    // Act
                    var result = RunRestore(_nugetExePath, pathContext, expectedExitCode: 1, additionalArgs: args);

                    // Assert
                    result.ExitCode.Should().Be(1);
                    result.Errors.Should().Contain(string.Format(_NU3008, SigningTestUtility.AddSignatureLogPrefix(_NU3008Message, packageX.Identity, pathContext.PackageSource)));
                    result.AllOutput.Should().Contain(string.Format(_NU3027, SigningTestUtility.AddSignatureLogPrefix(_NU3027Message, packageX.Identity, pathContext.PackageSource)));
                }
        }
示例#13
0
        public void GetTimestampCertificateChain_WithRepositoryCountersignatureWithoutTimestamp_Throws()
        {
            var primarySignature = PrimarySignature.Load(SigningTestUtility.GetResourceBytes(".signature.p7s"));

            primarySignature = RemoveRepositoryCountersignatureTimestamp(primarySignature);

            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            var exception = Assert.Throws <SignatureException>(
                () => SignatureUtility.GetTimestampCertificateChain(primarySignature, repositoryCountersignature));

            Assert.Equal(NuGetLogCode.NU3000, exception.Code);
            Assert.Equal("The repository countersignature does not have a timestamp.", exception.Message);
        }
示例#14
0
        public async Task Install_TamperedAndRevokedCertificateSignaturePackage_FailsAsync()
        {
            // Arrange
            var nupkg      = new SimpleTestPackageContext("A", "1.0.0");
            var testServer = await _testFixture.GetSigningTestServerAsync();

            var certificateAuthority = await _testFixture.GetDefaultTrustedCertificateAuthorityAsync();

            var issueOptions  = IssueCertificateOptions.CreateDefaultForEndCertificate();
            var bcCertificate = certificateAuthority.IssueCertificate(issueOptions);

            using (var context = new SimpleTestPathContext())
                using (var testCertificate = new X509Certificate2(bcCertificate.GetEncoded()))
                {
                    testCertificate.PrivateKey = DotNetUtilities.ToRSA(issueOptions.KeyPair.Private as RsaPrivateCrtKeyParameters);

                    var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(testCertificate, nupkg, context.WorkingDirectory);

                    SignedArchiveTestUtility.TamperWithPackage(signedPackagePath);

                    await certificateAuthority.OcspResponder.WaitForResponseExpirationAsync(bcCertificate);

                    certificateAuthority.Revoke(
                        bcCertificate,
                        RevocationReason.KeyCompromise,
                        DateTimeOffset.UtcNow.AddSeconds(-1));

                    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.Errors.Should().Contain(string.Format(_NU3012, SigningTestUtility.AddSignatureLogPrefix(_NU3012Message, nupkg.Identity, context.WorkingDirectory)));
                    result.AllOutput.Should().Contain($"WARNING: {string.Format(_NU3027, SigningTestUtility.AddSignatureLogPrefix(_NU3027Message, nupkg.Identity, context.WorkingDirectory))}");
                }
        }
示例#15
0
        public void Create_WithLargePositiveSerialNumber_ReturnsIssuerSerial()
        {
            using (var certificate = SigningTestUtility.GenerateCertificate("test", generator =>
            {
                var bytes = BitConverter.GetBytes(long.MaxValue);
                Array.Reverse(bytes);
                generator.SetSerialNumber(bytes);
            }))
            {
                var issuerSerial = IssuerSerial.Create(certificate);

                SigningTestUtility.VerifySerialNumber(certificate, issuerSerial);
            }
        }
示例#16
0
        public void CreateSignedAttributes_SignPackageRequest_WithValidInput_ReturnsAttributes()
        {
            using (var rootCertificate = SigningTestUtility.GetCertificate("root.crt"))
                using (var intermediateCertificate = SigningTestUtility.GetCertificate("intermediate.crt"))
                    using (var leafCertificate = SigningTestUtility.GetCertificate("leaf.crt"))
                        using (var request = CreateRequest(leafCertificate))
                        {
                            var certList   = new[] { leafCertificate, intermediateCertificate, rootCertificate };
                            var attributes = SigningUtility.CreateSignedAttributes(request, certList);

                            Assert.Equal(3, attributes.Count);

                            VerifyAttributes(attributes, request);
                        }
        }
示例#17
0
 public void IsValidForPurposeFast_WithAnyExtendedKeyUsage_ReturnsFalseForCodeSigningEku()
 {
     using (var certificate = SigningTestUtility.GenerateCertificate("test",
                                                                     generator =>
     {
         generator.AddExtension(
             X509Extensions.ExtendedKeyUsage.Id,
             critical: false,
             extensionValue: new ExtendedKeyUsage(KeyPurposeID.IdKPEmailProtection, KeyPurposeID.AnyExtendedKeyUsage));
     }))
     {
         Assert.Equal(2, GetExtendedKeyUsageCount(certificate));
         Assert.False(CertificateUtility.IsValidForPurposeFast(certificate, Oids.CodeSigningEku));
     }
 }
示例#18
0
 public void HasExtendedKeyUsage_WithEku_ReturnsTrueForEku()
 {
     using (var certificate = SigningTestUtility.GenerateCertificate("test",
                                                                     generator =>
     {
         generator.AddExtension(
             X509Extensions.ExtendedKeyUsage.Id,
             critical: false,
             extensionValue: new ExtendedKeyUsage(KeyPurposeID.IdKPCodeSigning));
     }))
     {
         Assert.Equal(1, GetExtendedKeyUsageCount(certificate));
         Assert.True(CertificateUtility.HasExtendedKeyUsage(certificate, Oids.CodeSigningEku));
     }
 }
        public void Create_WithSha512_ReturnsEssCertIdV2()
        {
            var hashAlgorithmName = HashAlgorithmName.SHA512;

            using (var certificate = _fixture.GetDefaultCertificate())
            {
                var essCertIdV2 = EssCertIdV2.Create(certificate, hashAlgorithmName);

                Assert.Equal(SigningTestUtility.GetHash(certificate, hashAlgorithmName), essCertIdV2.CertificateHash);
                Assert.Equal(Oids.Sha512, essCertIdV2.HashAlgorithm.Algorithm.Value);
                Assert.Equal(1, essCertIdV2.IssuerSerial.GeneralNames.Count);
                Assert.Equal(certificate.IssuerName.Name, essCertIdV2.IssuerSerial.GeneralNames[0].DirectoryName.Name);
                SigningTestUtility.VerifySerialNumber(certificate, essCertIdV2.IssuerSerial);
            }
        }
        public async Task SignAsync_WhenCertificateSignatureAlgorithmIsUnsupported_ThrowsAsync()
        {
            using (var certificate = SigningTestUtility.GenerateCertificate(
                       "test",
                       generator => { },
                       "SHA256WITHRSAANDMGF1"))
                using (var test = SignTest.Create(certificate, HashAlgorithmName.SHA256))
                {
                    var exception = await Assert.ThrowsAsync <SignatureException>(
                        () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None));

                    Assert.Equal(NuGetLogCode.NU3013, exception.Code);
                    Assert.Contains("The signing certificate has an unsupported signature algorithm.", exception.Message);
                }
        }
示例#21
0
        public async Task SignAsync_WhenCertificatePublicKeyLengthIsUnsupported_ThrowsAsync()
        {
            using (var certificate = SigningTestUtility.GenerateCertificate(
                       "test",
                       generator => { },
                       publicKeyLength: 1024))
                using (var test = SignTest.Create(certificate, HashAlgorithmName.SHA256))
                {
                    var exception = await Assert.ThrowsAsync <SignatureException>(
                        () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None));

                    Assert.Equal(NuGetLogCode.NU3014, exception.Code);
                    Assert.Contains("The signing certificate does not meet a minimum public key length requirement.", exception.Message);
                }
        }
示例#22
0
        public void GetCertificateChain_WithUntrustedRoot_Throws()
        {
            using (var chainHolder = new X509ChainHolder())
                using (var rootCertificate = SigningTestUtility.GetCertificate("root.crt"))
                    using (var intermediateCertificate = SigningTestUtility.GetCertificate("intermediate.crt"))
                        using (var leafCertificate = SigningTestUtility.GetCertificate("leaf.crt"))
                        {
                            var chain      = chainHolder.Chain;
                            var extraStore = new X509Certificate2Collection()
                            {
                                rootCertificate, intermediateCertificate
                            };
                            var logger = new TestLogger();

                            var exception = Assert.Throws <SignatureException>(
                                () => CertificateChainUtility.GetCertificateChain(
                                    leafCertificate,
                                    extraStore,
                                    logger,
                                    CertificateType.Signature));

                            Assert.Equal(NuGetLogCode.NU3018, exception.Code);
                            Assert.Equal("Certificate chain validation failed.", exception.Message);

                            Assert.Equal(1, logger.Errors);
                            SigningTestUtility.AssertUntrustedRoot(logger.LogMessages, LogLevel.Error);

                            SigningTestUtility.AssertRevocationStatusUnknown(logger.LogMessages, LogLevel.Warning);
                            if (RuntimeEnvironmentHelper.IsWindows)
                            {
                                Assert.Equal(2, logger.Warnings);
                                SigningTestUtility.AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning);
                            }
                            else if (RuntimeEnvironmentHelper.IsLinux)
                            {
#if NETCORE5_0
                                Assert.Equal(2, logger.Warnings);
                                SigningTestUtility.AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning);
#else
                                Assert.Equal(1, logger.Warnings);
#endif
                            }
                            else
                            {
                                Assert.Equal(1, logger.Warnings);
                            }
                        }
        }
        public async Task TimestampSignatureAsync_TimestampingCountersignature_Succeeds()
        {
            var logger           = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url);
            var signatureContent  = new SignatureContent(SigningSpecifications.V1, Common.HashAlgorithmName.SHA256, "Test data to be signed and timestamped");

            using (var authorCert = new X509Certificate2(_trustedTestCert.Source.Cert))
            {
                var timestampHashAlgorithm = Common.HashAlgorithmName.SHA256;
                var signedCms      = SigningTestUtility.GenerateRepositoryCountersignedSignedCms(authorCert, signatureContent.GetBytes());
                var signature      = PrimarySignature.Load(signedCms.Encode());
                var signatureValue = signature.GetSignatureValue();
                var messageHash    = timestampHashAlgorithm.ComputeHash(signatureValue);

                var request = new TimestampRequest(
                    SigningSpecifications.V1,
                    messageHash,
                    timestampHashAlgorithm,
                    SignaturePlacement.Countersignature);

                // Act
                var primarySignature = await timestampProvider.TimestampSignatureAsync(signature, request, logger, CancellationToken.None);

                var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

                // Assert
                repositoryCountersignature.Should().NotBeNull();
                repositoryCountersignature.SignerInfo.Should().NotBeNull();
                repositoryCountersignature.SignerInfo.UnsignedAttributes.Count.Should().BeGreaterOrEqualTo(1);

                var hasTimestampUnsignedAttribute = false;
                var timestampCms = new SignedCms();

                foreach (var attr in repositoryCountersignature.SignerInfo.UnsignedAttributes)
                {
                    if (string.Compare(attr.Oid.Value, Oids.SignatureTimeStampTokenAttribute, CultureInfo.CurrentCulture, CompareOptions.Ordinal) == 0)
                    {
                        hasTimestampUnsignedAttribute = true;
                        timestampCms.Decode(attr.Values[0].RawData);
                    }
                }
                hasTimestampUnsignedAttribute.Should().BeTrue();

                timestampCms.CheckSignature(verifySignatureOnly: true);
            }
        }
示例#24
0
        public CertificatesFixture()
        {
            Key = RSA.Create(keySizeInBits: 2048);
            _defaultCertificate   = SigningTestUtility.GenerateCertificate("test", Key);
            _rsaSsaPssCertificate = SigningTestUtility.GenerateCertificate("test",
                                                                           generator => { },
                                                                           hashAlgorithm: Common.HashAlgorithmName.SHA256,
                                                                           paddingMode: RSASignaturePaddingMode.Pss);
            _lifetimeSigningCertificate = SigningTestUtility.GenerateCertificate(
                "test",
                generator =>
            {
                generator.Extensions.Add(
                    new X509EnhancedKeyUsageExtension(
                        new OidCollection {
                    new Oid(Oids.LifetimeSigningEku)
                },
                        critical: true));
            });
            _expiredCertificate = SigningTestUtility.GenerateCertificate(
                "test",
                SigningTestUtility.CertificateModificationGeneratorExpiredCert);
            _notYetValidCertificate = SigningTestUtility.GenerateCertificate(
                "test",
                SigningTestUtility.CertificateModificationGeneratorNotYetValidCert);
            _nonSelfSignedCertificate = SigningTestUtility.GenerateCertificate(
                "test non-self-signed certificate", // Must be different than the issuing certificate's subject name.
                generator => { },
                chainCertificateRequest: new ChainCertificateRequest()
            {
                Issuer = _defaultCertificate
            });
            _selfIssuedCertificate = SigningTestUtility.GenerateSelfIssuedCertificate(isCa: false);
            _rootCertificate       = SigningTestUtility.GenerateSelfIssuedCertificate(isCa: true);

            const string name1 = "NuGet Cyclic Test Certificate 1";
            const string name2 = "NuGet Cyclic Test Certificate 2";

            using (var rsa1 = RSA.Create(keySizeInBits: 2048))
                using (var rsa2 = RSA.Create(keySizeInBits: 2048))
                {
                    _cyclicChain = new DisposableList <X509Certificate2>()
                    {
                        SigningTestUtility.GenerateCertificate(name1, name2, rsa1, rsa2),
                        SigningTestUtility.GenerateCertificate(name2, name1, rsa2, rsa1)
                    };
                }
        }
示例#25
0
        [InlineData(null)]                   // No commitment type.
        public async Task AllowsNonAuthorAndRepositoryCounterSignatures(string commitmentTypeOidBase64)
        {
            // Arrange
            _message = new SignatureValidationMessage(
                TestResources.SignedPackageLeafId,
                TestResources.SignedPackageLeaf1Version,
                new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                Guid.NewGuid());
            var packageStream = await GetSignedPackageStream1Async();

            ModifySignatureContent(
                packageStream,
                configuredSignedCms: signedCms =>
            {
                using (var counterCertificate = SigningTestUtility.GenerateCertificate(subjectName: null, modifyGenerator: null))
                {
                    var cmsSigner = new CmsSigner(counterCertificate);

                    if (commitmentTypeOidBase64 != null)
                    {
                        var value = new AsnEncodedData(
                            Oids.CommitmentTypeIndication,
                            Convert.FromBase64String(commitmentTypeOidBase64));

                        var attribute = new CryptographicAttributeObject(
                            new Oid(Oids.CommitmentTypeIndication),
                            new AsnEncodedDataCollection(value));

                        cmsSigner.SignedAttributes.Add(attribute);
                    }

                    signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner);
                }
            });

            // Act
            var result = await _target.ValidateAsync(
                _packageKey,
                _packageStream,
                _message,
                _token);

            // Assert
            VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);

            // This failure type indicates the counter signature validation passed.
            VerifyNU3008(result);
        }
        private void CreateSignedPackageWithExpiredCertificate()
        {
            _expiredSignedTestPackageV1Directory = TestDirectory.Create();
            _trustedExpiredTestCert = SigningTestUtility.GenerateTrustedTestCertificateThatExpiresIn5Seconds();

            _expiredSignedTestPackageV1 = Utils.CreatePackage(_expiredTestPackageName, _packageVersion);
            _expiredSignedTestPackageV1.AuthorSignatureCertificate = _trustedExpiredTestCert.Source.Cert;

            SimpleTestPackageUtility.CreatePackages(_expiredSignedTestPackageV1Directory, _expiredSignedTestPackageV1);
            _expiredSignedTestPackageV1Path = Path.Combine(_expiredSignedTestPackageV1Directory, _expiredSignedTestPackageV1.PackageName);

            // Wait for cert to expire
            Thread.Sleep(5000);

            Assert.True(IsCertificateExpired(_trustedExpiredTestCert.Source.Cert));
        }
        public void OpenPackageSignatureFileStream_WithFakeContent_ReturnsContent()
        {
            using (var test = new Test(SigningTestUtility.GetResourceBytes("SignatureFileWithFakeContent.zip")))
                using (var stream = SignedPackageArchiveUtility.OpenPackageSignatureFileStream(test.Reader))
                {
                    Assert.False(stream.CanWrite);

                    using (var reader = new BinaryReader(stream))
                    {
                        var expectedBytes = Encoding.ASCII.GetBytes("content");
                        var actualBytes   = reader.ReadBytes((int)reader.BaseStream.Length);

                        Assert.Equal(expectedBytes, actualBytes);
                    }
                }
        }
示例#28
0
        private async Task <X509Certificate2> CreateDefaultRepositorySigningCertificateAsync()
        {
            var ca = await CreateDefaultTrustedCertificateAuthorityAsync();

            var keyPair      = SigningTestUtility.GenerateKeyPair(publicKeyLength: 2048);
            var issueOptions = new IssueCertificateOptions()
            {
                KeyPair     = keyPair,
                NotBefore   = DateTimeOffset.UtcNow.AddSeconds(-2),
                NotAfter    = DateTimeOffset.UtcNow.AddHours(1),
                SubjectName = new X509Name("CN=NuGet Cross Verify Test Repository Signning Certificate")
            };
            var bcCertificate = ca.IssueCertificate(issueOptions);

            return(CertificateUtilities.GetCertificateWithPrivateKey(bcCertificate, keyPair));
        }
        public void ReadSignedArchiveMetadata_WithSignedPackage_ReturnsMetadata()
        {
            using (var stream = new MemoryStream(SigningTestUtility.GetResourceBytes("SignedPackage.1.0.0.nupkg")))
                using (var reader = new BinaryReader(stream))
                {
                    var metadata = SignedPackageArchiveIOUtility.ReadSignedArchiveMetadata(reader);

                    Assert.Equal(0, metadata.StartOfLocalFileHeaders);

                    Assert.Equal(6, metadata.CentralDirectoryHeaders.Count);
                    Assert.Equal(0xd7c, metadata.EndOfCentralDirectory);

                    Assert.Equal(5, metadata.SignatureCentralDirectoryHeaderIndex);

                    var expectedHeaders = new[]
                    {
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0x136, HeaderSize = 0x39, IndexInHeaders = 0,
                              IsPackageSignatureFile = false, OffsetToFileHeader = 0, Position = 0xbcc },
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0x110, HeaderSize = 0x42, IndexInHeaders = 1,
                              IsPackageSignatureFile = false, OffsetToFileHeader = 0x136, Position = 0xc05 },
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0x29, HeaderSize = 0x39, IndexInHeaders = 2,
                              IsPackageSignatureFile = false, OffsetToFileHeader = 0x246, Position = 0xc47 },
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0xff, HeaderSize = 0x41, IndexInHeaders = 3,
                              IsPackageSignatureFile = false, OffsetToFileHeader = 0x26f, Position = 0xc80 },
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0x1dd, HeaderSize = 0x7f, IndexInHeaders = 4,
                              IsPackageSignatureFile = false, OffsetToFileHeader = 0x36e, Position = 0xcc1 },
                        new { ChangeInOffset         = 0L, FileEntryTotalSize = 0x681, HeaderSize = 0x3c, IndexInHeaders = 5,
                              IsPackageSignatureFile = true, OffsetToFileHeader = 0x54b, Position = 0xd40 },
                    };

                    Assert.Equal(expectedHeaders.Length, metadata.CentralDirectoryHeaders.Count);

                    for (var i = 0; i < expectedHeaders.Length; ++i)
                    {
                        var expectedHeader = expectedHeaders[i];
                        var actualHeader   = metadata.CentralDirectoryHeaders[i];

                        Assert.Equal(expectedHeader.Position, actualHeader.Position);
                        Assert.Equal(expectedHeader.OffsetToFileHeader, actualHeader.OffsetToLocalFileHeader);
                        Assert.Equal(expectedHeader.FileEntryTotalSize, actualHeader.FileEntryTotalSize);
                        Assert.Equal(expectedHeader.IsPackageSignatureFile, actualHeader.IsPackageSignatureFile);
                        Assert.Equal(expectedHeader.HeaderSize, actualHeader.HeaderSize);
                        Assert.Equal(expectedHeader.ChangeInOffset, actualHeader.ChangeInOffset);
                        Assert.Equal(expectedHeader.IndexInHeaders, actualHeader.IndexInHeaders);
                    }
                }
        }
        public async Task TrustedSignersCommand_AddTrustedSigner_WithAuthorSignedPackage_AddsItSuccesfullyToConfigAsync(bool allowUntrustedRoot)
        {
            // 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 trustedTestCert = SigningTestUtility.GenerateTrustedTestCertificate())
                    {
                        var certFingerprint   = SignatureTestUtility.GetFingerprint(trustedTestCert.Source.Cert, HashAlgorithmName.SHA256);
                        var signedPackagePath = await SignedArchiveTestUtility.AuthorSignPackageAsync(trustedTestCert.Source.Cert, package, dir);

                        SettingsTestUtils.CreateConfigurationFile(nugetConfigFileName, dir, config);
                        var nugetConfigPath       = Path.Combine(dir, nugetConfigFileName);
                        var allowUntrustedRootArg = allowUntrustedRoot ? "-AllowUntrustedRoot" : string.Empty;

                        // Act
                        var commandResult = CommandRunner.Run(
                            _nugetExePath,
                            dir,
                            $"trusted-signers add {signedPackagePath} -Name signer -Author {allowUntrustedRootArg} -Config {nugetConfigPath}",
                            waitForExit: true);

                        // Assert
                        commandResult.Success.Should().BeTrue();
                        commandResult.AllOutput.Should().Contain(string.Format(CultureInfo.CurrentCulture, _successfulAddTrustedSigner, "author", "signer"));

                        var expectedResult = SettingsTestUtils.RemoveWhitespace($@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<trustedSigners>
    <author name=""signer"">
        <certificate fingerprint=""{certFingerprint}"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""{allowUntrustedRoot.ToString().ToLower()}"" />
    </author>
</trustedSigners>
</configuration>");

                        SettingsTestUtils.RemoveWhitespace(File.ReadAllText(nugetConfigPath)).Should().Be(expectedResult);
                    }
        }