// Inspired from https://github.com/squaredup/bettersigntool/blob/master/bettersigntool/bettersigntool/SignCommand.cs async Task <bool> Sign(string file, SignConfigurationSet config, string timestampUrl, HashAlgorithmName alg) { var retry = TimeSpan.FromSeconds(5); var attempt = 1; do { if (attempt > 1) { logger.LogInformation($"Performing attempt #{attempt} of 3 attempts after {retry.TotalSeconds}s"); await Task.Delay(retry); retry = TimeSpan.FromSeconds(Math.Pow(retry.TotalSeconds, 1.5)); } if (await RunSignTool(file, config, timestampUrl, alg)) { logger.LogInformation($"Signed successfully"); return(true); } attempt++; } while (attempt <= 3); logger.LogError($"Failed to sign. Attempts exceeded"); throw new Exception($"Could not sign {file}"); }
async Task SubmitInternal(HashMode hashMode, string name, IList <string> files) { logger.LogInformation("Signing OpenVsixSignTool job {0} with {1} files", name, files.Count()); // Dual isn't supported, use sha256 var alg = hashMode == HashMode.Sha1 ? HashAlgorithmName.SHA1 : HashAlgorithmName.SHA256; var config = new SignConfigurationSet ( fileDigestAlgorithm: alg, signatureDigestAlgorithm: alg, publicCertificate: await keyVaultService.GetCertificateAsync(), signingKey: await keyVaultService.ToRSA() ); try { var tasks = files.Select(file => { telemetryLogger.OnSignFile(file, signToolName); return(Sign(file, config, keyVaultService.CertificateInfo.TimestampUrl, alg)); }); await Task.WhenAll(tasks); } finally { config.SigningKey?.Dispose(); } }
async Task <bool> RunSignTool(string file, SignConfigurationSet config, string timestampUrl, HashAlgorithmName alg) { // Append a sha256 signature using var package = OpcPackage.Open(file, OpcPackageFileMode.ReadWrite); var startTime = DateTimeOffset.UtcNow; var stopwatch = Stopwatch.StartNew(); logger.LogInformation("Signing {fileName}", file); var signBuilder = package.CreateSignatureBuilder(); signBuilder.EnqueueNamedPreset <VSIXSignatureBuilderPreset>(); var signature = signBuilder.Sign(config); var failed = false; if (timestampUrl != null) { var timestampBuilder = signature.CreateTimestampBuilder(); var result = await timestampBuilder.SignAsync(new Uri(timestampUrl), alg); if (result == TimestampResult.Failed) { failed = true; logger.LogError("Error timestamping VSIX"); } } telemetryLogger.TrackSignToolDependency(signToolName, file, startTime, stopwatch.Elapsed, null, failed ? 1 : 0); return(!failed); }
private async Task <int> PerformSignOnVsixAsync(string vsixPath, bool force, Uri timestampUri, HashAlgorithmName fileDigestAlgorithm, HashAlgorithmName timestampDigestAlgorithm, X509Certificate2 certificate, AsymmetricAlgorithm signingKey ) { using (var package = OpcPackage.Open(vsixPath, OpcPackageFileMode.ReadWrite)) { if (package.GetSignatures().Any() && !force) { _signCommandApplication.Out.WriteLine("The VSIX is already signed."); return(EXIT_CODES.FAILED); } var signBuilder = package.CreateSignatureBuilder(); signBuilder.EnqueueNamedPreset <VSIXSignatureBuilderPreset>(); var signingConfiguration = new SignConfigurationSet ( fileDigestAlgorithm: fileDigestAlgorithm, signatureDigestAlgorithm: fileDigestAlgorithm, publicCertificate: certificate, signingKey: signingKey ); var signature = signBuilder.Sign(signingConfiguration); if (timestampUri != null) { var timestampBuilder = signature.CreateTimestampBuilder(); var result = await timestampBuilder.SignAsync(timestampUri, timestampDigestAlgorithm); if (result == TimestampResult.Failed) { return(EXIT_CODES.FAILED); } } _signCommandApplication.Out.WriteLine("The signing operation is complete."); return(EXIT_CODES.SUCCESS); } }
public void ShouldSignABlobOfDataWithEcdsaP256Sha256() { var certificate = new X509Certificate2(CertPath("ecdsa-p256-sha256.pfx"), "test"); var config = new SignConfigurationSet ( publicCertificate: certificate, signatureDigestAlgorithm: HashAlgorithmName.SHA256, fileDigestAlgorithm: HashAlgorithmName.SHA256, signingKey: certificate.GetECDsaPrivateKey() ); var context = new SigningContext(config); using (var hash = SHA256.Create()) { var digest = hash.ComputeHash(new byte[] { 1, 2, 3 }); var signature = context.SignDigest(digest); Assert.Equal(OpcKnownUris.SignatureAlgorithms.ecdsaSHA256, context.XmlDSigIdentifier); Assert.Equal(SigningAlgorithm.ECDSA, context.SignatureAlgorithm); var roundtrips = context.VerifyDigest(digest, signature); Assert.True(roundtrips); } }
public void ShouldSignABlobOfDataWithRsaSha1(string pfxPath) { var certificate = new X509Certificate2(pfxPath, "test"); var config = new SignConfigurationSet ( publicCertificate: certificate, signatureDigestAlgorithm: HashAlgorithmName.SHA1, fileDigestAlgorithm: HashAlgorithmName.SHA1, signingKey: certificate.GetRSAPrivateKey() ); var context = new SigningContext(config); using (var hash = SHA1.Create()) { var digest = hash.ComputeHash(new byte[] { 1, 2, 3 }); var signature = context.SignDigest(digest); Assert.Equal(OpcKnownUris.SignatureAlgorithms.rsaSHA1, context.XmlDSigIdentifier); Assert.Equal(SigningAlgorithm.RSA, context.SignatureAlgorithm); var roundtrips = context.VerifyDigest(digest, signature); Assert.True(roundtrips); } }