public void GetRepositoryCountersignature_WithNonRepositoryCountersignature_ReturnsNull()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();

                // Generate valid countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateNuGetV3ServiceIndexUrl(new Uri("https://api.nuget.org/v3/index.json")));
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

                Assert.Null(countersignature);
            }
        }
        public async Task LoadSignatureDataAsync()
        {
            using (var reader = new PackageArchiveReader(_streamFactory(), false))
            {
                IsSigned = await reader.IsSignedAsync(CancellationToken.None);

                if (IsSigned)
                {
                    try
                    {
                        var sig = await reader.GetPrimarySignatureAsync(CancellationToken.None);

                        // Author signatures must be the primary, but they can contain
                        // a repository counter signature
                        if (sig.Type == SignatureType.Author)
                        {
                            PublisherSignature = new SignatureInfo(sig);

                            var counter = RepositoryCountersignature.GetRepositoryCountersignature(sig);
                            if (counter != null)
                            {
                                RepositorySignature = new RepositorySignatureInfo(counter);
                            }
                        }
                        else if (sig.Type == SignatureType.Repository)
                        {
                            RepositorySignature = new RepositorySignatureInfo(sig);
                        }
                    }
                    catch (SignatureException)
                    {
                    }
                }
            }
        }
        public void GetRepositoryCountersignature_WithRepositoryPrimarySignature_Throws()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidRepositoryPrimarySignature();

                // Generate valid countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateCommitmentTypeIndication(SignatureType.Repository));
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateNuGetV3ServiceIndexUrl(new Uri("https://api.nuget.org/v3/index.json")));
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var exception = Assert.Throws <SignatureException>(
                    () => RepositoryCountersignature.GetRepositoryCountersignature(primarySignature));

                Assert.Equal(NuGetLogCode.NU3033, exception.Code);
                Assert.Equal("A repository primary signature must not have a repository countersignature.", exception.Message);
            }
        }
        public void GetRepositoryCountersignature_WithValidRepositoryCountersignature_ReturnsRepositoryCountersignature()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();

                // Generate valid countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateCommitmentTypeIndication(SignatureType.Repository));
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateNuGetV3ServiceIndexUrl(new Uri("https://api.nuget.org/v3/index.json")));
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateNuGetPackageOwners(new List <string> {
                    "microsoft", "nuget"
                }));
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

                Assert.Equal(SignatureType.Repository, countersignature.Type);
            }
        }
        public void GetRepositoryCountersignature_WithRepositoryCountersignatureWithoutV3ServiceIndexUrl_Throws()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();

                // Generate countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateCommitmentTypeIndication(SignatureType.Repository));
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var exception = Assert.Throws <SignatureException>(
                    () => RepositoryCountersignature.GetRepositoryCountersignature(primarySignature));

                Assert.Equal(NuGetLogCode.NU3000, exception.Code);
                Assert.Equal("Exactly one nuget-v3-service-index-url attribute is required.", exception.Message);
            }
        }
        public void GetRepositoryCountersignature_WhenPrimarySignatureNull_Throws()
        {
            var exception = Assert.Throws <ArgumentNullException>(
                () => RepositoryCountersignature.GetRepositoryCountersignature(primarySignature: null));

            Assert.Equal("primarySignature", exception.ParamName);
        }
        private static void ExtractSignaturesAndCertificates(Context context)
        {
            if (context.PrimarySignature.Timestamps.Count != 1)
            {
                throw new InvalidOperationException("There should be exactly one timestamp on the primary signature.");
            }

            var primarySignatureCertificates = ExtractPrimarySignatureCertificates(context);

            if (context.PrimarySignature.Type == SignatureType.Author)
            {
                context.Author = new SignatureAndCertificates(context.PrimarySignature, primarySignatureCertificates);

                var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(context.PrimarySignature);
                if (repositoryCountersignature != null)
                {
                    if (repositoryCountersignature.Timestamps.Count != 1)
                    {
                        throw new InvalidOperationException("There should be exactly one timestamp on the repository countersignature.");
                    }

                    var countersignatureCertificates = ExtractRepositoryCountersignatureCertificates(context, repositoryCountersignature);
                    context.Repository = new SignatureAndCertificates(repositoryCountersignature, countersignatureCertificates);
                }
            }
            else if (context.PrimarySignature.Type == SignatureType.Repository)
            {
                context.Repository = new SignatureAndCertificates(context.PrimarySignature, primarySignatureCertificates);
            }
            else
            {
                throw new InvalidOperationException("The primary signature must be an author or repository signature.");
            }
        }
        private static ExtractedCertificates ExtractCertificates(
            Context context,
            RepositoryCountersignature repositoryCountersignature)
        {
            IX509CertificateChain signatureCertificates;

            if (repositoryCountersignature == null)
            {
                signatureCertificates = SignatureUtility.GetCertificateChain(context.PrimarySignature);
            }
            else
            {
                signatureCertificates = SignatureUtility.GetCertificateChain(context.PrimarySignature, repositoryCountersignature);
            }

            context.Disposables.Add(signatureCertificates);

            if (signatureCertificates == null || !signatureCertificates.Any())
            {
                throw new InvalidOperationException("The provided signature must have at least one signing certificate.");
            }

            var hashedSignatureCertificates = signatureCertificates
                                              .Select(x => new HashedCertificate(x))
                                              .ToList();
            var signatureEndCertificate     = hashedSignatureCertificates.First();
            var signatureParentCertificates = hashedSignatureCertificates.Skip(1).ToList();

            IX509CertificateChain timestampCertificates;

            if (repositoryCountersignature == null)
            {
                timestampCertificates = SignatureUtility.GetTimestampCertificateChain(context.PrimarySignature);
            }
            else
            {
                timestampCertificates = SignatureUtility.GetTimestampCertificateChain(context.PrimarySignature, repositoryCountersignature);
            }

            context.Disposables.Add(timestampCertificates);

            if (timestampCertificates == null || !timestampCertificates.Any())
            {
                throw new InvalidOperationException("The provided signature must have at least one timestamp certificate.");
            }

            var hashedTimestampCertificates = timestampCertificates
                                              .Select(x => new HashedCertificate(x))
                                              .ToList();
            var timestampEndCertificate     = hashedTimestampCertificates.First();
            var timestampParentCertificates = hashedTimestampCertificates.Skip(1).ToList();

            return(new ExtractedCertificates(
                       signatureEndCertificate,
                       signatureParentCertificates,
                       timestampEndCertificate,
                       timestampParentCertificates));
        }
        public async Task GetRepositoryCountersignature_WithNoCountersignatures_ReturnsNull()
        {
            using (var test = await Test.CreateWithoutRepositoryCountersignatureAsync(_fixture.TrustedTestCertificate.Source.Cert))
            {
                var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(test.PrimarySignature);

                Assert.Null(repositoryCountersignature);
            }
        }
        public async Task GetSignatureValue_WithSha256_ReturnsValue()
        {
            using (var test = await Test.CreateAsync(new X509Certificate2(_fixture.TrustedTestCertificate.Source.Cert)))
            {
                var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(test.PrimarySignature);
                var actualValue   = repositoryCountersignature.GetSignatureValue();
                var expectedValue = GetRepositoryCountersignatureSignatureValue(test.PrimarySignature.SignedCms);

                Assert.Equal(expectedValue, actualValue);
            }
        }
        public void GetCertificateChain_WithRepositoryCountersignature_ReturnsCertificates()
        {
            var primarySignature           = PrimarySignature.Load(SignTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            using (var certificates = SignatureUtility.GetCertificateChain(primarySignature, repositoryCountersignature))
            {
                Assert.Equal(3, certificates.Count);
                Assert.Equal("8d8cc5bdf9e5f86b971d7fb961fe24b999486483", certificates[0].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("c8ae47bfd632870a15e3775784affd2bdc96cbf1", certificates[1].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("d4e8185475a062de3518d1aa693f13c4283f81ff", certificates[2].Thumbprint, StringComparer.OrdinalIgnoreCase);
            }
        }
        public void GetRepositoryCountersignature_WithoutCountersignature_ReturnsNull()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

                Assert.Null(countersignature);
            }
        }
        public void GetTimestampCertificateChain_WithRepositoryCountersignatureTimestamp_ReturnsCertificates()
        {
            var primarySignature           = PrimarySignature.Load(SignTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            using (var certificates = SignatureUtility.GetTimestampCertificateChain(primarySignature, repositoryCountersignature))
            {
                Assert.Equal(3, certificates.Count);
                Assert.Equal("96b479acf63394f3bcc9928c396264afd60909ed", certificates[0].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("fa4e4ca3d9a26b92a73bb875f964972983b55ccd", certificates[1].Thumbprint, StringComparer.OrdinalIgnoreCase);
                Assert.Equal("88b288ff6d3d826469a9ef7816166a7def221885", certificates[2].Thumbprint, StringComparer.OrdinalIgnoreCase);
            }
        }
        public void GetCertificateChain_WithUnrelatedRepositoryCountersignature_Throws()
        {
            var primarySignature           = PrimarySignature.Load(SignTestUtility.GetResourceBytes(".signature.p7s"));
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

            primarySignature = RemoveRepositoryCountersignature(primarySignature);

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

            Assert.Equal("repositoryCountersignature", exception.ParamName);
            Assert.StartsWith("The primary signature and repository countersignature are unrelated.", exception.Message);
        }
Exemple #15
0
        private async Task <bool> HasAllValidRepositorySignaturesAsync(Context context)
        {
            if (context.Signature.Type == SignatureType.Repository)
            {
                if (!await IsValidRepositorySignatureAsync(context, (RepositoryPrimarySignature)context.Signature))
                {
                    _logger.LogInformation(
                        "Signed package {PackageId} {PackageVersion} for validation {ValidationId} has repository " +
                        "primary signature that is invalid.",
                        context.Message.PackageId,
                        context.Message.PackageVersion,
                        context.Message.ValidationId);

                    return(false);
                }
            }

            try
            {
                var repositoryCounterSignature = RepositoryCountersignature.GetRepositoryCountersignature(context.Signature);

                if (repositoryCounterSignature != null &&
                    !await IsValidRepositorySignatureAsync(context, repositoryCounterSignature))
                {
                    _logger.LogInformation(
                        "Signed package {PackageId} {PackageVersion} for validation {ValidationId} has repository " +
                        "countersignature that is invalid.",
                        context.Message.PackageId,
                        context.Message.PackageVersion,
                        context.Message.ValidationId);

                    return(false);
                }
            }
            catch (SignatureException ex)
            {
                // This handles the case when there are multiple repository signatures.
                _logger.LogInformation(
                    0,
                    ex,
                    "Signed package {PackageId} {PackageVersion} for validation {ValidationId} has repository " +
                    "countersignature that is invalid due to an exception.",
                    context.Message.PackageId,
                    context.Message.PackageVersion,
                    context.Message.ValidationId);

                return(false);
            }

            return(true);
        }
        public void GetTimestampCertificateChain_WithRepositoryCountersignatureWithoutTimestamp_Throws()
        {
            var primarySignature = PrimarySignature.Load(SignTestUtility.GetResourceBytes(".signature.p7s"));

            primarySignature = RemoveRepositoryCountersignatureTimestamp(primarySignature);

            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);

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

            Assert.Equal(NuGetLogCode.NU3000, exception.Code);
            Assert.Equal("The repository countersignature does not have a timestamp.", exception.Message);
        }
        private Task <PrimarySignature> TimestampRepositoryCountersignatureAsync(SignPackageRequest request, ILogger logger, PrimarySignature primarySignature, CancellationToken token)
        {
            var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);
            var signatureValue             = repositoryCountersignature.GetSignatureValue();
            var messageHash = request.TimestampHashAlgorithm.ComputeHash(signatureValue);

            var timestampRequest = new TimestampRequest(
                signingSpecifications: SigningSpecifications.V1,
                hashedMessage: messageHash,
                hashAlgorithm: request.TimestampHashAlgorithm,
                target: SignaturePlacement.Countersignature
                );

            return(timestampProvider.TimestampSignatureAsync(primarySignature, timestampRequest, logger, token));
        }
        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);
            }
        }
        public async Task GetRepositoryCountersignature_WithRepositoryCountersignature_ReturnsInstance()
        {
            using (var test = await Test.CreateAsync(new X509Certificate2(_fixture.TrustedTestCertificate.Source.Cert)))
            {
                var repositoryCountersignature = RepositoryCountersignature.GetRepositoryCountersignature(test.PrimarySignature);

                Assert.NotNull(repositoryCountersignature);

                Assert.Equal(test.Request.Certificate, repositoryCountersignature.SignerInfo.Certificate);
                Assert.Equal(
                    test.Request.SignatureHashAlgorithm.ConvertToOidString(),
                    repositoryCountersignature.SignerInfo.DigestAlgorithm.Value);
                Assert.Equal(test.Request.V3ServiceIndexUrl, repositoryCountersignature.V3ServiceIndexUrl);
                Assert.Equal(test.Request.PackageOwners, repositoryCountersignature.PackageOwners);
            }
        }
        protected async override Task RunInternalAsync(ValidationContext context)
        {
            // Get the package's signature, if any.
            var signature = await GetPrimarySignatureOrNullAsync(context);

            if (signature == null)
            {
                throw new MissingRepositorySignatureException(
                          $"Package {context.Package.Id} {context.Package.Version} is unsigned",
                          MissingRepositorySignatureReason.Unsigned);
            }

            // The repository signature can be the primary signature or the author signature's countersignature.
            IRepositorySignature repositorySignature = null;

            switch (signature.Type)
            {
            case SignatureType.Repository:
                repositorySignature = (RepositoryPrimarySignature)signature;
                break;

            case SignatureType.Author:
                repositorySignature = RepositoryCountersignature.GetRepositoryCountersignature(signature);

                if (repositorySignature == null)
                {
                    throw new MissingRepositorySignatureException(
                              $"Package {context.Package.Id} {context.Package.Version} is author signed but not repository signed",
                              MissingRepositorySignatureReason.AuthorSignedNoRepositoryCountersignature);
                }

                break;

            default:
            case SignatureType.Unknown:
                throw new MissingRepositorySignatureException(
                          $"Package {context.Package.Id} {context.Package.Version} has an unknown signature type '{signature.Type}'",
                          MissingRepositorySignatureReason.UnknownSignature);
            }

            Logger.LogInformation(
                "Package {PackageId} {PackageVersion} has a repository signature with service index {ServiceIndex} and owners {Owners}",
                context.Package.Id,
                context.Package.Version,
                repositorySignature.V3ServiceIndexUrl,
                repositorySignature.PackageOwners);
        }
        public void GetRepositoryCountersignature_WithRepositoryCountersignatureWithInvalidPackageOwners_Throws()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();

                // Generate countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateCommitmentTypeIndication(SignatureType.Repository));

                var invalidPackageOwnersBytes = DerEncoder.ConstructSequence(
                    (new List <string> {
                    "", "   "
                }).Select(packageOwner => DerEncoder.SegmentedEncodeUtf8String(packageOwner.ToCharArray())));

                var invalidPackageOwners = new System.Security.Cryptography.CryptographicAttributeObject(
                    new System.Security.Cryptography.Oid(Oids.NuGetPackageOwners),
                    new System.Security.Cryptography.AsnEncodedDataCollection(new System.Security.Cryptography.AsnEncodedData(Oids.NuGetPackageOwners, invalidPackageOwnersBytes)));

                test.CounterCmsSigner.SignedAttributes.Add(
                    invalidPackageOwners);
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateNuGetV3ServiceIndexUrl(new Uri("https://api.nuget.org/v3/index.json")));
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var exception = Assert.Throws <SignatureException>(
                    () => RepositoryCountersignature.GetRepositoryCountersignature(primarySignature));

                Assert.Equal(NuGetLogCode.NU3000, exception.Code);
                Assert.Equal("The nuget-package-owners attribute is invalid.", exception.Message);
            }
        }
        public static Task <PrimarySignature> TimestampSignature(ITimestampProvider timestampProvider, PrimarySignature primarySignature, HashAlgorithmName hashAlgorithm, SignaturePlacement target, ILogger logger)
        {
            Signature signatureToTimestamp = primarySignature;

            if (target == SignaturePlacement.Countersignature)
            {
                signatureToTimestamp = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);
            }

            var signatureValue = signatureToTimestamp.GetSignatureValue();
            var messageHash    = hashAlgorithm.ComputeHash(signatureValue);

            var timestampRequest = new TimestampRequest(
                SigningSpecifications.V1,
                messageHash,
                hashAlgorithm,
                target);

            return(timestampProvider.TimestampSignatureAsync(primarySignature, timestampRequest, logger, CancellationToken.None));
        }
        public void GetRepositoryCountersignature_WithRepositoryCountersignatureWithInvalidV3ServiceIndexUrl_Throws()
        {
            using (var test = new Test(_fixture))
            {
                test.CreateValidAuthorPrimarySignature();

                // Generate countersignature
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateCommitmentTypeIndication(SignatureType.Repository));

                var invalidV3ServiceIndexBytes = DerEncoder.SegmentedEncodeIA5String("notAValidUri".ToCharArray())
                                                 .SelectMany(x => x)
                                                 .ToArray();

                var invalidV3ServiceIndex = new System.Security.Cryptography.CryptographicAttributeObject(
                    new System.Security.Cryptography.Oid(Oids.NuGetV3ServiceIndexUrl),
                    new System.Security.Cryptography.AsnEncodedDataCollection(new System.Security.Cryptography.AsnEncodedData(Oids.NuGetV3ServiceIndexUrl, invalidV3ServiceIndexBytes)));

                test.CounterCmsSigner.SignedAttributes.Add(
                    invalidV3ServiceIndex);
                test.CounterCmsSigner.SignedAttributes.Add(
                    new Pkcs9SigningTime());
                test.CounterCmsSigner.SignedAttributes.Add(
                    AttributeUtility.CreateSigningCertificateV2(test.Certificate, HashAlgorithmName.SHA256));

                // Create counter signature
                test.PrimarySignedCms.SignerInfos[0].ComputeCounterSignature(test.CounterCmsSigner);

                // Load primary signature
                var primarySignature = PrimarySignature.Load(test.PrimarySignedCms.Encode());

                // Validate countersignature
                var exception = Assert.Throws <SignatureException>(
                    () => RepositoryCountersignature.GetRepositoryCountersignature(primarySignature));

                Assert.Equal(NuGetLogCode.NU3000, exception.Code);
                Assert.Equal("The nuget-v3-service-index-url attribute is invalid.", exception.Message);
            }
        }
Exemple #24
0
        /// <summary>
        /// Adds a trusted signer item to the settings based a signed package.
        /// </summary>
        /// <param name="name">Name of the trusted signer.</param>
        /// <param name="package">Package to read signature from.</param>
        /// <param name="trustTarget">Signature to trust from package.</param>
        /// <param name="allowUntrustedRoot">Specifies if allowUntrustedRoot should be set to true.</param>
        /// <param name="owners">Trusted owners that should be set when trusting a repository.</param>
        /// <param name="token">Cancellation token for async request</param>
        public async Task AddTrustedSignerAsync(string name, ISignedPackageReader package, VerificationTarget trustTarget, bool allowUntrustedRoot, IEnumerable <string> owners, CancellationToken token)
        {
            if (package == null)
            {
                throw new ArgumentNullException(nameof(package));
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException(Strings.ArgumentCannotBeNullOrEmpty, nameof(name));
            }

            if (!Enum.IsDefined(typeof(VerificationTarget), trustTarget) || (trustTarget != VerificationTarget.Repository && trustTarget != VerificationTarget.Author))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Strings.Error_UnsupportedTrustTarget, trustTarget.ToString()));
            }

            if (trustTarget == VerificationTarget.Author && owners != null && owners.Any())
            {
                throw new ArgumentException(Strings.Error_TrustedAuthorNoOwners);
            }

            token.ThrowIfCancellationRequested();

            string v3ServiceIndex = null;
            IRepositorySignature repositorySignature = null;
            var trustingRepository = trustTarget.HasFlag(VerificationTarget.Repository);

            var primarySignature = await package.GetPrimarySignatureAsync(token);

            if (primarySignature == null)
            {
                throw new InvalidOperationException(Strings.Error_PackageNotSigned);
            }

            if (trustingRepository)
            {
                if (primarySignature.Type == SignatureType.Repository)
                {
                    repositorySignature = primarySignature as RepositoryPrimarySignature;
                }
                else
                {
                    var countersignature = RepositoryCountersignature.GetRepositoryCountersignature(primarySignature);
                    repositorySignature = countersignature ?? throw new InvalidOperationException(Strings.Error_RepoTrustExpectedRepoSignature);
                }

                v3ServiceIndex = repositorySignature.V3ServiceIndexUrl.AbsoluteUri;
            }

            ValidateNoExistingSigner(name, v3ServiceIndex, trustingRepository);

            if (trustingRepository)
            {
                var certificateItem = GetCertificateItemForSignature(repositorySignature, allowUntrustedRoot);

                _trustedSignersProvider.AddOrUpdateTrustedSigner(new RepositoryItem(name, v3ServiceIndex, CreateOwnersList(owners), certificateItem));

                await _logger.LogAsync(LogLevel.Information, string.Format(CultureInfo.CurrentCulture, Strings.SuccessfullyAddedTrustedRepository, name));
            }
            else
            {
                if (primarySignature.Type != SignatureType.Author)
                {
                    throw new InvalidOperationException(Strings.Error_AuthorTrustExpectedAuthorSignature);
                }

                var certificateItem = GetCertificateItemForSignature(primarySignature, allowUntrustedRoot);

                _trustedSignersProvider.AddOrUpdateTrustedSigner(new AuthorItem(name, certificateItem));

                await _logger.LogAsync(LogLevel.Information, string.Format(CultureInfo.CurrentCulture, Strings.SuccessfullyAddedTrustedAuthor, name));
            }
        }
 private static ExtractedCertificates ExtractRepositoryCountersignatureCertificates(
     Context context,
     RepositoryCountersignature repositoryCountersignature)
 {
     return(ExtractCertificates(context, repositoryCountersignature));
 }