-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Description
Steps to reproduce
- Inspect the code at
ILSpy/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
Lines 24 to 54 in 1370b99
static HashAlgorithm GetHashAlgorithm(this MetadataReader reader) { switch (reader.GetAssemblyDefinition().HashAlgorithm) { case AssemblyHashAlgorithm.None: // only for multi-module assemblies? return SHA1.Create(); case AssemblyHashAlgorithm.MD5: return MD5.Create(); case AssemblyHashAlgorithm.Sha1: return SHA1.Create(); case AssemblyHashAlgorithm.Sha256: return SHA256.Create(); case AssemblyHashAlgorithm.Sha384: return SHA384.Create(); case AssemblyHashAlgorithm.Sha512: return SHA512.Create(); default: return SHA1.Create(); // default? } } static string CalculatePublicKeyToken(BlobHandle blob, MetadataReader reader) { // Calculate public key token: // 1. hash the public key using the appropriate algorithm. byte[] publicKeyTokenBytes = reader.GetHashAlgorithm().ComputeHash(reader.GetBlobBytes(blob)); // 2. take the last 8 bytes // 3. according to Cecil we need to reverse them, other sources did not mention this. return publicKeyTokenBytes.TakeLast(8).Reverse().ToHexString(8); }
Error message shown
The implementation uses the assembly's hash algorithm id to choose which hash algorithm to use when hashing the public key. This is incorrect. public key tokens are always calculated using a SHA1 hash of the public key.
Details
Since SHA1 is the default, and it is pretty difficult to successfully create a non-SHA1 assembly, the current implementation almost always works.
Here's a straightforward implementation from .NET itself: https://github.com/dotnet/runtime/blob/cc5f1df48e5e39a6fa5ab94ca4664aac3cc36898/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs#L11C1-L33C10
You can see that SHA1 is always used. Recall that assembly references can capture a public key without the ability to capture a hash algorithm, so it must be calculatable without that. Also, publishers must be able to change the hash algorithm in future releases without changing an assembly's identity.