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); }
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)); }
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)); }
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)); }
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); }
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); }
// 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); }
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); } }
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); } } }
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 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); } }
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); } }
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))); } }
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); } }
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); } }