public void CreateSignedAttributes_SignPackageRequest_WithValidInput_ReturnsAttributes() { using (var rootCertificate = SigningTestUtility.GetCertificate("root.crt")) using (var intermediateCertificate = SigningTestUtility.GetCertificate("intermediate.crt")) using (var leafCertificate = SigningTestUtility.GetCertificate("leaf.crt")) using (var request = CreateRequest(leafCertificate)) { var certList = new[] { leafCertificate, intermediateCertificate, rootCertificate }; var attributes = SigningUtility.CreateSignedAttributes(request, certList); Assert.Equal(3, attributes.Count); VerifyAttributes(attributes, request); } }
public async Task SignAsync_WhenCertificateSignatureAlgorithmIsUnsupported_ThrowsAsync() { using (var certificate = SigningTestUtility.GenerateCertificate( "test", generator => { }, "SHA256WITHRSAANDMGF1")) using (var test = SignTest.Create(certificate, HashAlgorithmName.SHA256)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3013, exception.Code); Assert.Equal("The signing certificate has an unsupported signature algorithm.", exception.Message); } }
public void CreateSignedAttributes_RepositorySignPackageRequest_WhenPackageOwnersNonEmpty_ReturnsAttributes() { var v3ServiceIndexUrl = new Uri("https://test.test", UriKind.Absolute); var packageOwners = new[] { "a" }; using (var certificate = _fixture.GetDefaultCertificate()) using (var request = CreateRequestRepository(certificate, v3ServiceIndexUrl, packageOwners)) { var attributes = SigningUtility.CreateSignedAttributes(request, new[] { certificate }); Assert.Equal(5, attributes.Count); VerifyAttributesRepository(attributes, request); } }
public async Task SignAsync_WhenCertificatePublicKeyLengthIsUnsupported_ThrowsAsync() { using (var certificate = SigningTestUtility.GenerateCertificate( "test", generator => { }, publicKeyLength: 1024)) using (var test = SignTest.Create(certificate, HashAlgorithmName.SHA256)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3014, exception.Code); Assert.Equal("The signing certificate does not meet a minimum public key length requirement.", exception.Message); } }
public static async Task CreateSignedPackageAsync( SignPackageRequest request, Stream packageReadStream, Stream packageWriteStream) { using (var signedPackage = new SignedPackageArchive(packageReadStream, packageWriteStream)) using (var options = new SigningOptions( new Lazy <Stream>(() => packageReadStream), new Lazy <Stream>(() => packageWriteStream), overwrite: false, signatureProvider: new X509SignatureProvider(timestampProvider: null), logger: NullLogger.Instance)) { await SigningUtility.SignAsync(options, request, CancellationToken.None); } }
public async Task SignAsync_WhenCertificateSignatureAlgorithmIsUnsupported_ThrowsAsync() { using (var certificate = SigningTestUtility.GenerateCertificate( "test", generator => { }, Common.HashAlgorithmName.SHA256, System.Security.Cryptography.RSASignaturePaddingMode.Pss)) using (var test = SignTest.Create(certificate, HashAlgorithmName.SHA256)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3013, exception.Code); Assert.Contains("The signing certificate has an unsupported signature algorithm.", exception.Message); } }
public async Task SignAsync_WithNotYetValidCertificate_ThrowsAsync() { using (var test = await Test.CreateAsync(_testFixture.TrustedTestCertificateNotYetValid.Source.Cert)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3017, exception.Code); Assert.Contains("The signing certificate is not yet valid", exception.Message); var isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.InputPackageStream); Assert.False(isSigned); Assert.False(test.OutputFile.Exists); } }
public async Task SignAsync_WithExpiredCertificate_ThrowsAsync() { using (var test = new Test(_testFixture.TrustedTestCertificateExpired.Source.Cert)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3018, exception.Code); Assert.Contains("Certificate chain validation failed.", exception.Message); var isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.InputPackageStream); Assert.False(isSigned); Assert.False(test.OutputFile.Exists); } }
public void GetCertificateChain_WithUntrustedRoot_Throws() { using (var chain = new X509Chain()) using (var rootCertificate = GetCertificate("root.crt")) using (var intermediateCertificate = GetCertificate("intermediate.crt")) using (var leafCertificate = GetCertificate("leaf.crt")) { var extraStore = new X509Certificate2Collection(); extraStore.Add(rootCertificate); extraStore.Add(intermediateCertificate); var exception = Assert.Throws <SignatureException>( () => SigningUtility.GetCertificateChain(leafCertificate, extraStore)); Assert.Equal(NuGetLogCode.NU3018, exception.Code); } }
public async Task SignAsync_WhenRepositoryCountersigningRepositoryCountersignedPackage_ThrowsAsync() { using (var test = await Test.CreateAsync(_testFixture.TrustedTestCertificate.Source.Cert)) { await SigningUtility.SignAsync(test.Options, test.AuthorRequest, CancellationToken.None); using (var package = new PackageArchiveReader(test.Options.OutputPackageStream)) { var isSigned = await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream); Assert.True(isSigned); } var countersignedPackageOutputPath = test.GetNewTempFilePath(); using (var countersignatureOptions = SigningOptions.CreateFromFilePaths( test.OutputFile.FullName, countersignedPackageOutputPath, overwrite: false, signatureProvider: new X509SignatureProvider(timestampProvider: null), logger: NullLogger.Instance)) { await SigningUtility.SignAsync(countersignatureOptions, test.RepositoryRequest, CancellationToken.None); var isRepositoryCountersigned = await SignedArchiveTestUtility.IsRepositoryCountersignedAsync(countersignatureOptions.OutputPackageStream); Assert.True(isRepositoryCountersigned); } using (var countersignatureOptions = SigningOptions.CreateFromFilePaths( countersignedPackageOutputPath, test.GetNewTempFilePath(), overwrite: false, signatureProvider: new X509SignatureProvider(timestampProvider: null), logger: NullLogger.Instance)) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(countersignatureOptions, test.RepositoryRequest, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3032, exception.Code); Assert.Contains("The package already contains a repository countersignature", exception.Message); } } }
/// <summary> /// Generates a SignedCMS object for some content. /// </summary> /// <param name="content"></param> /// <param name="cert">Certificate for cms signer</param> /// <returns>SignedCms object</returns> public static SignedCms GenerateRepositoryCountersignedSignedCms(X509Certificate2 cert, byte[] content) { var contentInfo = new ContentInfo(content); var hashAlgorithm = NuGet.Common.HashAlgorithmName.SHA256; using (var primarySignatureRequest = new AuthorSignPackageRequest(new X509Certificate2(cert), hashAlgorithm)) using (var countersignatureRequest = new RepositorySignPackageRequest(new X509Certificate2(cert), hashAlgorithm, hashAlgorithm, new Uri("https://api.nuget.org/v3/index.json"), null)) { var cmsSigner = SigningUtility.CreateCmsSigner(primarySignatureRequest, NullLogger.Instance); var cms = new SignedCms(contentInfo); cms.ComputeSignature(cmsSigner); var counterCmsSigner = SigningUtility.CreateCmsSigner(countersignatureRequest, NullLogger.Instance); cms.SignerInfos[0].ComputeCounterSignature(counterCmsSigner); return(cms); } }
public async Task SignAsync_WithUntrustedSelfSignedCertificate_SucceedsAsync() { using (var packageStream = new SimpleTestPackageContext().CreateAsStream()) using (var test = SignTest.Create( _fixture.GetDefaultCertificate(), HashAlgorithmName.SHA256, packageStream.ToArray(), new X509SignatureProvider(timestampProvider: null))) { await SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None); Assert.True(await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream)); Assert.Equal(0, test.Logger.Errors); Assert.Equal(1, test.Logger.Warnings); Assert.Equal(1, test.Logger.Messages.Count()); Assert.True(test.Logger.Messages.Contains("A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.")); } }
public async Task SignAsync_WhenPackageEntryCountWouldRequireZip64_FailsAsync() { const ushort desiredFileCount = 0xFFFF - 1; var package = new SimpleTestPackageContext(); var requiredFileCount = desiredFileCount - package.Files.Count; for (var i = 0; i < requiredFileCount - 1 /*nuspec*/; ++i) { package.AddFile(i.ToString()); } using (var packageStream = await package.CreateAsStreamAsync()) { using (var zipArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, leaveOpen: true)) { // Sanity check before testing. Assert.Equal(desiredFileCount, zipArchive.Entries.Count()); } packageStream.Position = 0; using (var test = SignTest.Create( _fixture.GetDefaultCertificate(), HashAlgorithmName.SHA256, packageStream.ToArray(), new X509SignatureProvider(timestampProvider: null))) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3039, exception.Code); Assert.Equal("The package cannot be signed as it would require the Zip64 format.", exception.Message); Assert.Equal(0, test.Options.OutputPackageStream.Length); Assert.Equal(0, test.Logger.Errors); Assert.Equal(1, test.Logger.Warnings); Assert.Equal(1, test.Logger.Messages.Count()); Assert.True(test.Logger.Messages.Contains("A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.")); } } }
public void Verify_WithUntrustedSelfSignedCertificate_Succeeds() { using (var certificate = _fixture.GetDefaultCertificate()) using (var request = CreateRequest(certificate)) { var logger = new TestLogger(); SigningUtility.Verify(request, logger); Assert.Equal(0, logger.Errors); Assert.Equal(RuntimeEnvironmentHelper.IsWindows ? 1 : 2, logger.Warnings); AssertUntrustedRoot(logger.LogMessages, LogLevel.Warning); if (!RuntimeEnvironmentHelper.IsWindows) { AssertOfflineRevocation(logger.LogMessages, LogLevel.Warning); } } }
/// <summary> /// Sign and timestamp a package for test purposes. /// This method timestamps a package and should only be used with tests marked with [CIOnlyFact] /// </summary> private static async Task SignAndTimeStampPackageAsync( TestLogger testLogger, string inputPackagePath, string outputPackagePath, Uri timestampService, AuthorSignPackageRequest request) { var testSignatureProvider = new X509SignatureProvider(new Rfc3161TimestampProvider(timestampService)); var overwrite = false; using (var options = SigningOptions.CreateFromFilePaths( inputPackagePath, outputPackagePath, overwrite, testSignatureProvider, testLogger)) { await SigningUtility.SignAsync(options, request, CancellationToken.None); } }
public void GetCertificateChain_ReturnsCertificatesInOrder() { using (var chain = new X509Chain()) using (var rootCertificate = GetCertificate("root.crt")) using (var intermediateCertificate = GetCertificate("intermediate.crt")) using (var leafCertificate = GetCertificate("leaf.crt")) { chain.ChainPolicy.ExtraStore.Add(rootCertificate); chain.ChainPolicy.ExtraStore.Add(intermediateCertificate); chain.Build(leafCertificate); var certificateChain = SigningUtility.GetCertificateChain(chain); Assert.Equal(3, certificateChain.Count); Assert.Equal(leafCertificate.Thumbprint, certificateChain[0].Thumbprint); Assert.Equal(intermediateCertificate.Thumbprint, certificateChain[1].Thumbprint); Assert.Equal(rootCertificate.Thumbprint, certificateChain[2].Thumbprint); } }
/// <summary> /// Sign a package for test purposes. /// This does not timestamp a signature and can be used outside corp network. /// </summary> private static async Task SignPackageAsync(TestLogger testLogger, X509Certificate2 certificate, string inputPackagePath, string outputPackagePath) { #if IS_DESKTOP var testSignatureProvider = new X509SignatureProvider(timestampProvider: null); using (var cert = new X509Certificate2(certificate)) using (var request = new AuthorSignPackageRequest(cert, HashAlgorithmName.SHA256)) { const bool overwrite = false; using (var options = SigningOptions.CreateFromFilePaths( inputPackagePath, outputPackagePath, overwrite, testSignatureProvider, testLogger)) { await SigningUtility.SignAsync(options, request, CancellationToken.None); } } #endif }
public void CreateCmsSigner_WithRepositorySignPackageRequest_ReturnsInstance() { var v3ServiceIndexUrl = new Uri("https://test.test", UriKind.Absolute); var packageOwners = new[] { "a", "b", "c" }; using (var certificate = _fixture.GetDefaultCertificate()) using (var request = new RepositorySignPackageRequest( certificate, Common.HashAlgorithmName.SHA256, Common.HashAlgorithmName.SHA256, v3ServiceIndexUrl, packageOwners)) { var signer = SigningUtility.CreateCmsSigner(request, NullLogger.Instance); Assert.Equal(request.Certificate, signer.Certificate); Assert.Equal(request.SignatureHashAlgorithm.ConvertToOidString(), signer.DigestAlgorithm.Value); VerifyAttributesRepository(signer.SignedAttributes, request); } }
public async Task SignAsync_WithUntrustedSelfSignedCertificate_SucceedsAsync() { var package = new SimpleTestPackageContext(); using (var packageStream = await package.CreateAsStreamAsync()) using (var test = SignTest.Create( _fixture.GetDefaultCertificate(), HashAlgorithmName.SHA256, packageStream.ToArray(), new X509SignatureProvider(timestampProvider: null))) { await SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None); Assert.True(await SignedArchiveTestUtility.IsSignedAsync(test.Options.OutputPackageStream)); Assert.Equal(0, test.Logger.Errors); Assert.Equal(1, test.Logger.Warnings); Assert.Equal(1, test.Logger.Messages.Count()); SigningTestUtility.AssertUntrustedRoot(test.Logger.LogMessages, LogLevel.Warning); } }
public async Task <bool> SignAsync(string packagePath, string outputPath, string timestampUrl, HashAlgorithmName signatureHashAlgorithm, HashAlgorithmName timestampHashAlgorithm, bool overwrite, X509Certificate2 publicCertificate, System.Security.Cryptography.RSA rsa) { var fileName = Path.GetFileName(packagePath); logger.LogInformation($"{nameof(SignAsync)} [{fileName}]: Begin Signing {packagePath}"); var signatureProvider = new KeyVaultSignatureProvider(rsa, new Rfc3161TimestampProvider(new Uri(timestampUrl))); var request = new AuthorSignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm); string originalPackageCopyPath = null; try { originalPackageCopyPath = CopyPackage(packagePath); using (var options = SigningOptions.CreateFromFilePaths(originalPackageCopyPath, outputPath, overwrite, signatureProvider, new NuGetLogger(logger, fileName))) { await SigningUtility.SignAsync(options, request, CancellationToken.None); } } catch (Exception e) { logger.LogError(e, e.Message); return(false); } finally { try { FileUtility.Delete(originalPackageCopyPath); } catch { } logger.LogInformation($"{nameof(SignAsync)} [{fileName}]: End Signing {packagePath}"); } return(true); }
internal async Task RepositoryCountersignAsync() { PrimarySignature primarySignature; using (var archiveReader = new PackageArchiveReader(SignedPackage)) { primarySignature = await archiveReader.GetPrimarySignatureAsync(CancellationToken.None); } using (var request = new RepositorySignPackageRequest( new X509Certificate2(Certificate), HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, new Uri("https://test.test"), packageOwners: null)) { var cmsSigner = SigningUtility.CreateCmsSigner(request, NullLogger.Instance); var signedCms = primarySignature.SignedCms; signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner); primarySignature = PrimarySignature.Load(signedCms.Encode()); } using (var originalPackage = new MemoryStream(Zip.ToByteArray(), writable: false)) using (var signedPackage = new MemoryStream()) using (var archive = new SignedPackageArchive(originalPackage, signedPackage)) using (var signatureStream = new MemoryStream(primarySignature.GetBytes())) { await archive.AddSignatureAsync(signatureStream, CancellationToken.None); SignedPackage = new MemoryStream(signedPackage.ToArray(), writable: false); } var isSigned = await SignedArchiveTestUtility.IsSignedAsync(SignedPackage); Assert.True(isSigned); }
public async Task SignAsync_WhenChainBuildingFails_ThrowsAsync() { var package = new SimpleTestPackageContext(); using (var packageStream = await package.CreateAsStreamAsync()) using (var test = SignTest.Create( _fixture.GetExpiredCertificate(), HashAlgorithmName.SHA256, packageStream.ToArray(), new X509SignatureProvider(timestampProvider: null))) { var exception = await Assert.ThrowsAsync <SignatureException>( () => SigningUtility.SignAsync(test.Options, test.Request, CancellationToken.None)); Assert.Equal(NuGetLogCode.NU3018, exception.Code); Assert.Equal("Certificate chain validation failed.", exception.Message); Assert.Equal(1, test.Logger.Errors); Assert.Equal(1, test.Logger.Warnings); SigningTestUtility.AssertNotTimeValid(test.Logger.LogMessages, LogLevel.Error); SigningTestUtility.AssertUntrustedRoot(test.Logger.LogMessages, LogLevel.Warning); } }
internal static async Task <Test> CreateAsync( X509Certificate2 certificate, Uri v3ServiceIndexUrl = null, IReadOnlyList <string> packageOwners = null) { v3ServiceIndexUrl = v3ServiceIndexUrl ?? new Uri("https://test.test"); var test = await CreateWithoutRepositoryCountersignatureAsync(certificate); var request = new RepositorySignPackageRequest( new X509Certificate2(certificate), HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, v3ServiceIndexUrl, packageOwners); var cmsSigner = SigningUtility.CreateCmsSigner(request, NullLogger.Instance); var signedCms = test.PrimarySignature.SignedCms; signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner); var primarySignature = PrimarySignature.Load(signedCms.Encode()); return(new Test(request, primarySignature)); }
public async Task <int> ExecuteCommandAsync( IEnumerable <string> packagesToSign, SignPackageRequest signPackageRequest, string timestamper, ILogger logger, string outputDirectory, bool overwrite, CancellationToken token) { var success = true; try { SigningUtility.Verify(signPackageRequest, logger); } catch (Exception e) { success = false; ExceptionUtilities.LogException(e, logger); } if (success) { var signatureProvider = GetSignatureProvider(timestamper); foreach (var packagePath in packagesToSign) { // Set the output of the signing operation to a temp file because signing cannot be done in place. var tempPackageFile = new FileInfo(Path.GetTempFileName()); try { string outputPath; if (string.IsNullOrEmpty(outputDirectory)) { outputPath = packagePath; } else { outputPath = Path.Combine(outputDirectory, Path.GetFileName(packagePath)); } using (var options = SigningOptions.CreateFromFilePaths( packagePath, tempPackageFile.FullName, overwrite, signatureProvider, logger)) { await SigningUtility.SignAsync(options, signPackageRequest, token); } if (tempPackageFile.Length > 0) { FileUtility.Replace(tempPackageFile.FullName, outputPath); } else { throw new SignatureException(Strings.Error_UnableToSignPackage); } } catch (Exception e) { success = false; ExceptionUtilities.LogException(e, logger); } finally { FileUtility.Delete(tempPackageFile.FullName); } } } if (success) { logger.LogInformation(Strings.SignCommandSuccess); } return(success ? 0 : 1); }