| File: src\runtime\src\libraries\Common\src\System\Security\IdentityHelper.cs | Web Access |
| Project: System.IO.IsolatedStorage.csproj (System.IO.IsolatedStorage) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.IO; using System.Reflection; using System.Security.Cryptography; using System.Text; namespace System.Security { /// <summary> /// Helper class for getting identity hashes for types that used /// to live in Assembly Evidence. /// </summary> internal static class IdentityHelper { /// <summary> /// Gives a hash equivalent to what Url.Normalize() gives. /// </summary> internal static string GetNormalizedUriHash(Uri uri) { // On .NET Framework System.Security.Url is used as evidence, it has an internal Normalize() method. // Uri.ToString() appears to be functionally equivalent. return GetStrongHashSuitableForObjectName(uri.ToString()); } /// <summary> /// Uses the AssemblyName's public key to generate a hash equivalent to what /// StrongName.Normalize() gives. /// </summary> internal static string? GetNormalizedStrongNameHash(AssemblyName name) { byte[]? publicKey = name.GetPublicKey(); // If we don't have a key, we're not strong named if (publicKey == null || publicKey.Length == 0) return null; // Emulate what we get from StrongName.Normalize(). using (MemoryStream ms = new MemoryStream()) using (BinaryWriter bw = new BinaryWriter(ms)) { bw.Write(publicKey); bw.Write(name.Version!.Major); bw.Write(name.Name!); ms.Position = 0; return GetStrongHashSuitableForObjectName(ms); } } internal static string GetStrongHashSuitableForObjectName(string name) { using (MemoryStream ms = new MemoryStream()) using (BinaryWriter b = new BinaryWriter(ms)) { b.Write(name.ToUpperInvariant()); ms.Position = 0; return GetStrongHashSuitableForObjectName(ms); } } [Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "Compat: Used to generate an 8.3 filename.")] internal static string GetStrongHashSuitableForObjectName(Stream stream) { using (SHA1 sha1 = SHA1.Create()) { return ToBase32StringSuitableForDirName(sha1.ComputeHash(stream)); } } // This is from the .NET Framework Path class. The implementation in the runtime libraries was optimized for internal Path usage so // we can't share the implementation. internal static string ToBase32StringSuitableForDirName(byte[] buff) { // This routine is optimised to be used with buffs of length 20 Debug.Assert(((buff.Length % 5) == 0), "Unexpected hash length"); StringBuilder sb = new StringBuilder(); int l, i; l = buff.Length; i = 0; // Create l chars using the last 5 bits of each byte. // Consume 3 MSB bits 5 bytes at a time. ReadOnlySpan<byte> base32Chars = "abcdefghijklmnopqrstuvwxyz012345"u8; do { byte b0 = (i < l) ? buff[i++] : (byte)0; byte b1 = (i < l) ? buff[i++] : (byte)0; byte b2 = (i < l) ? buff[i++] : (byte)0; byte b3 = (i < l) ? buff[i++] : (byte)0; byte b4 = (i < l) ? buff[i++] : (byte)0; // Consume the 5 Least significant bits of each byte sb.Append((char)base32Chars[b0 & 0x1F]); sb.Append((char)base32Chars[b1 & 0x1F]); sb.Append((char)base32Chars[b2 & 0x1F]); sb.Append((char)base32Chars[b3 & 0x1F]); sb.Append((char)base32Chars[b4 & 0x1F]); // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 sb.Append((char)base32Chars[( ((b0 & 0xE0) >> 5) | ((b3 & 0x60) >> 2))]); sb.Append((char)base32Chars[( ((b1 & 0xE0) >> 5) | ((b4 & 0x60) >> 2))]); // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4 b2 >>= 5; Debug.Assert(((b2 & 0xF8) == 0), "Unexpected set bits"); if ((b3 & 0x80) != 0) b2 |= 0x08; if ((b4 & 0x80) != 0) b2 |= 0x10; sb.Append((char)base32Chars[b2]); } while (i < l); return sb.ToString(); } } }