/// <summary>
        /// Generates a signed copy of a package and returns the path to that package
        /// This method timestamps a package and should only be used with tests marked with [CIOnlyFact]
        /// </summary>
        /// <param name="certificate">Certificate to be used while signing the package</param>
        /// <param name="nupkg">Package to be signed</param>
        /// <param name="dir">Directory for placing the signed package</param>
        /// <param name="timestampService">RFC 3161 timestamp service URL.</param>
        /// <param name="request">An author signing request.</param>
        /// <returns>Path to the signed copy of the package</returns>
        public static async Task <string> CreateSignedAndTimeStampedPackageAsync(
            X509Certificate2 certificate,
            SimpleTestPackageContext nupkg,
            string dir,
            Uri timestampService,
            AuthorSignPackageRequest request = null)
        {
            var testLogger = new TestLogger();

            using (var zipReadStream = nupkg.CreateAsStream())
                using (var zipWriteStream = nupkg.CreateAsStream())
                {
                    var signedPackagePath = Path.Combine(dir, Guid.NewGuid().ToString());

                    using (var signPackage = new SignedPackageArchive(zipReadStream, zipWriteStream))
                    {
                        request = request ?? new AuthorSignPackageRequest(certificate, HashAlgorithmName.SHA256);

                        // Sign the package
                        await SignAndTimeStampPackageAsync(testLogger, certificate, signPackage, timestampService, request);
                    }

                    zipWriteStream.Seek(offset: 0, loc: SeekOrigin.Begin);

                    using (Stream fileStream = File.OpenWrite(signedPackagePath))
                    {
                        zipWriteStream.CopyTo(fileStream);
                    }

                    return(signedPackagePath);
                }
        }
        /// <summary>
        /// Generates a signed copy of a package and returns the path to that package
        /// This method timestamps a package and should only be used with tests marked with [CIOnlyFact]
        /// </summary>
        /// <param name="testCert">Certificate to be used while signing the package</param>
        /// <param name="nupkg">Package to be signed</param>
        /// <param name="dir">Directory for placing the signed package</param>
        /// <param name="timestampService">RFC 3161 timestamp service URL.</param>
        /// <returns>Path to the signed copy of the package</returns>
        public static async Task <string> CreateSignedAndTimeStampedPackageAsync(
            X509Certificate2 testCert,
            SimpleTestPackageContext nupkg,
            string dir,
            Uri timestampService)
        {
            var testLogger = new TestLogger();

            using (var zipReadStream = nupkg.CreateAsStream())
                using (var zipWriteStream = nupkg.CreateAsStream())
                {
                    var signedPackagePath = Path.Combine(dir, Guid.NewGuid().ToString());

                    using (var signPackage = new SignedPackageArchive(zipReadStream, zipWriteStream))
                    {
                        // Sign the package
                        await SignAndTimeStampPackageAsync(testLogger, testCert, signPackage, timestampService);
                    }

                    zipWriteStream.Seek(offset: 0, loc: SeekOrigin.Begin);

                    using (Stream fileStream = File.OpenWrite(signedPackagePath))
                    {
                        zipWriteStream.CopyTo(fileStream);
                    }

                    return(signedPackagePath);
                }
        }
예제 #3
0
            private static async Task <MemoryStream> CreateSignedPackageAsync(
                X509Certificate2 certificate,
                Stream unsignedPackage = null)
            {
                if (unsignedPackage == null)
                {
                    var packageContext = new SimpleTestPackageContext();
                    unsignedPackage = packageContext.CreateAsStream();
                }

                var signatureProvider = new X509SignatureProvider(timestampProvider: null);
                var overwrite         = true;

                using (var request = new AuthorSignPackageRequest(certificate, HashAlgorithmName.SHA256))
                    using (var outputPackageStream = new MemoryStream())
                        using (var options = new SigningOptions(
                                   new Lazy <Stream>(() => unsignedPackage),
                                   new Lazy <Stream>(() => outputPackageStream),
                                   overwrite,
                                   signatureProvider,
                                   NullLogger.Instance))
                        {
                            await SigningUtility.SignAsync(options, request, CancellationToken.None);

                            var isSigned = await SignedArchiveTestUtility.IsSignedAsync(options.OutputPackageStream);

                            Assert.True(isSigned);

                            return(new MemoryStream(outputPackageStream.ToArray()));
                        }
            }
예제 #4
0
            internal static Test CreateUnsigned()
            {
                var packageContext = new SimpleTestPackageContext();
                var package        = packageContext.CreateAsStream();

                return(new Test(package));
            }
예제 #5
0
        /// <summary>
        /// Generates an repository signed copy of a package and returns the path to that package
        /// This method can timestamp a package and should only be used with tests marked with [CIOnlyFact]
        /// </summary>
        /// <param name="certificate">Certificate to be used while signing the package</param>
        /// <param name="nupkg">Package to be signed</param>
        /// <param name="dir">Directory for placing the signed package</param>
        /// <param name="timestampService">RFC 3161 timestamp service URL.</param>
        /// <param name="v3ServiceIndex">Value for the V3ServiceIndex for the repository signature attribute</param>
        /// <param name="packageOwners">List of package owners for teh repository signature attribute</param>
        /// <param name="signatureHashAlgorithm">Hash algorithm to be used in the signature. Defaults to SHA256</param>
        /// <param name="timestampHashAlgorithm">Hash algorithm to be used in the timestamp. Defaults to SHA256</param>
        /// <returns>Path to the signed copy of the package</returns>
        public static async Task <string> RepositorySignPackageAsync(
            X509Certificate2 certificate,
            SimpleTestPackageContext nupkg,
            string dir,
            Uri v3ServiceIndex,
            Uri timestampService = null,
            IReadOnlyList <string> packageOwners     = null,
            HashAlgorithmName signatureHashAlgorithm = HashAlgorithmName.SHA256,
            HashAlgorithmName timestampHashAlgorithm = HashAlgorithmName.SHA256)
        {
            var testLogger        = new TestLogger();
            var signedPackagePath = Path.Combine(dir, Guid.NewGuid().ToString());
            var tempPath          = Path.GetTempFileName();

            using (var packageStream = nupkg.CreateAsStream())
                using (var fileStream = File.OpenWrite(tempPath))
                {
                    packageStream.CopyTo(fileStream);
                }

            using (var originalPackage = File.OpenRead(tempPath))
                using (var signedPackage = File.Open(signedPackagePath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    using (var request = new RepositorySignPackageRequest(certificate, signatureHashAlgorithm, timestampHashAlgorithm, v3ServiceIndex, packageOwners))
                    {
                        await CreateSignedPackageAsync(request, originalPackage, signedPackage, timestampService);
                    }

            FileUtility.Delete(tempPath);

            return(signedPackagePath);
        }
예제 #6
0
        /// <summary>
        /// Generates a signed copy of a package and returns the path to that package
        /// This method timestamps a package and should only be used with tests marked with [CIOnlyFact]
        /// </summary>
        /// <param name="certificate">Certificate to be used while signing the package</param>
        /// <param name="nupkg">Package to be signed</param>
        /// <param name="dir">Directory for placing the signed package</param>
        /// <param name="timestampService">RFC 3161 timestamp service URL.</param>
        /// <param name="request">An author signing request.</param>
        /// <returns>Path to the signed copy of the package</returns>
        public static async Task <string> CreateSignedAndTimeStampedPackageAsync(
            X509Certificate2 certificate,
            SimpleTestPackageContext nupkg,
            string dir,
            Uri timestampService,
            AuthorSignPackageRequest request = null)
        {
            var testLogger        = new TestLogger();
            var signedPackagePath = Path.Combine(dir, Guid.NewGuid().ToString());
            var tempPath          = Path.GetTempFileName();

            using (var packageStream = nupkg.CreateAsStream())
                using (var fileStream = File.OpenWrite(tempPath))
                {
                    packageStream.CopyTo(fileStream);
                }
#if IS_DESKTOP
            using (var cert = new X509Certificate2(certificate))
                using (request = request ?? new AuthorSignPackageRequest(cert, HashAlgorithmName.SHA256))
                {
                    await SignAndTimeStampPackageAsync(testLogger, tempPath, signedPackagePath, timestampService, request);
                }
#endif

            FileUtility.Delete(tempPath);

            return(signedPackagePath);
        }
예제 #7
0
        public async Task GetTimestamp_AssertCompleteChain_Success()
        {
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url);
            var nupkg             = new SimpleTestPackageContext();

            using (var authorCert = new X509Certificate2(_trustedTestCert.Source.Cert))
                using (var packageStream = nupkg.CreateAsStream())
                {
                    // Act
                    var signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(authorCert, packageStream, timestampProvider);

                    var authorSignedCms = signature.SignedCms;
                    var timestamp       = signature.Timestamps.First();
                    var timestampCms    = timestamp.SignedCms;
                    IX509CertificateChain certificateChain;
                    var chainBuildSuccess = true;

                    // rebuild the chain to get the list of certificates
                    using (var chainHolder = new X509ChainHolder())
                    {
                        var chain  = chainHolder.Chain;
                        var policy = chain.ChainPolicy;

                        policy.ApplicationPolicy.Add(new Oid(Oids.TimeStampingEku));
                        policy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid;
                        policy.RevocationFlag    = X509RevocationFlag.ExcludeRoot;
                        policy.RevocationMode    = X509RevocationMode.Online;

                        var timestampSignerCertificate = timestampCms.SignerInfos[0].Certificate;
                        chainBuildSuccess = chain.Build(timestampSignerCertificate);
                        certificateChain  = CertificateChainUtility.GetCertificateChain(chain);
                    }

                    using (certificateChain)
                    {
                        // Assert
                        authorSignedCms.Should().NotBeNull();
                        authorSignedCms.Detached.Should().BeFalse();
                        authorSignedCms.ContentInfo.Should().NotBeNull();
                        authorSignedCms.SignerInfos.Count.Should().Be(1);
                        authorSignedCms.SignerInfos[0].UnsignedAttributes.Count.Should().Be(1);
                        authorSignedCms.SignerInfos[0].UnsignedAttributes[0].Oid.Value.Should().Be(Oids.SignatureTimeStampTokenAttribute);

                        timestampCms.Should().NotBeNull();
                        timestampCms.Detached.Should().BeFalse();
                        timestampCms.ContentInfo.Should().NotBeNull();

                        chainBuildSuccess.Should().BeTrue();
                        certificateChain.Count.Should().Be(timestampCms.Certificates.Count);

                        foreach (var cert in certificateChain)
                        {
                            timestampCms.Certificates.Contains(cert).Should().BeTrue();
                        }
                    }
                }
        }
예제 #8
0
            internal Test(X509Certificate2 certificate)
            {
                _directory   = TestDirectory.Create();
                _certificate = new X509Certificate2(certificate);

                var packageContext = new SimpleTestPackageContext();

                ReadStream  = packageContext.CreateAsStream();
                WriteStream = packageContext.CreateAsStream();

                Package = new SignedPackageArchive(ReadStream, WriteStream);
                Request = new AuthorSignPackageRequest(_certificate, HashAlgorithmName.SHA256);

                var signatureProvider = new X509SignatureProvider(timestampProvider: null);

                Signer = new Signer(Package, signatureProvider);
            }
예제 #9
0
        public async Task HasRepositoryCountersignature_WithSignatureWithoutRepositoryCountersignature_ReturnsFalseAsync()
        {
            using (var certificate = _fixture.GetDefaultCertificate())
            {
                var packageContext        = new SimpleTestPackageContext();
                var unsignedPackageStream = packageContext.CreateAsStream();

                var signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(
                    certificate,
                    unsignedPackageStream);

                var hasRepoCountersignature = SignatureUtility.HasRepositoryCountersignature(signature);

                Assert.False(hasRepoCountersignature);
            }
        }
예제 #10
0
        public async Task GetTrustResultAsync_SettingsRequireExactlyOneTimestamp_MultipleTimestamps_Fails()
        {
            // Arrange
            var nupkg            = new SimpleTestPackageContext();
            var testLogger       = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var setting = new SignedPackageVerifierSettings(
                allowUnsigned: false,
                allowIllegal: false,
                allowUntrusted: false,
                allowUntrustedSelfIssuedCertificate: false,
                allowIgnoreTimestamp: false,
                allowMultipleTimestamps: false,
                allowNoTimestamp: false,
                allowUnknownRevocation: false,
                allowNoClientCertificateList: true,
                allowNoRepositoryCertificateList: true);

            var timestampProvider    = new Rfc3161TimestampProvider(timestampService.Url);
            var verificationProvider = new SignatureTrustAndValidityVerificationProvider();

            using (var package = new PackageArchiveReader(nupkg.CreateAsStream(), leaveStreamOpen: false))
                using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert))
                    using (var signatureRequest = new AuthorSignPackageRequest(testCertificate, HashAlgorithmName.SHA256))
                    {
                        var signature = await SignedArchiveTestUtility.CreatePrimarySignatureForPackageAsync(package, signatureRequest);

                        var timestampedSignature = await SignedArchiveTestUtility.TimestampSignature(timestampProvider, signature, signatureRequest.TimestampHashAlgorithm, SignaturePlacement.PrimarySignature, testLogger);

                        var reTimestampedSignature = await SignedArchiveTestUtility.TimestampSignature(timestampProvider, timestampedSignature, signatureRequest.TimestampHashAlgorithm, SignaturePlacement.PrimarySignature, testLogger);

                        timestampedSignature.Timestamps.Count.Should().Be(1);
                        reTimestampedSignature.Timestamps.Count.Should().Be(2);

                        // Act
                        var result = await verificationProvider.GetTrustResultAsync(package, reTimestampedSignature, setting, CancellationToken.None);

                        var totalErrorIssues = result.GetErrorIssues();

                        // Assert
                        result.Trust.Should().Be(SignatureVerificationStatus.Illegal);
                        totalErrorIssues.Count().Should().Be(1);
                        totalErrorIssues.First().Code.Should().Be(NuGetLogCode.NU3000);
                    }
        }
예제 #11
0
        /// <summary>
        /// Generates a signed copy of a package and returns the path to that package
        /// </summary>
        /// <param name="testCert">Certificate to be used while signing the package</param>
        /// <param name="nupkg">Package to be signed</param>
        /// <param name="dir">Directory for placing the signed package</param>
        /// <param name="name">Name of the signed package file to create.</param>
        /// <returns>Path to the signed copy of the package</returns>
        public static async Task <string> CreateSignedPackageAsync(X509Certificate2 testCert, SimpleTestPackageContext nupkg, string dir, string name = null)
        {
            var testLogger        = new TestLogger();
            var signedPackagePath = Path.Combine(dir, name ?? Guid.NewGuid().ToString());
            var tempPath          = Path.GetTempFileName();

            using (var packageStream = nupkg.CreateAsStream())
                using (var fileStream = File.OpenWrite(tempPath))
                {
                    packageStream.CopyTo(fileStream);
                }

            await SignPackageAsync(testLogger, testCert, tempPath, signedPackagePath);

            FileUtility.Delete(tempPath);

            return(signedPackagePath);
        }
예제 #12
0
        public async Task HasRepositoryCountersignature_WithSignatureWithRepositoryCountersignature_ReturnsTrueAsync()
        {
            using (var certificate = _fixture.GetDefaultCertificate())
                using (var repositoryCertificate = _fixture.GetDefaultCertificate())
                {
                    var packageContext        = new SimpleTestPackageContext();
                    var unsignedPackageStream = packageContext.CreateAsStream();

                    var signature = await SignedArchiveTestUtility.CreatePrimarySignatureForPackageAsync(
                        certificate,
                        unsignedPackageStream);

                    var reposignedSignature = await SignedArchiveTestUtility.RepositoryCountersignPrimarySignatureAsync(repositoryCertificate, signature);

                    var hasRepoCountersignature = SignatureUtility.HasRepositoryCountersignature(reposignedSignature);

                    Assert.True(hasRepoCountersignature);
                }
        }
예제 #13
0
        public async Task HasRepositoryCountersignature_WithSignatureWithRepositoryCountersignature_ReturnsTrueAsync()
        {
            using (var certificate = _fixture.GetDefaultCertificate())
                using (var repositoryCertificate = _fixture.GetDefaultCertificate())
                {
                    var packageContext        = new SimpleTestPackageContext();
                    var unsignedPackageStream = packageContext.CreateAsStream();

                    var signature = await SignedArchiveTestUtility.CreateAuthorSignatureForPackageAsync(
                        certificate,
                        unsignedPackageStream);

                    var hashAlgorithm     = Common.HashAlgorithmName.SHA256;
                    var v3ServiceIndexUri = new Uri("https://v3serviceIndex.test/api/index.json");
                    using (var request = new RepositorySignPackageRequest(repositoryCertificate, hashAlgorithm, hashAlgorithm, v3ServiceIndexUri, null))
                    {
                        var reposignedSignature = await SignedArchiveTestUtility.RepositoryCountersignPrimarySignatureAsync(signature, request);

                        var hasRepoCountersignature = SignatureUtility.HasRepositoryCountersignature(reposignedSignature);

                        Assert.True(hasRepoCountersignature);
                    }
                }
        }