From 6c6d2362aacf80a6d20d8c08b1412e3803d2e070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Bj=C3=B6rkstr=C3=B6m?= Date: Fri, 21 Oct 2016 23:11:00 +0300 Subject: [PATCH] (GH-685) Adds support for SHA-256 code signing and timestamps in SignTool --- .../Tools/SignTool/SignToolSignRunnerTests.cs | 43 +++++++++++++++++++ .../Tools/SignTool/SignToolDigestAlgorithm.cs | 18 ++++++++ .../Tools/SignTool/SignToolSignRunner.cs | 28 +++++++++++- .../Tools/SignTool/SignToolSignSettings.cs | 15 +++++++ 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/Cake.Common/Tools/SignTool/SignToolDigestAlgorithm.cs diff --git a/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs b/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs index 83388bbcb7..418365321a 100644 --- a/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs +++ b/src/Cake.Common.Tests/Unit/Tools/SignTool/SignToolSignRunnerTests.cs @@ -4,6 +4,7 @@ using System; using Cake.Common.Tests.Fixtures.Tools; +using Cake.Common.Tools.SignTool; using Cake.Core; using Cake.Testing; using Xunit; @@ -279,6 +280,48 @@ public void Should_Call_Sign_Tool_With_Correct_Parameters_With_Thumbprint() // Then Assert.Equal("SIGN /t \"https://t.com/\" /sha1 \"ThumbprintTest\" \"/Working/a.dll\"", result.Args); } + + [Fact] + public void Should_Call_Sign_Tool_With_Correct_Parameters_With_Sha256_Digest_Algorithm() + { + // Given + var fixture = new SignToolSignRunnerFixture(); + fixture.Settings.DigestAlgorithm = SignToolDigestAlgorithm.Sha256; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("SIGN /fd sha256 /t \"https://t.com/\" /f \"/Working/cert.pfx\" /p secret \"/Working/a.dll\"", result.Args); + } + + [Fact] + public void Should_Call_Sign_Tool_With_Correct_Parameters_With_RFC6131_Timestamp_Uri_And_Sha256_Timestamp_Algorithm() + { + // Given + var fixture = new SignToolSignRunnerFixture(); + fixture.Settings.TimeStampDigestAlgorithm = SignToolDigestAlgorithm.Sha256; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("SIGN /tr \"https://t.com/\" /td sha256 /f \"/Working/cert.pfx\" /p secret \"/Working/a.dll\"", result.Args); + } + + [Fact] + public void Should_Call_Sign_Tool_With_Correct_Parameters_With_Append_Signature() + { + // Given + var fixture = new SignToolSignRunnerFixture(); + fixture.Settings.AppendSignature = true; + + // When + var result = fixture.Run(); + + // Then + Assert.Equal("SIGN /t \"https://t.com/\" /f \"/Working/cert.pfx\" /p secret /as \"/Working/a.dll\"", result.Args); + } } } } \ No newline at end of file diff --git a/src/Cake.Common/Tools/SignTool/SignToolDigestAlgorithm.cs b/src/Cake.Common/Tools/SignTool/SignToolDigestAlgorithm.cs new file mode 100644 index 0000000000..e9cf9a78b4 --- /dev/null +++ b/src/Cake.Common/Tools/SignTool/SignToolDigestAlgorithm.cs @@ -0,0 +1,18 @@ +namespace Cake.Common.Tools.SignTool +{ + /// + /// Digest algorithm for SignTool + /// + public enum SignToolDigestAlgorithm + { + /// + /// SHA-1 digest algorithm + /// + Sha1, + + /// + /// SHA-256 digest algorithm. + /// + Sha256 + } +} diff --git a/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs b/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs index 3d8fd76bb3..78702e2b5c 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolSignRunner.cs @@ -104,9 +104,27 @@ private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, SignToolSignS // SIGN Command. builder.Append("SIGN"); + // SHA-256. + if (settings.DigestAlgorithm == SignToolDigestAlgorithm.Sha256) + { + builder.Append("/fd sha256"); + } + // TimeStamp server. - builder.Append("/t"); - builder.AppendQuoted(settings.TimeStampUri.AbsoluteUri); + if (settings.TimeStampDigestAlgorithm == SignToolDigestAlgorithm.Sha256) + { + // If Sha256 use RFC 3161 timestamp server. + builder.Append("/tr"); + builder.AppendQuoted(settings.TimeStampUri.AbsoluteUri); + + builder.Append("/td sha256"); + } + else + { + // Otherwise use SHA-1 Authenticode timestamp server + builder.Append("/t"); + builder.AppendQuoted(settings.TimeStampUri.AbsoluteUri); + } if (settings.CertPath == null && string.IsNullOrEmpty(settings.CertThumbprint)) { @@ -180,6 +198,12 @@ private ProcessArgumentBuilder GetArguments(FilePath assemblyPath, SignToolSignS builder.AppendQuoted(settings.DescriptionUri.AbsoluteUri); } + // Append signature. + if (settings.AppendSignature) + { + builder.Append("/as"); + } + // Target Assembly to sign. builder.AppendQuoted(assemblyPath.MakeAbsolute(_environment).FullPath); diff --git a/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs b/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs index 6ed2a0347a..af43c9009c 100644 --- a/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs +++ b/src/Cake.Common/Tools/SignTool/SignToolSignSettings.cs @@ -42,5 +42,20 @@ public sealed class SignToolSignSettings : ToolSettings /// Gets or sets the signed content's expanded description URL. /// public Uri DescriptionUri { get; set; } + + /// + /// Gets or sets the file digest algorithm + /// + public SignToolDigestAlgorithm DigestAlgorithm { get; set; } + + /// + /// Gets or sets the timestamp digest algorithm + /// + public SignToolDigestAlgorithm TimeStampDigestAlgorithm { get; set; } + + /// + /// Gets or sets a value indicating whether the signature should be appended + /// + public bool AppendSignature { get; set; } } } \ No newline at end of file