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);
                        }
        }
        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.Equal("The signing certificate has an unsupported signature algorithm.", exception.Message);
                }
        }
        public void CreateSignedAttributes_RepositorySignPackageRequest_WhenPackageOwnersNonEmpty_ReturnsAttributes()
        {
            var v3ServiceIndexUrl = new Uri("https://test.test", UriKind.Absolute);
            var packageOwners     = new[] { "a" };

            using (var certificate = _fixture.GetDefaultCertificate())
                using (var request = CreateRequestRepository(certificate, v3ServiceIndexUrl, packageOwners))
                {
                    var attributes = SigningUtility.CreateSignedAttributes(request, new[] { certificate });

                    Assert.Equal(5, attributes.Count);

                    VerifyAttributesRepository(attributes, request);
                }
        }
        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.Equal("The signing certificate does not meet a minimum public key length requirement.", exception.Message);
                }
        }
示例#5
0
 public static async Task CreateSignedPackageAsync(
     SignPackageRequest request,
     Stream packageReadStream,
     Stream packageWriteStream)
 {
     using (var signedPackage = new SignedPackageArchive(packageReadStream, packageWriteStream))
         using (var options = new SigningOptions(
                    new Lazy <Stream>(() => packageReadStream),
                    new Lazy <Stream>(() => packageWriteStream),
                    overwrite: false,
                    signatureProvider: new X509SignatureProvider(timestampProvider: null),
                    logger: NullLogger.Instance))
         {
             await SigningUtility.SignAsync(options, request, CancellationToken.None);
         }
 }
示例#6
0
        public async Task SignAsync_WhenCertificateSignatureAlgorithmIsUnsupported_ThrowsAsync()
        {
            using (var certificate = SigningTestUtility.GenerateCertificate(
                       "test",
                       generator => { },
                       Common.HashAlgorithmName.SHA256,
                       System.Security.Cryptography.RSASignaturePaddingMode.Pss))
                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);
                }
        }
        public async Task SignAsync_WithNotYetValidCertificate_ThrowsAsync()
        {
            using (var test = await Test.CreateAsync(_testFixture.TrustedTestCertificateNotYetValid.Source.Cert))
            {
                var exception = await Assert.ThrowsAsync <SignatureException>(
                    () => SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None));

                Assert.Equal(NuGetLogCode.NU3017, exception.Code);
                Assert.Contains("The signing certificate is not yet valid", exception.Message);

                var isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.InputPackageStream);

                Assert.False(isSigned);

                Assert.False(test.OutputFile.Exists);
            }
        }
示例#8
0
        public async Task SignAsync_WithExpiredCertificate_ThrowsAsync()
        {
            using (var test = new Test(_testFixture.TrustedTestCertificateExpired.Source.Cert))
            {
                var exception = await Assert.ThrowsAsync <SignatureException>(
                    () => SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None));

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

                var isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.InputPackageStream);

                Assert.False(isSigned);

                Assert.False(test.OutputFile.Exists);
            }
        }
示例#9
0
        public void GetCertificateChain_WithUntrustedRoot_Throws()
        {
            using (var chain = new X509Chain())
                using (var rootCertificate = GetCertificate("root.crt"))
                    using (var intermediateCertificate = GetCertificate("intermediate.crt"))
                        using (var leafCertificate = GetCertificate("leaf.crt"))
                        {
                            var extraStore = new X509Certificate2Collection();

                            extraStore.Add(rootCertificate);
                            extraStore.Add(intermediateCertificate);

                            var exception = Assert.Throws <SignatureException>(
                                () => SigningUtility.GetCertificateChain(leafCertificate, extraStore));

                            Assert.Equal(NuGetLogCode.NU3018, exception.Code);
                        }
        }
        public async Task SignAsync_WhenRepositoryCountersigningRepositoryCountersignedPackage_ThrowsAsync()
        {
            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 isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream);

                    Assert.True(isSigned);
                }

                var countersignedPackageOutputPath = test.GetNewTempFilePath();
                using (var countersignatureOptions = SigningOptions.CreateFromFilePaths(
                           test.OutputFile.FullName,
                           countersignedPackageOutputPath,
                           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);
                }

                using (var countersignatureOptions = SigningOptions.CreateFromFilePaths(
                           countersignedPackageOutputPath,
                           test.GetNewTempFilePath(),
                           overwrite: false,
                           signatureProvider: new X509SignatureProvider(timestampProvider: null),
                           logger: NullLogger.Instance))
                {
                    var exception = await Assert.ThrowsAsync <SignatureException>(
                        () => SigningUtility.SignAsync(countersignatureOptions, test.RepositoryRequest, CancellationToken.None));

                    Assert.Equal(NuGetLogCode.NU3032, exception.Code);
                    Assert.Contains("The package already contains a repository countersignature", exception.Message);
                }
            }
        }
示例#11
0
        /// <summary>
        /// Generates a SignedCMS object for some content.
        /// </summary>
        /// <param name="content"></param>
        /// <param name="cert">Certificate for cms signer</param>
        /// <returns>SignedCms object</returns>
        public static SignedCms GenerateRepositoryCountersignedSignedCms(X509Certificate2 cert, byte[] content)
        {
            var contentInfo   = new ContentInfo(content);
            var hashAlgorithm = NuGet.Common.HashAlgorithmName.SHA256;

            using (var primarySignatureRequest = new AuthorSignPackageRequest(new X509Certificate2(cert), hashAlgorithm))
                using (var countersignatureRequest = new RepositorySignPackageRequest(new X509Certificate2(cert), hashAlgorithm, hashAlgorithm, new Uri("https://api.nuget.org/v3/index.json"), null))
                {
                    var cmsSigner = SigningUtility.CreateCmsSigner(primarySignatureRequest, NullLogger.Instance);

                    var cms = new SignedCms(contentInfo);
                    cms.ComputeSignature(cmsSigner);

                    var counterCmsSigner = SigningUtility.CreateCmsSigner(countersignatureRequest, NullLogger.Instance);
                    cms.SignerInfos[0].ComputeCounterSignature(counterCmsSigner);

                    return(cms);
                }
        }
示例#12
0
        public async Task SignAsync_WithUntrustedSelfSignedCertificate_SucceedsAsync()
        {
            using (var packageStream = new SimpleTestPackageContext().CreateAsStream())
                using (var test = SignTest.Create(
                           _fixture.GetDefaultCertificate(),
                           HashAlgorithmName.SHA256,
                           packageStream.ToArray(),
                           new X509SignatureProvider(timestampProvider: null)))
                {
                    await SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None);

                    Assert.True(await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream));

                    Assert.Equal(0, test.Logger.Errors);
                    Assert.Equal(1, test.Logger.Warnings);
                    Assert.Equal(1, test.Logger.Messages.Count());
                    Assert.True(test.Logger.Messages.Contains("A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider."));
                }
        }
示例#13
0
        public async Task SignAsync_WhenPackageEntryCountWouldRequireZip64_FailsAsync()
        {
            const ushort desiredFileCount = 0xFFFF - 1;

            var package = new SimpleTestPackageContext();

            var requiredFileCount = desiredFileCount - package.Files.Count;

            for (var i = 0; i < requiredFileCount - 1 /*nuspec*/; ++i)
            {
                package.AddFile(i.ToString());
            }

            using (var packageStream = await package.CreateAsStreamAsync())
            {
                using (var zipArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, leaveOpen: true))
                {
                    // Sanity check before testing.
                    Assert.Equal(desiredFileCount, zipArchive.Entries.Count());
                }

                packageStream.Position = 0;

                using (var test = SignTest.Create(
                           _fixture.GetDefaultCertificate(),
                           HashAlgorithmName.SHA256,
                           packageStream.ToArray(),
                           new X509SignatureProvider(timestampProvider: null)))
                {
                    var exception = await Assert.ThrowsAsync <SignatureException>(
                        () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None));

                    Assert.Equal(NuGetLogCode.NU3039, exception.Code);
                    Assert.Equal("The package cannot be signed as it would require the Zip64 format.", exception.Message);

                    Assert.Equal(0, test.Options.OutputPackageStream.Length);
                    Assert.Equal(0, test.Logger.Errors);
                    Assert.Equal(1, test.Logger.Warnings);
                    Assert.Equal(1, test.Logger.Messages.Count());
                    Assert.True(test.Logger.Messages.Contains("A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider."));
                }
            }
        }
示例#14
0
        public void Verify_WithUntrustedSelfSignedCertificate_Succeeds()
        {
            using (var certificate = _fixture.GetDefaultCertificate())
                using (var request = CreateRequest(certificate))
                {
                    var logger = new TestLogger();

                    SigningUtility.Verify(request, logger);

                    Assert.Equal(0, logger.Errors);
                    Assert.Equal(RuntimeEnvironmentHelper.IsWindows ? 1 : 2, logger.Warnings);

                    AssertUntrustedRoot(logger.LogMessages, LogLevel.Warning);

                    if (!RuntimeEnvironmentHelper.IsWindows)
                    {
                        AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning);
                    }
                }
        }
示例#15
0
        /// <summary>
        /// Sign and timestamp a package for test purposes.
        /// This method timestamps a package and should only be used with tests marked with [CIOnlyFact]
        /// </summary>
        private static async Task SignAndTimeStampPackageAsync(
            TestLogger testLogger,
            string inputPackagePath,
            string outputPackagePath,
            Uri timestampService,
            AuthorSignPackageRequest request)
        {
            var testSignatureProvider = new X509SignatureProvider(new Rfc3161TimestampProvider(timestampService));
            var overwrite             = false;

            using (var options = SigningOptions.CreateFromFilePaths(
                       inputPackagePath,
                       outputPackagePath,
                       overwrite,
                       testSignatureProvider,
                       testLogger))
            {
                await SigningUtility.SignAsync(options, request, CancellationToken.None);
            }
        }
示例#16
0
        public void GetCertificateChain_ReturnsCertificatesInOrder()
        {
            using (var chain = new X509Chain())
                using (var rootCertificate = GetCertificate("root.crt"))
                    using (var intermediateCertificate = GetCertificate("intermediate.crt"))
                        using (var leafCertificate = GetCertificate("leaf.crt"))
                        {
                            chain.ChainPolicy.ExtraStore.Add(rootCertificate);
                            chain.ChainPolicy.ExtraStore.Add(intermediateCertificate);

                            chain.Build(leafCertificate);

                            var certificateChain = SigningUtility.GetCertificateChain(chain);

                            Assert.Equal(3, certificateChain.Count);
                            Assert.Equal(leafCertificate.Thumbprint, certificateChain[0].Thumbprint);
                            Assert.Equal(intermediateCertificate.Thumbprint, certificateChain[1].Thumbprint);
                            Assert.Equal(rootCertificate.Thumbprint, certificateChain[2].Thumbprint);
                        }
        }
示例#17
0
        /// <summary>
        /// Sign a package for test purposes.
        /// This does not timestamp a signature and can be used outside corp network.
        /// </summary>
        private static async Task SignPackageAsync(TestLogger testLogger, X509Certificate2 certificate, string inputPackagePath, string outputPackagePath)
        {
#if IS_DESKTOP
            var testSignatureProvider = new X509SignatureProvider(timestampProvider: null);
            using (var cert = new X509Certificate2(certificate))
                using (var request = new AuthorSignPackageRequest(cert, HashAlgorithmName.SHA256))
                {
                    const bool overwrite = false;
                    using (var options = SigningOptions.CreateFromFilePaths(
                               inputPackagePath,
                               outputPackagePath,
                               overwrite,
                               testSignatureProvider,
                               testLogger))
                    {
                        await SigningUtility.SignAsync(options, request, CancellationToken.None);
                    }
                }
#endif
        }
示例#18
0
        public void CreateCmsSigner_WithRepositorySignPackageRequest_ReturnsInstance()
        {
            var v3ServiceIndexUrl = new Uri("https://test.test", UriKind.Absolute);
            var packageOwners     = new[] { "a", "b", "c" };

            using (var certificate = _fixture.GetDefaultCertificate())
                using (var request = new RepositorySignPackageRequest(
                           certificate,
                           Common.HashAlgorithmName.SHA256,
                           Common.HashAlgorithmName.SHA256,
                           v3ServiceIndexUrl,
                           packageOwners))
                {
                    var signer = SigningUtility.CreateCmsSigner(request, NullLogger.Instance);

                    Assert.Equal(request.Certificate, signer.Certificate);
                    Assert.Equal(request.SignatureHashAlgorithm.ConvertToOidString(), signer.DigestAlgorithm.Value);

                    VerifyAttributesRepository(signer.SignedAttributes, request);
                }
        }
        public async Task SignAsync_WithUntrustedSelfSignedCertificate_SucceedsAsync()
        {
            var package = new SimpleTestPackageContext();

            using (var packageStream = await package.CreateAsStreamAsync())
                using (var test = SignTest.Create(
                           _fixture.GetDefaultCertificate(),
                           HashAlgorithmName.SHA256,
                           packageStream.ToArray(),
                           new X509SignatureProvider(timestampProvider: null)))
                {
                    await SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None);

                    Assert.True(await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream));

                    Assert.Equal(0, test.Logger.Errors);
                    Assert.Equal(1, test.Logger.Warnings);
                    Assert.Equal(1, test.Logger.Messages.Count());
                    SigningTestUtility.AssertUntrustedRoot(test.Logger.LogMessages, LogLevel.Warning);
                }
        }
示例#20
0
        public async Task <bool> SignAsync(string packagePath, string outputPath, string timestampUrl, HashAlgorithmName signatureHashAlgorithm, HashAlgorithmName timestampHashAlgorithm, bool overwrite, X509Certificate2 publicCertificate, System.Security.Cryptography.RSA rsa)
        {
            var fileName = Path.GetFileName(packagePath);

            logger.LogInformation($"{nameof(SignAsync)} [{fileName}]: Begin Signing {packagePath}");
            var signatureProvider = new KeyVaultSignatureProvider(rsa, new Rfc3161TimestampProvider(new Uri(timestampUrl)));

            var request = new AuthorSignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm);

            string originalPackageCopyPath = null;

            try
            {
                originalPackageCopyPath = CopyPackage(packagePath);

                using (var options = SigningOptions.CreateFromFilePaths(originalPackageCopyPath, outputPath, overwrite, signatureProvider, new NuGetLogger(logger, fileName)))
                {
                    await SigningUtility.SignAsync(options, request, CancellationToken.None);
                }
            }
            catch (Exception e)
            {
                logger.LogError(e, e.Message);
                return(false);
            }
            finally
            {
                try
                {
                    FileUtility.Delete(originalPackageCopyPath);
                }
                catch
                {
                }

                logger.LogInformation($"{nameof(SignAsync)} [{fileName}]: End Signing {packagePath}");
            }

            return(true);
        }
            internal async Task RepositoryCountersignAsync()
            {
                PrimarySignature primarySignature;

                using (var archiveReader = new PackageArchiveReader(SignedPackage))
                {
                    primarySignature = await archiveReader.GetPrimarySignatureAsync(CancellationToken.None);
                }

                using (var request = new RepositorySignPackageRequest(
                           new X509Certificate2(Certificate),
                           HashAlgorithmName.SHA256,
                           HashAlgorithmName.SHA256,
                           new Uri("https://test.test"),
                           packageOwners: null))
                {
                    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 SignAsync_WhenChainBuildingFails_ThrowsAsync()
        {
            var package = new SimpleTestPackageContext();

            using (var packageStream = await package.CreateAsStreamAsync())
                using (var test = SignTest.Create(
                           _fixture.GetExpiredCertificate(),
                           HashAlgorithmName.SHA256,
                           packageStream.ToArray(),
                           new X509SignatureProvider(timestampProvider: null)))
                {
                    var exception = await Assert.ThrowsAsync <SignatureException>(
                        () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None));

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

                    Assert.Equal(1, test.Logger.Errors);
                    Assert.Equal(1, test.Logger.Warnings);
                    SigningTestUtility.AssertNotTimeValid(test.Logger.LogMessages, LogLevel.Error);
                    SigningTestUtility.AssertUntrustedRoot(test.Logger.LogMessages, LogLevel.Warning);
                }
        }
            internal static async Task <Test> CreateAsync(
                X509Certificate2 certificate,
                Uri v3ServiceIndexUrl = null,
                IReadOnlyList <string> packageOwners = null)
            {
                v3ServiceIndexUrl = v3ServiceIndexUrl ?? new Uri("https://test.test");

                var test = await CreateWithoutRepositoryCountersignatureAsync(certificate);

                var request = new RepositorySignPackageRequest(
                    new X509Certificate2(certificate),
                    HashAlgorithmName.SHA256,
                    HashAlgorithmName.SHA256,
                    v3ServiceIndexUrl,
                    packageOwners);
                var cmsSigner = SigningUtility.CreateCmsSigner(request, NullLogger.Instance);
                var signedCms = test.PrimarySignature.SignedCms;

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

                var primarySignature = PrimarySignature.Load(signedCms.Encode());

                return(new Test(request, primarySignature));
            }
示例#24
0
        public async Task <int> ExecuteCommandAsync(
            IEnumerable <string> packagesToSign,
            SignPackageRequest signPackageRequest,
            string timestamper,
            ILogger logger,
            string outputDirectory,
            bool overwrite,
            CancellationToken token)
        {
            var success = true;

            try
            {
                SigningUtility.Verify(signPackageRequest, logger);
            }
            catch (Exception e)
            {
                success = false;
                ExceptionUtilities.LogException(e, logger);
            }

            if (success)
            {
                var signatureProvider = GetSignatureProvider(timestamper);

                foreach (var packagePath in packagesToSign)
                {
                    // Set the output of the signing operation to a temp file because signing cannot be done in place.
                    var tempPackageFile = new FileInfo(Path.GetTempFileName());

                    try
                    {
                        string outputPath;

                        if (string.IsNullOrEmpty(outputDirectory))
                        {
                            outputPath = packagePath;
                        }
                        else
                        {
                            outputPath = Path.Combine(outputDirectory, Path.GetFileName(packagePath));
                        }

                        using (var options = SigningOptions.CreateFromFilePaths(
                                   packagePath,
                                   tempPackageFile.FullName,
                                   overwrite,
                                   signatureProvider,
                                   logger))
                        {
                            await SigningUtility.SignAsync(options, signPackageRequest, token);
                        }

                        if (tempPackageFile.Length > 0)
                        {
                            FileUtility.Replace(tempPackageFile.FullName, outputPath);
                        }
                        else
                        {
                            throw new SignatureException(Strings.Error_UnableToSignPackage);
                        }
                    }
                    catch (Exception e)
                    {
                        success = false;
                        ExceptionUtilities.LogException(e, logger);
                    }
                    finally
                    {
                        FileUtility.Delete(tempPackageFile.FullName);
                    }
                }
            }

            if (success)
            {
                logger.LogInformation(Strings.SignCommandSuccess);
            }

            return(success ? 0 : 1);
        }