private static async Task AddRepositoryCountersignatureToSignedPackageAsync(SimpleTestPackageContext packageContext, ISignedPackage package, RepositorySignPackageRequest request, ILogger logger) { var primarySignature = await package.GetPrimarySignatureAsync(CancellationToken.None); if (primarySignature != null) { var testSignatureProvider = new X509SignatureProvider(packageContext.CounterTimestampProvider); var signature = await testSignatureProvider.CreateRepositoryCountersignatureAsync(request, primarySignature, logger, CancellationToken.None); using (var stream = new MemoryStream(signature.GetBytes())) { await package.AddSignatureAsync(stream, CancellationToken.None); } } }
/// <summary> /// Adds a Repository countersignature to a given primary signature /// </summary> /// <param name="testCert">Certificate to be used while generating the countersignature.</param> /// <param name="primarySignature">Primary signature to add countersignature.</param> /// <param name="timestampProvider">An optional timestamp provider.</param> /// <returns></returns> public static async Task <PrimarySignature> RepositoryCountersignPrimarySignatureAsync( X509Certificate2 testCert, PrimarySignature primarySignature, ITimestampProvider timestampProvider = null) { var testLogger = new TestLogger(); var hashAlgorithm = HashAlgorithmName.SHA256; var v3ServiceIndexUrl = new Uri("https://v3serviceIndex.test/api/index.json"); using (var request = new RepositorySignPackageRequest(testCert, hashAlgorithm, hashAlgorithm, v3ServiceIndexUrl, null)) { var testSignatureProvider = new X509SignatureProvider(timestampProvider); return(await testSignatureProvider.CreateRepositoryCountersignatureAsync(request, primarySignature, testLogger, CancellationToken.None)); } }
private static async Task AddSignatureToPackageAsync(SimpleTestPackageContext packageContext, ISignedPackage package, SignPackageRequest request, ILogger logger) { var testSignatureProvider = new X509SignatureProvider(packageContext.PrimaryTimestampProvider); var zipArchiveHash = await package.GetArchiveHashAsync(request.SignatureHashAlgorithm, CancellationToken.None); var base64ZipArchiveHash = Convert.ToBase64String(zipArchiveHash); var signatureContent = new SignatureContent(SigningSpecifications.V1, request.SignatureHashAlgorithm, base64ZipArchiveHash); var signature = await testSignatureProvider.CreatePrimarySignatureAsync(request, signatureContent, logger, CancellationToken.None); using (var stream = new MemoryStream(signature.GetBytes())) { await package.AddSignatureAsync(stream, CancellationToken.None); } }
internal Test(X509Certificate2 certificate) { _directory = TestDirectory.Create(); _certificate = new X509Certificate2(certificate); var packageContext = new SimpleTestPackageContext(); ReadStream = packageContext.CreateAsStream(); WriteStream = packageContext.CreateAsStream(); Package = new SignedPackageArchive(ReadStream, WriteStream); Request = new AuthorSignPackageRequest(_certificate, HashAlgorithmName.SHA256); var signatureProvider = new X509SignatureProvider(timestampProvider: null); Signer = new Signer(Package, signatureProvider); }
/// <summary> /// Generates a Signature for a given package for tests. /// </summary> /// <param name="package">Package to be used for the signature.</param> /// <param name="request">Sign package request for primary signature</param> /// <param name="timestampProvider">Provider to add timestamp to package. Defaults to null.</param> /// <returns>Signature for the package.</returns> public static async Task <PrimarySignature> CreatePrimarySignatureForPackageAsync( PackageArchiveReader package, SignPackageRequest request, ITimestampProvider timestampProvider = null) { Assert.False(await package.IsSignedAsync(CancellationToken.None)); var testLogger = new TestLogger(); var signatureProvider = new X509SignatureProvider(timestampProvider); var zipArchiveHash = await package.GetArchiveHashAsync(request.SignatureHashAlgorithm, CancellationToken.None); var base64ZipArchiveHash = Convert.ToBase64String(zipArchiveHash); var signatureContent = new SignatureContent(SigningSpecifications.V1, request.SignatureHashAlgorithm, base64ZipArchiveHash); return(await signatureProvider.CreatePrimarySignatureAsync(request, signatureContent, testLogger, CancellationToken.None)); }
/// <summary> /// Generates a Signature for a package. /// </summary> /// <param name="testCert">Certificate to be used while generating the signature.</param> /// <param name="nupkg">Package for which the signature has to be generated.</param> /// <returns>Signature for the package.</returns> public static async Task <Signature> CreateSignatureForPackageAsync(X509Certificate2 testCert, Stream packageStream) { var testLogger = new TestLogger(); var hashAlgorithm = HashAlgorithmName.SHA256; using (var request = new SignPackageRequest(testCert, hashAlgorithm)) using (var package = new PackageArchiveReader(packageStream, leaveStreamOpen: true)) { var zipArchiveHash = await package.GetArchiveHashAsync(request.SignatureHashAlgorithm, CancellationToken.None); var base64ZipArchiveHash = Convert.ToBase64String(zipArchiveHash); var signatureContent = new SignatureContent(SigningSpecifications.V1, hashAlgorithm, base64ZipArchiveHash); var testSignatureProvider = new X509SignatureProvider(timestampProvider: null); return(await testSignatureProvider.CreateSignatureAsync(request, signatureContent, testLogger, CancellationToken.None)); } }
public async Task GetTrustResultAsync_SettingsRequireExactlyOneTimestamp_MultipleTimestamps_Fails() { // Arrange var nupkg = new SimpleTestPackageContext(); var testLogger = new TestLogger(); var timestampService = await _testFixture.GetDefaultTrustedTimestampServiceAsync(); var setting = new SignedPackageVerifierSettings( allowUnsigned: false, allowUntrusted: false, allowUntrustedSelfSignedCertificate: false, allowIgnoreTimestamp: false, allowMultipleTimestamps: false, allowNoTimestamp: false, allowUnknownRevocation: false); var signatureProvider = new X509SignatureProvider(timestampProvider: null); var timestampProvider = new Rfc3161TimestampProvider(timestampService.Url); var verificationProvider = new SignatureTrustAndValidityVerificationProvider(); using (var package = new PackageArchiveReader(nupkg.CreateAsStream(), leaveStreamOpen: false)) using (var testCertificate = new X509Certificate2(_trustedTestCert.Source.Cert)) using (var signatureRequest = new AuthorSignPackageRequest(testCertificate, HashAlgorithmName.SHA256)) { var signature = await SignedArchiveTestUtility.CreateSignatureForPackageAsync(signatureProvider, package, signatureRequest, testLogger); var timestampedSignature = await SignedArchiveTestUtility.TimestampSignature(timestampProvider, signatureRequest, signature, testLogger); var reTimestampedSignature = await SignedArchiveTestUtility.TimestampSignature(timestampProvider, signatureRequest, timestampedSignature, testLogger); timestampedSignature.Timestamps.Count.Should().Be(1); reTimestampedSignature.Timestamps.Count.Should().Be(2); // Act var result = await verificationProvider.GetTrustResultAsync(package, reTimestampedSignature, setting, CancellationToken.None); var totalErrorIssues = result.GetErrorIssues(); // Assert result.Trust.Should().Be(SignatureVerificationStatus.Invalid); totalErrorIssues.Count().Should().Be(1); totalErrorIssues.First().Code.Should().Be(NuGetLogCode.NU3000); } }
/// <summary> /// unsigns a package for test purposes. /// This does not timestamp a signature and can be used outside corp network. /// </summary> public static async Task ShiftSignatureMetadataAsync(SigningSpecifications spec, string signedPackagePath, string dir, int centralDirectoryIndex, int fileHeaderIndex) { var testLogger = new TestLogger(); var testSignatureProvider = new X509SignatureProvider(timestampProvider: null); // Create a temp path var copiedSignedPackagePath = Path.Combine(dir, Guid.NewGuid().ToString()); using (var signedReadStream = File.OpenRead(signedPackagePath)) using (var signedPackage = new BinaryReader(signedReadStream)) using (var shiftedWriteStream = File.OpenWrite(copiedSignedPackagePath)) using (var shiftedPackage = new BinaryWriter(shiftedWriteStream)) { await ShiftSignatureMetadata(spec, signedPackage, shiftedPackage, centralDirectoryIndex, fileHeaderIndex); } // Overwrite the original package with the shifted one File.Copy(copiedSignedPackagePath, signedPackagePath, overwrite: true); }
private Test(X509Certificate2 certificate, TestDirectory dir, FileInfo package) { _authorCertificate = new X509Certificate2(certificate); _repositoryCertificate = new X509Certificate2(certificate); _directory = dir; var outputPath = GetNewTempFilePath(); OutputFile = new FileInfo(outputPath); var signatureProvider = new X509SignatureProvider(timestampProvider: null); AuthorRequest = new AuthorSignPackageRequest(_authorCertificate, HashAlgorithmName.SHA256); RepositoryRequest = new RepositorySignPackageRequest(_repositoryCertificate, HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, new Uri("https://test/api/index.json"), packageOwners: null); var overwrite = true; Options = SigningOptions.CreateFromFilePaths(package.FullName, outputPath, overwrite, signatureProvider, NullLogger.Instance); }
/// <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); } }
/// <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 }
internal Test(X509Certificate2 certificate) { _directory = TestDirectory.Create(); _authorCertificate = new X509Certificate2(certificate); _repositoryCertificate = new X509Certificate2(certificate); var outputPath = GetNewTempFilePath(); OutputFile = new FileInfo(outputPath); var packageContext = new SimpleTestPackageContext(); var packageFileName = Guid.NewGuid().ToString(); var package = packageContext.CreateAsFile(_directory, packageFileName); var signatureProvider = new X509SignatureProvider(timestampProvider: null); AuthorRequest = new AuthorSignPackageRequest(_authorCertificate, HashAlgorithmName.SHA256); RepositoryRequest = new RepositorySignPackageRequest(_repositoryCertificate, HashAlgorithmName.SHA256, HashAlgorithmName.SHA256, new Uri("https://test/api/index.json"), packageOwners: null); var overwrite = true; Options = SigningOptions.CreateFromFilePaths(package.FullName, outputPath, overwrite, signatureProvider, NullLogger.Instance); }
/// <summary> /// Write a zip file to a stream. /// </summary> public static void CreatePackage(Stream stream, SimpleTestPackageContext packageContext) { var id = packageContext.Id; var version = packageContext.Version; var runtimeJson = packageContext.RuntimeJson; var pathResolver = new VersionFolderPathResolver(null); var testLogger = new TestLogger(); var tempStream = stream; var isUsingTempStream = false; if (packageContext.AuthorSignatureCertificate != null) { tempStream = new MemoryStream(); isUsingTempStream = true; } using (var zip = new ZipArchive(tempStream, ZipArchiveMode.Create, leaveOpen: true)) { if (packageContext.Files.Any()) { foreach (var entryFile in packageContext.Files) { zip.AddEntry(entryFile.Key, entryFile.Value); } } else { zip.AddEntry("contentFiles/any/any/config.xml", new byte[] { 0 }); zip.AddEntry("contentFiles/cs/net45/code.cs", new byte[] { 0 }); zip.AddEntry("lib/net45/a.dll", new byte[] { 0 }); zip.AddEntry("lib/netstandard1.0/a.dll", new byte[] { 0 }); zip.AddEntry($"build/net45/{id}.targets", @"<targets />", Encoding.UTF8); zip.AddEntry("runtimes/any/native/a.dll", new byte[] { 0 }); zip.AddEntry("tools/a.exe", new byte[] { 0 }); } if (!string.IsNullOrEmpty(runtimeJson)) { zip.AddEntry("runtime.json", runtimeJson, Encoding.UTF8); } var frameworkAssembliesAndContentFiles = packageContext.UseDefaultRuntimeAssemblies ? $@"<frameworkAssemblies> <frameworkAssembly assemblyName=""System.Runtime""/> </frameworkAssemblies> <contentFiles> <files include=""cs/net45/config/config.xml"" buildAction=""none"" /> <files include=""cs/net45/config/config.xml"" copyToOutput=""true"" flatten=""false"" /> <files include=""cs/net45/images/image.jpg"" buildAction=""embeddedresource"" /> </contentFiles>" : string.Empty; var nuspecXml = packageContext.Nuspec?.ToString() ?? $@"<?xml version=""1.0"" encoding=""utf-8""?> <package> <metadata> <id>{id}</id> <version>{version.ToString()}</version> <title /> {frameworkAssembliesAndContentFiles} </metadata> </package>"; var xml = XDocument.Parse(nuspecXml); // Add the min client version if it exists if (!string.IsNullOrEmpty(packageContext.MinClientVersion)) { xml.Root.Element(XName.Get("metadata")) .Add(new XAttribute(XName.Get("minClientVersion"), packageContext.MinClientVersion)); } var dependencies = packageContext.Dependencies.Select(e => new PackageDependency( e.Id, VersionRange.Parse(e.Version), string.IsNullOrEmpty(e.Include) ? new List <string>() : e.Include.Split(',').ToList(), string.IsNullOrEmpty(e.Exclude) ? new List <string>() : e.Exclude.Split(',').ToList())); if (dependencies.Any()) { var metadata = xml.Element(XName.Get("package")).Element(XName.Get("metadata")); var dependenciesNode = new XElement(XName.Get("dependencies")); var groupNode = new XElement(XName.Get("group")); dependenciesNode.Add(groupNode); metadata.Add(dependenciesNode); foreach (var dependency in dependencies) { var node = new XElement(XName.Get("dependency")); groupNode.Add(node); node.Add(new XAttribute(XName.Get("id"), dependency.Id)); node.Add(new XAttribute(XName.Get("version"), dependency.VersionRange.ToNormalizedString())); if (dependency.Include.Count > 0) { node.Add(new XAttribute(XName.Get("include"), string.Join(",", dependency.Include))); } if (dependency.Exclude.Count > 0) { node.Add(new XAttribute(XName.Get("exclude"), string.Join(",", dependency.Exclude))); } } } if (packageContext.PackageTypes.Count > 0) { var metadata = xml.Element("package").Element("metadata"); var packageTypes = new XElement("packageTypes"); metadata.Add(packageTypes); foreach (var packageType in packageContext.PackageTypes) { var packageTypeElement = new XElement("packageType"); packageTypeElement.Add(new XAttribute("name", packageType.Name)); if (packageType.Version != PackageType.EmptyVersion) { packageTypeElement.Add(new XAttribute("version", packageType.Version)); } packageTypes.Add(packageTypeElement); } } zip.AddEntry($"{id}.nuspec", xml.ToString(), Encoding.UTF8); } if (isUsingTempStream) { using (var signPackage = new SignedPackageArchive(tempStream, stream)) { var testSignatureProvider = new X509SignatureProvider(timestampProvider: null); var signer = new Signer(signPackage, testSignatureProvider); var request = new AuthorSignPackageRequest(packageContext.AuthorSignatureCertificate, hashAlgorithm: HashAlgorithmName.SHA256); signer.SignAsync(request, testLogger, CancellationToken.None).Wait(); } tempStream.Dispose(); } // Reset position stream.Position = 0; }