コード例 #1
0
        public async Task RejectsNonAuthorSignature()
        {
            // Arrange
            var content = new SignatureContent(
                SigningSpecifications.V1,
                NuGetHashAlgorithmName.SHA256,
                hashValue: "hash");

            SetSignatureContent(
                TestResources.SignedPackageLeafId,
                TestResources.GetResourceStream(TestResources.SignedPackageLeaf1),
                content.GetBytes());

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

            // Assert
            VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
            var issue = Assert.Single(result.Issues);

            Assert.Equal(ValidationIssueCode.OnlyAuthorSignaturesSupported, issue.IssueCode);
        }
コード例 #2
0
        PrimarySignature CreateKeyVaultPrimarySignature(SignPackageRequest request, SignatureContent signatureContent, ILogger logger)
        {
            // Get the chain

            var getter = typeof(SignPackageRequest).GetProperty("Chain", BindingFlags.Instance | BindingFlags.NonPublic)
                         .GetGetMethod(true);

            var certs = (IReadOnlyList <X509Certificate2>)getter.Invoke(request, null);


            var cmsSigner = CreateCmsSigner(request, certs, logger);

            var contentInfo = new ContentInfo(signatureContent.GetBytes());
            var cms         = new SignedCms(contentInfo);

            try
            {
                cms.ComputeSignature(cmsSigner, false); // silent is false to ensure PIN prompts appear if CNG/CAPI requires it
            }
            catch (CryptographicException ex) when(ex.HResult == INVALID_PROVIDER_TYPE_HRESULT)
            {
                var exceptionBuilder = new StringBuilder();

                exceptionBuilder.AppendLine("Invalid provider type");
                exceptionBuilder.AppendLine(CertificateUtility.X509Certificate2ToString(request.Certificate, NuGet.Common.HashAlgorithmName.SHA256));

                throw new SignatureException(NuGetLogCode.NU3001, exceptionBuilder.ToString());
            }

            return(PrimarySignature.Load(cms));
        }
コード例 #3
0
        public void GetBytes_ReturnsValidContent()
        {
            var content = new SignatureContent(SigningSpecifications.V1, HashAlgorithmName.SHA256, "a");

            var bytes = content.GetBytes();

            Assert.Equal("Version:1\n\n2.16.840.1.101.3.4.2.1-Hash:a\n\n", Encoding.UTF8.GetString(bytes));
        }
コード例 #4
0
        PrimarySignature CreateKeyVaultPrimarySignature(SignPackageRequest request, SignatureContent signatureContent, SignatureType signatureType)
        {
            // Get the chain

            var getter = typeof(SignPackageRequest).GetProperty("Chain", BindingFlags.Instance | BindingFlags.NonPublic)
                         .GetGetMethod(true);

            var certs = (IReadOnlyList <X509Certificate2>)getter.Invoke(request, null);


            var attribs = SigningUtility.CreateSignedAttributes(request, certs);

            // Convert .NET crypto attributes to Bouncy Castle
            var attribTable = new AttributeTable(new Asn1EncodableVector(attribs.Cast <CryptographicAttributeObject>()
                                                                         .Select(ToBcAttribute)
                                                                         .ToArray()));
            // SignerInfo generator setup
            var signerInfoGeneratorBuilder = new SignerInfoGeneratorBuilder()
                                             .WithSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(attribTable));


            // Subject Key Identifier (SKI) is smaller and less prone to accidental matching than issuer and serial
            // number.  However, to ensure cross-platform verification, SKI should only be used if the certificate
            // has the SKI extension attribute.

            // Try to look for the value
            var bcCer = DotNetUtilities.FromX509Certificate(request.Certificate);
            var ext   = bcCer.GetExtensionValue(new DerObjectIdentifier(Oids.SubjectKeyIdentifier));
            SignerInfoGenerator signerInfoGenerator;

            if (ext != null)
            {
                var ski = new SubjectKeyIdentifierStructure(ext);
                signerInfoGenerator = signerInfoGeneratorBuilder.Build(new RsaSignatureFactory(HashAlgorithmToBouncyCastle(request.SignatureHashAlgorithm), provider), ski.GetKeyIdentifier());
            }
            else
            {
                signerInfoGenerator = signerInfoGeneratorBuilder.Build(new RsaSignatureFactory(HashAlgorithmToBouncyCastle(request.SignatureHashAlgorithm), provider), bcCer);
            }


            var generator = new CmsSignedDataGenerator();

            generator.AddSignerInfoGenerator(signerInfoGenerator);

            // Get the chain as bc certs
            generator.AddCertificates(X509StoreFactory.Create("Certificate/Collection",
                                                              new X509CollectionStoreParameters(certs.Select(DotNetUtilities.FromX509Certificate).
                                                                                                ToList())));

            var msg  = new CmsProcessableByteArray(signatureContent.GetBytes());
            var data = generator.Generate(msg, true);

            var encoded = data.ContentInfo.GetDerEncoded();

            return(PrimarySignature.Load(encoded));
        }
コード例 #5
0
            internal LoadTest(CertificatesFixture fixture)
            {
                Certificate = fixture.GetDefaultCertificate();

                var content = new SignatureContent(
                    SigningSpecifications.V1,
                    HashAlgorithmName.SHA256,
                    hashValue: "hash");
                var contentInfo = new ContentInfo(content.GetBytes());

                SignedCms = new SignedCms(contentInfo);
                CmsSigner = new CmsSigner(Certificate);
            }
コード例 #6
0
        private static SignedCms CreateSignature(SignatureContent signatureContent, X509Certificate2 certificate)
        {
            var cmsSigner = new CmsSigner(certificate);

            cmsSigner.DigestAlgorithm = HashAlgorithmName.SHA256.ConvertToOid();
            cmsSigner.IncludeOption   = X509IncludeOption.WholeChain;

            var contentInfo = new ContentInfo(signatureContent.GetBytes());
            var signedCms   = new SignedCms(contentInfo);

            signedCms.ComputeSignature(cmsSigner);

            Assert.Empty(signedCms.SignerInfos[0].SignedAttributes);
            Assert.Empty(signedCms.SignerInfos[0].UnsignedAttributes);

            return(signedCms);
        }
コード例 #7
0
        // This generates a package with a basic signed CMS.
        // The signature MUST NOT have any signed or unsigned attributes.
        public static async Task <FileInfo> SignPackageFileWithBasicSignedCmsAsync(
            TestDirectory directory,
            FileInfo packageFile,
            X509Certificate2 certificate)
        {
            SignatureContent signatureContent;

            using (var stream = packageFile.OpenRead())
                using (var hashAlgorithm = HashAlgorithmName.SHA256.GetHashProvider())
                {
                    var hash = hashAlgorithm.ComputeHash(stream, leaveStreamOpen: false);
                    signatureContent = new SignatureContent(SigningSpecifications.V1, HashAlgorithmName.SHA256, Convert.ToBase64String(hash));
                }

            var signedPackageFile = new FileInfo(Path.Combine(directory, Guid.NewGuid().ToString()));
            var cmsSigner         = new CmsSigner(certificate)
            {
                DigestAlgorithm = HashAlgorithmName.SHA256.ConvertToOid(),
                IncludeOption   = X509IncludeOption.WholeChain
            };

            var contentInfo = new ContentInfo(signatureContent.GetBytes());
            var signature   = new SignedCms(contentInfo);

            signature.ComputeSignature(cmsSigner);

            Assert.Empty(signature.SignerInfos[0].SignedAttributes);
            Assert.Empty(signature.SignerInfos[0].UnsignedAttributes);

            using (var packageReadStream = packageFile.OpenRead())
                using (var packageWriteStream = signedPackageFile.OpenWrite())
                    using (var package = new SignedPackageArchive(packageReadStream, packageWriteStream))
                        using (var signatureStream = new MemoryStream(signature.Encode()))
                        {
                            await package.AddSignatureAsync(signatureStream, CancellationToken.None);
                        }

            return(signedPackageFile);
        }
コード例 #8
0
        public void Load_WithMultiplePrimarySignatures_Throws()
        {
            using (var certificate = _fixture.GetDefaultCertificate())
            {
                var content = new SignatureContent(
                    SigningSpecifications.V1,
                    HashAlgorithmName.SHA256,
                    hashValue: "hash");
                var contentInfo = new ContentInfo(content.GetBytes());
                var signedCms   = new SignedCms(contentInfo);

                var cmsSigner = new CmsSigner(certificate);
                signedCms.ComputeSignature(cmsSigner);

                cmsSigner = new CmsSigner(certificate);
                signedCms.ComputeSignature(cmsSigner);

                var exception = Assert.Throws <SignatureException>(
                    () => Signature.Load(signedCms.Encode()));

                Assert.Equal(NuGetLogCode.NU3009, exception.Code);
                Assert.Equal("The package signature contains multiple primary signatures.", exception.Message);
            }
        }
コード例 #9
0
        private void VerifyTimestampData(
            ISigningTestServer testServer,
            TimestampService timestampService,
            Action <Rfc3161TimestampProvider, TimestampRequest> verifyTimestampData)
        {
            using (testServer.RegisterResponder(timestampService))
            {
                var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url);

                using (var certificate = new X509Certificate2(_trustedTestCert.Source.Cert))
                {
                    var timestampHashAlgorithm = Common.HashAlgorithmName.SHA256;
                    var content        = new SignatureContent(SigningSpecifications.V1, Common.HashAlgorithmName.SHA256, "peach");
                    var signedCms      = SigningTestUtility.GenerateSignedCms(certificate, content.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.PrimarySignature);

                    verifyTimestampData(timestampProvider, request);
                }
            }
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        public async Task GetTimestamp_WithValidInput_ReturnsTimestamp()
        {
            var logger           = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

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

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

                var request = new TimestampRequest(
                    signingSpecifications: SigningSpecifications.V1,
                    hashedMessage: messageHash,
                    hashAlgorithm: timestampHashAlgorithm,
                    target: SignaturePlacement.PrimarySignature
                    );

                // Act
                var timestampedCms = timestampProvider.GetTimestamp(request, logger, CancellationToken.None);

                // Assert
                timestampedCms.Should().NotBeNull();
                timestampedCms.Detached.Should().BeFalse();
                timestampedCms.ContentInfo.Should().NotBeNull();
                timestampedCms.SignerInfos.Count.Should().Be(1);
            }
        }
コード例 #12
0
        public async Task GetTimestamp_WhenCancelled_Throws()
        {
            var logger           = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url);
            var content           = 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.GenerateSignedCms(authorCert, content.GetBytes());
                var signature      = PrimarySignature.Load(signedCms.Encode());
                var signatureValue = signature.GetSignatureValue();
                var messageHash    = timestampHashAlgorithm.ComputeHash(signatureValue);

                var request = new TimestampRequest(
                    signingSpecifications: SigningSpecifications.V1,
                    hashedMessage: messageHash,
                    hashAlgorithm: timestampHashAlgorithm,
                    target: SignaturePlacement.PrimarySignature
                    );

                // Act
                Action timestampAction = () => timestampProvider.GetTimestamp(request, logger, new CancellationToken(canceled: true));

                // Assert
                timestampAction.ShouldThrow <OperationCanceledException>()
                .WithMessage(_operationCancelledExceptionMessage);
            }
        }
コード例 #13
0
        public async Task GetTimestamp_WhenRequestNull_Throws()
        {
            var logger           = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

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

            Action <X509V3CertificateGenerator> modifyGenerator = delegate(X509V3CertificateGenerator gen)
            {
                gen.SetNotBefore(DateTime.MinValue);
                gen.SetNotBefore(DateTime.UtcNow.Subtract(TimeSpan.FromDays(1))); // cert has expired
            };

            using (var authorCert = SigningTestUtility.GenerateCertificate(authorCertName, modifyGenerator: modifyGenerator))
            {
                var timestampHashAlgorithm = Common.HashAlgorithmName.SHA256;
                var signedCms      = SigningTestUtility.GenerateSignedCms(authorCert, content.GetBytes());
                var signature      = PrimarySignature.Load(signedCms.Encode());
                var signatureValue = signature.GetSignatureValue();
                var messageHash    = timestampHashAlgorithm.ComputeHash(signatureValue);

                var request = new TimestampRequest(
                    signingSpecifications: SigningSpecifications.V1,
                    hashedMessage: messageHash,
                    hashAlgorithm: timestampHashAlgorithm,
                    target: SignaturePlacement.PrimarySignature
                    );

                // Act
                Action timestampAction = () => timestampProvider.GetTimestamp(null, logger, CancellationToken.None);

                // Assert
                timestampAction.ShouldThrow <ArgumentNullException>()
                .WithMessage(string.Format(_argumentNullExceptionMessage, nameof(request)));
            }
        }
コード例 #14
0
        public async Task GetTimestampAsync_WhenLoggerNull_ThrowsAsync()
        {
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

            var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url);
            var content           = 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.GenerateSignedCms(authorCert, content.GetBytes());
                var signature      = PrimarySignature.Load(signedCms.Encode());
                var signatureValue = signature.GetSignatureValue();
                var messageHash    = timestampHashAlgorithm.ComputeHash(signatureValue);

                var request = new TimestampRequest(
                    signingSpecifications: SigningSpecifications.V1,
                    hashedMessage: messageHash,
                    hashAlgorithm: timestampHashAlgorithm,
                    target: SignaturePlacement.PrimarySignature
                    );

                // Assert
                var exception = await Assert.ThrowsAsync <ArgumentNullException>(
                    () => timestampProvider.GetTimestampAsync(request, logger: null, CancellationToken.None));

                Assert.Equal("logger", exception.ParamName);
                Assert.StartsWith("Value cannot be null.", exception.Message);
            }
        }
コード例 #15
0
        public async Task GetTimestampAsync_WhenRequestNull_ThrowsAsync()
        {
            var logger           = new TestLogger();
            var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync();

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

            Action <TestCertificateGenerator> modifyGenerator = delegate(TestCertificateGenerator gen)
            {
                gen.NotBefore = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)); // cert has expired
            };

            using (var authorCert = SigningTestUtility.GenerateCertificate(authorCertName, modifyGenerator: modifyGenerator))
            {
                var timestampHashAlgorithm = Common.HashAlgorithmName.SHA256;
                var signedCms      = SigningTestUtility.GenerateSignedCms(authorCert, content.GetBytes());
                var signature      = PrimarySignature.Load(signedCms.Encode());
                var signatureValue = signature.GetSignatureValue();
                var messageHash    = timestampHashAlgorithm.ComputeHash(signatureValue);

                var request = new TimestampRequest(
                    signingSpecifications: SigningSpecifications.V1,
                    hashedMessage: messageHash,
                    hashAlgorithm: timestampHashAlgorithm,
                    target: SignaturePlacement.PrimarySignature
                    );

                // Assert
                var exception = await Assert.ThrowsAsync <ArgumentNullException>(
                    () => timestampProvider.GetTimestampAsync(request: null, logger, CancellationToken.None));

                Assert.Equal("request", exception.ParamName);
                Assert.StartsWith("Value cannot be null.", exception.Message);
            }
        }