public async Task <bool> SignAsync(string packagePath, string outputPath, string timestampUrl, Uri v3ServiceIndex, IReadOnlyList <string> packageOwners,
                                           SignatureType signatureType, HashAlgorithmName signatureHashAlgorithm, HashAlgorithmName timestampHashAlgorithm,
                                           bool overwrite, X509Certificate2 publicCertificate, System.Security.Cryptography.RSA rsa, CancellationToken cancellationToken = default)
        {
            var packagesToSign = LocalFolderUtility.ResolvePackageFromPath(packagePath);

            var signatureProvider = new KeyVaultSignatureProvider(rsa, new Rfc3161TimestampProvider(new Uri(timestampUrl)));

            SignPackageRequest request = null;

            if (signatureType == SignatureType.Author)
            {
                request = new AuthorSignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm);
            }
            else if (signatureType == SignatureType.Repository)
            {
                request = new RepositorySignPackageRequest(publicCertificate, signatureHashAlgorithm, timestampHashAlgorithm, v3ServiceIndex, packageOwners);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(signatureType));
            }

            string originalPackageCopyPath = null;

            foreach (var package in packagesToSign)
            {
                cancellationToken.ThrowIfCancellationRequested();
                logger.LogInformation($"{nameof(SignAsync)} [{package}]: Begin Signing {Path.GetFileName(package)}");
                try
                {
                    originalPackageCopyPath = CopyPackage(package);

                    using var options = SigningOptions.CreateFromFilePaths(originalPackageCopyPath, outputPath, overwrite, signatureProvider, new NuGetLogger(logger, package));
                    await SigningUtility.SignAsync(options, request, cancellationToken);
                }
                catch (Exception e)
                {
                    logger.LogError(e, e.Message);
                    return(false);
                }
                finally
                {
                    try
                    {
                        FileUtility.Delete(originalPackageCopyPath);
                    }
                    catch
                    {
                    }

                    logger.LogInformation($"{nameof(SignAsync)} [{package}]: End Signing {Path.GetFileName(package)}");
                }
            }

            return(true);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        public async Task <int> SignAsync(string file,
                                          string timestampUrl,
                                          HashAlgorithmName signatureHashAlgorithm,
                                          HashAlgorithmName timestampeHashAlgorithm,
                                          string keyVaultCertificateName,
                                          string keyVaultUrl,
                                          string keyVaultClientId,
                                          string keyVaultClientSecret,
                                          string keyVaultAccessToken)
        {
            string validatedToken = null;

            async Task <string> Authenticate(string authority, string resource, string scope)
            {
                if (!string.IsNullOrWhiteSpace(keyVaultAccessToken))
                {
                    validatedToken = keyVaultAccessToken;
                    return(keyVaultAccessToken);
                }

                var context    = new AuthenticationContext(authority);
                var credential = new ClientCredential(keyVaultClientId, keyVaultClientSecret);

                var result = await context.AcquireTokenAsync(resource, credential)
                             .ConfigureAwait(false);

                if (result == null)
                {
                    throw new InvalidOperationException("Authentication to Azure failed.");
                }
                validatedToken = result.AccessToken;
                return(result.AccessToken);
            }

            var client = new KeyVaultClient(Authenticate, new HttpClient());

            // We call this here to verify it's a valid cert
            // It also implicitly validates the access token or credentials
            var kvcert = await client.GetCertificateAsync(keyVaultUrl, keyVaultCertificateName)
                         .ConfigureAwait(false);

            var cert = new X509Certificate2(kvcert.Cer);



            var rsa = client.ToRSA(kvcert.KeyIdentifier, cert);

            // TODO: Add Hash Alg choice
            var request = new SignPackageRequest()
            {
                Certificate            = cert,
                SignatureHashAlgorithm = signatureHashAlgorithm,
                TimestampHashAlgorithm = timestampeHashAlgorithm
            };

            string tempFilePath = null;

            try
            {
                tempFilePath = CopyPackage(file);
                var signatureProvider = new KeyVaultSignatureProvider(rsa, new Rfc3161TimestampProvider(new Uri(timestampUrl)));

                // remove first to overwrite
                // This command overwrites by default, like signtool
                using (var packageWriteStream = File.Open(tempFilePath, FileMode.Open))
                    using (var package = new SignedPackageArchive(packageWriteStream))
                    {
                        var signer = new Signer(package, signatureProvider);
                        await signer.RemoveSignaturesAsync(new NullLogger(), CancellationToken.None);
                    }

                // Now sign
                using (var packageWriteStream = File.Open(tempFilePath, FileMode.Open))
                    using (var package = new SignedPackageArchive(packageWriteStream))
                    {
                        var signer = new Signer(package, signatureProvider);
                        await signer.SignAsync(request, new NullLogger(), CancellationToken.None);
                    }

                OverwritePackage(tempFilePath, file);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                Console.Error.WriteLine(e.StackTrace);
                return(-1);
            }
            finally
            {
                try
                {
                    FileUtility.Delete(tempFilePath);
                }
                catch
                {
                }
            }

            return(0);
        }