diff --git a/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs b/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs index e9da3214711..d567109b239 100644 --- a/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs +++ b/src/Microsoft.DotNet.SignTool/src/BatchSignUtil.cs @@ -277,7 +277,11 @@ private void VerifyAfterSign(FileSignInfo file) { if (!_signTool.VerifySignedPEFile(stream)) { - _log.LogError($"Assembly {file.FullPath} is not signed properly"); + _log.LogError($"Assembly {file.FullPath} is NOT signed properly"); + } + else + { + _log.LogMessage(MessageImportance.Low, $"Assembly {file.FullPath} is signed properly"); } } } @@ -321,9 +325,16 @@ private void VerifyAfterSign(FileSignInfo file) } } - if (!SkipZipContainerSignatureMarkerCheck && (file.IsNupkg() || file.IsVsix()) && !signedContainer) + if (!SkipZipContainerSignatureMarkerCheck) { - _log.LogError($"Container {file.FullPath} does not have signature marker."); + if ((file.IsNupkg() || file.IsVsix()) && !signedContainer) + { + _log.LogError($"Container {file.FullPath} does not have signature marker."); + } + else + { + _log.LogMessage(MessageImportance.Low, $"Container {file.FullPath} has a signature marker."); + } } } } @@ -342,6 +353,10 @@ private void VerifyStrongNameSigning() { _log.LogError($"Assembly {file.FullPath} is not strong-name signed correctly."); } + else + { + _log.LogMessage(MessageImportance.Low, $"Assembly {file.FullPath} strong-name signature is valid."); + } } } diff --git a/src/Microsoft.DotNet.SignTool/src/Configuration.cs b/src/Microsoft.DotNet.SignTool/src/Configuration.cs index f5c277be1ee..7e93cc86ffb 100644 --- a/src/Microsoft.DotNet.SignTool/src/Configuration.cs +++ b/src/Microsoft.DotNet.SignTool/src/Configuration.cs @@ -13,6 +13,7 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.Versioning; +using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Microsoft.DotNet.SignTool @@ -131,17 +132,23 @@ internal void ReadExistingContainerSigningCache() // might have changed the hash but we want to still use the same hash of the unsigned // file that originally built the cache. string stringHash = cacheRelative.Substring(0, indexOfHash); - + ImmutableArray contentHash; try { - ImmutableArray contentHash = ContentUtil.StringToHash(stringHash); + contentHash = ContentUtil.StringToHash(stringHash); } - catch { + catch + { _log.LogMessage($"Failed to parse the content hash from path '{file}' so skipping it."); continue; } - TrackFile(file, ContentUtil.StringToHash(stringHash), false); + // if the content of the file doesn't match the hash in file path than the file has changed + // which indicates that it was signed so we need to ensure we repack the binary with the signed version + string actualFileHash = ContentUtil.HashToString(ContentUtil.GetContentHash(file)); + bool forceRepack = stringHash != actualFileHash; + + TrackFile(file, contentHash, false, forceRepack); } _log.LogMessage("Done loading existing files from cache"); } @@ -193,10 +200,10 @@ internal BatchSignInput GenerateListOfFiles() return new BatchSignInput(_filesToSign.ToImmutableArray(), _zipDataMap.ToImmutableDictionary(ByteSequenceComparer.Instance), _filesToCopy.ToImmutableArray()); } - private FileSignInfo TrackFile(string fullPath, ImmutableArray contentHash, bool isNested) + private FileSignInfo TrackFile(string fullPath, ImmutableArray contentHash, bool isNested, bool forceRepack = false) { _log.LogMessage($"Tracking file '{fullPath}' isNested={isNested}"); - var fileSignInfo = ExtractSignInfo(fullPath, contentHash); + var fileSignInfo = ExtractSignInfo(fullPath, contentHash, forceRepack); var key = new SignedFileContentKey(contentHash, Path.GetFileName(fullPath)); @@ -220,10 +227,10 @@ private FileSignInfo TrackFile(string fullPath, ImmutableArray contentHash } } - _log.LogMessage($"Caching file {key.FileName}"); + _log.LogMessage(MessageImportance.Low, $"Caching file {key.FileName} {key.StringHash}"); _filesByContentKey.Add(key, fileSignInfo); - if (fileSignInfo.SignInfo.ShouldSign || fileSignInfo.IsZipContainer()) + if (fileSignInfo.SignInfo.ShouldSign || fileSignInfo.ForceRepack || fileSignInfo.IsZipContainer()) { _filesToSign.Add(fileSignInfo); } @@ -231,7 +238,7 @@ private FileSignInfo TrackFile(string fullPath, ImmutableArray contentHash return fileSignInfo; } - private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash) + private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash, bool forceRepack = false) { // Try to determine default certificate name by the extension of the file var hasSignInfo = _fileExtensionSignInfo.TryGetValue(Path.GetExtension(fullPath), out var signInfo); @@ -286,8 +293,8 @@ private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash) // If has overriding info, is it for ignoring the file? if (SignToolConstants.IgnoreFileCertificateSentinel.Equals(explicitCertificateName, StringComparison.OrdinalIgnoreCase)) { - _log.LogMessage($"File configurated to not be signed: {fileName}{fileSpec}"); - return new FileSignInfo(fullPath, hash, SignInfo.Ignore); + _log.LogMessage($"File configured to not be signed: {fileName}{fileSpec}"); + return new FileSignInfo(fullPath, hash, SignInfo.Ignore, forceRepack:forceRepack); } // Do we have an explicit certificate after all? @@ -301,7 +308,7 @@ private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash) { if (isAlreadySigned && !_dualCertificates.Contains(signInfo.Certificate)) { - return new FileSignInfo(fullPath, hash, SignInfo.AlreadySigned); + return new FileSignInfo(fullPath, hash, SignInfo.AlreadySigned, forceRepack:forceRepack); } // TODO: implement this check for native PE files as well: @@ -323,7 +330,7 @@ private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash) } } - return new FileSignInfo(fullPath, hash, signInfo, (peInfo != null && peInfo.TargetFramework != "") ? peInfo.TargetFramework : null); + return new FileSignInfo(fullPath, hash, signInfo, (peInfo != null && peInfo.TargetFramework != "") ? peInfo.TargetFramework : null, forceRepack:forceRepack); } if (SignToolConstants.SignableExtensions.Contains(extension) || SignToolConstants.SignableOSXExtensions.Contains(extension)) @@ -339,7 +346,7 @@ private FileSignInfo ExtractSignInfo(string fullPath, ImmutableArray hash) _log.LogMessage($"Ignoring non-signable file: {fullPath}"); } - return new FileSignInfo(fullPath, hash, SignInfo.Ignore); + return new FileSignInfo(fullPath, hash, SignInfo.Ignore, forceRepack: forceRepack); } private void LogWarning(SigningToolErrorCode code, string message) @@ -519,7 +526,7 @@ private bool TryBuildZipData(FileSignInfo zipFileSignInfo, out ZipData zipData) fileSignInfo = TrackFile(tempPath, contentHash, isNested: true); } - if (fileSignInfo.SignInfo.ShouldSign) + if (fileSignInfo.SignInfo.ShouldSign || fileSignInfo.ForceRepack) { nestedParts.Add(new ZipPart(relativePath, fileSignInfo)); } diff --git a/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs b/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs index 45d89e4e9f0..60f27e41e2d 100644 --- a/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs +++ b/src/Microsoft.DotNet.SignTool/src/FileSignInfo.cs @@ -20,6 +20,8 @@ internal readonly struct FileSignInfo // optional file information that allows to disambiguate among multiple files with the same name: internal readonly string TargetFramework; + internal readonly bool ForceRepack; + internal static bool IsPEFile(string path) => Path.GetExtension(path) == ".exe" || Path.GetExtension(path) == ".dll"; @@ -64,7 +66,7 @@ internal static bool IsZipContainer(string path) internal bool IsPowerShellScript() => IsPowerShellScript(FileName); - internal FileSignInfo(string fullPath, ImmutableArray contentHash, SignInfo signInfo, string targetFramework = null) + internal FileSignInfo(string fullPath, ImmutableArray contentHash, SignInfo signInfo, string targetFramework = null, bool forceRepack = false) { Debug.Assert(fullPath != null); Debug.Assert(!contentHash.IsDefault && contentHash.Length == 256 / 8); @@ -75,6 +77,7 @@ internal FileSignInfo(string fullPath, ImmutableArray contentHash, SignInf FullPath = fullPath; SignInfo = signInfo; TargetFramework = targetFramework; + ForceRepack = forceRepack; } public override string ToString()