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);
                }
            }
        }
示例#2
0
        public void CreateFromFilePaths_WithValidInput_InitializesProperties()
        {
            using (var directory = TestDirectory.Create())
            {
                var inputPackageFilePath  = Path.Combine(directory, "a");
                var outputPackageFilePath = Path.Combine(directory, "b");
                var overwrite             = false;
                var signatureProvider     = Mock.Of <ISignatureProvider>();
                var logger = Mock.Of <ILogger>();

                File.WriteAllBytes(inputPackageFilePath, Array.Empty <byte>());

                using (var options = SigningOptions.CreateFromFilePaths(
                           inputPackageFilePath,
                           outputPackageFilePath,
                           overwrite,
                           signatureProvider,
                           logger))
                {
                    Assert.NotNull(options.InputPackageStream);
                    Assert.NotNull(options.OutputPackageStream);
                    Assert.Equal(overwrite, options.Overwrite);
                    Assert.Same(signatureProvider, options.SignatureProvider);
                    Assert.Same(logger, options.Logger);
                }
            }
        }
        public async Task SignAsync_WhenRepositoryCountersigningRepositorySignedPackage_ThrowsAsync()
        {
            using (var test = await Test.CreateAsync(_testFixture.TrustedTestCertificate.Source.Cert))
            {
                await SigningUtility.SignAsync(test.Options, test.RepositoryRequest, CancellationToken.None);

                using (var package = new PackageArchiveReader(test.Options.OutputPackageStream))
                {
                    var primarySignature = await package.GetPrimarySignatureAsync(CancellationToken.None);

                    Assert.IsType <RepositoryPrimarySignature>(primarySignature);
                }

                using (var countersignatureOptions = SigningOptions.CreateFromFilePaths(
                           test.OutputFile.FullName,
                           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.NU3033, exception.Code);
                    Assert.Contains("A repository primary signature must not have a repository countersignature", exception.Message);
                }
            }
        }
        public async Task <bool> SignAsync(string packagePath, string outputPath, string timestampUrl, Uri v3ServiceIndex, IReadOnlyList <string> packageOwners,
                                           SignatureType signatureType, HashAlgorithmName signatureHashAlgorithm, HashAlgorithmName timestampHashAlgorithm,
                                           bool overwrite, X509Certificate2 publicCertificate, System.Security.Cryptography.RSA rsa, CancellationToken cancellationToken = default)
        {
            var packagesToSign = LocalFolderUtility.ResolvePackageFromPath(packagePath);

            var signatureProvider = new KeyVaultSignatureProvider(rsa, new Rfc3161TimestampProvider(new Uri(timestampUrl)));

            SignPackageRequest request = null;

            if (signatureType == SignatureType.Author)
            {
                request = new AuthorSignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm);
            }
            else if (signatureType == SignatureType.Repository)
            {
                request = new RepositorySignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm, v3ServiceIndex, packageOwners);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(signatureType));
            }

            string originalPackageCopyPath = null;

            foreach (var package in packagesToSign)
            {
                cancellationToken.ThrowIfCancellationRequested();
                logger.LogInformation($"{nameof(SignAsync)} [{package}]: Begin Signing {Path.GetFileName(package)}");
                try
                {
                    originalPackageCopyPath = CopyPackage(package);

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

                    logger.LogInformation($"{nameof(SignAsync)} [{package}]: End Signing {Path.GetFileName(package)}");
                }
            }

            return(true);
        }
示例#5
0
        public void CreateFromFilePaths_WhenLoggerIsNull_Throws()
        {
            var exception = Assert.Throws <ArgumentNullException>(
                () => SigningOptions.CreateFromFilePaths(
                    inputPackageFilePath: Path.Combine(Path.GetTempPath(), "a"),
                    outputPackageFilePath: Path.Combine(Path.GetTempPath(), "b"),
                    overwrite: true,
                    signatureProvider: Mock.Of <ISignatureProvider>(),
                    logger: null));

            Assert.Equal("logger", exception.ParamName);
        }
示例#6
0
        public void CreateFromFilePaths_WhenInputPackageFilePathAndOutputPackageFilePathAreEquivalent_Throws()
        {
            var exception = Assert.Throws <ArgumentException>(
                () => SigningOptions.CreateFromFilePaths(
                    inputPackageFilePath: Path.Combine(Path.GetTempPath(), "file"),
                    outputPackageFilePath: Path.Combine(Path.GetTempPath(), "FILE"),
                    overwrite: true,
                    signatureProvider: Mock.Of <ISignatureProvider>(),
                    logger: Mock.Of <ILogger>()));

            Assert.Equal("inputPackageFilePath and outputPackageFilePath should be different. Package signing cannot be done in place.", exception.Message);
        }
示例#7
0
        public void CreateFromFilePaths_WhenOutputPackageFilePathIsNullOrEmpty_Throws(string outputPackageFilePath)
        {
            var exception = Assert.Throws <ArgumentException>(
                () => SigningOptions.CreateFromFilePaths(
                    inputPackageFilePath: "a",
                    outputPackageFilePath: outputPackageFilePath,
                    overwrite: true,
                    signatureProvider: Mock.Of <ISignatureProvider>(),
                    logger: Mock.Of <ILogger>()));

            Assert.Equal("outputPackageFilePath", exception.ParamName);
        }
            private Test(X509Certificate2 certificate, TestDirectory dir, FileInfo package)
            {
                _authorCertificate     = new X509Certificate2(certificate);
                _repositoryCertificate = new X509Certificate2(certificate);
                _directory             = dir;

                var outputPath = GetNewTempFilePath();

                OutputFile = new FileInfo(outputPath);

                var signatureProvider = new X509SignatureProvider(timestampProvider: null);

                AuthorRequest     = new AuthorSignPackageRequest(_authorCertificate, HashAlgorithmName.SHA256);
                RepositoryRequest = new RepositorySignPackageRequest(_repositoryCertificate, HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, new Uri("https://test/api/index.json"), packageOwners: null);

                var overwrite = true;

                Options = SigningOptions.CreateFromFilePaths(package.FullName, outputPath, overwrite, signatureProvider, NullLogger.Instance);
            }
        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);
                }
            }
        }
示例#10
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);
            }
        }
示例#11
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
        }
示例#12
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);
        }
示例#13
0
            internal static SignTest Create(
                X509Certificate2 certificate,
                HashAlgorithmName hashAlgorithm,
                byte[] package = null,
                ISignatureProvider signatureProvider = null)
            {
                var directory         = TestDirectory.Create();
                var signedPackageFile = new FileInfo(Path.Combine(directory, Guid.NewGuid().ToString()));
                var outputPackageFile = new FileInfo(Path.Combine(directory, Guid.NewGuid().ToString()));

                if (package == null)
                {
                    File.WriteAllBytes(signedPackageFile.FullName, Array.Empty <byte>());
                }
                else
                {
                    using (var fileStream = signedPackageFile.Create())
                    {
                        fileStream.Write(package, 0, package.Length);
                    }
                }

                signatureProvider = signatureProvider ?? Mock.Of <ISignatureProvider>();
                var logger    = new TestLogger();
                var request   = new AuthorSignPackageRequest(certificate, hashAlgorithm);
                var overwrite = false;
                var options   = SigningOptions.CreateFromFilePaths(
                    signedPackageFile.FullName,
                    outputPackageFile.FullName,
                    overwrite,
                    signatureProvider,
                    logger);

                return(new SignTest(
                           request,
                           directory,
                           options,
                           logger));
            }
示例#14
0
            internal Test(X509Certificate2 certificate)
            {
                _directory             = TestDirectory.Create();
                _authorCertificate     = new X509Certificate2(certificate);
                _repositoryCertificate = new X509Certificate2(certificate);

                var outputPath = GetNewTempFilePath();

                OutputFile = new FileInfo(outputPath);

                var packageContext    = new SimpleTestPackageContext();
                var packageFileName   = Guid.NewGuid().ToString();
                var package           = packageContext.CreateAsFile(_directory, packageFileName);
                var signatureProvider = new X509SignatureProvider(timestampProvider: null);

                AuthorRequest     = new AuthorSignPackageRequest(_authorCertificate, HashAlgorithmName.SHA256);
                RepositoryRequest = new RepositorySignPackageRequest(_repositoryCertificate, HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, new Uri("https://test/api/index.json"), packageOwners: null);

                var overwrite = true;

                Options = SigningOptions.CreateFromFilePaths(package.FullName, outputPath, overwrite, signatureProvider, NullLogger.Instance);
            }
示例#15
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);
        }