From a32e159bdbeba2fb153314c4d9da9c6499ebf8c2 Mon Sep 17 00:00:00 2001 From: Jevgeni Geurtsen Date: Fri, 23 Jun 2023 15:12:45 +0200 Subject: [PATCH] Use HMAC one-shot methods instead of instances --- src/ImageSharp.Web/HMACUtilities.cs | 37 ++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp.Web/HMACUtilities.cs b/src/ImageSharp.Web/HMACUtilities.cs index ee128aff..e0834780 100644 --- a/src/ImageSharp.Web/HMACUtilities.cs +++ b/src/ImageSharp.Web/HMACUtilities.cs @@ -19,6 +19,16 @@ public static class HMACUtilities /// public const string TokenCommand = "hmac"; + /// + /// HMAC hash algorithms and their respective hash sizes in bytes. + /// + private enum HashAlgorithmSizes + { + HMACSHA256 = 32, + HMACSHA384 = 48, + HMACSHA512 = 64 + } + /// /// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA256 hash function. /// @@ -30,8 +40,7 @@ public static class HMACUtilities /// The hashed . public static unsafe string ComputeHMACSHA256(string value, byte[] secret) { - using HMACSHA256 hmac = new(secret); - return CreateHMAC(value, hmac); + return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA256); } /// @@ -45,8 +54,7 @@ public static unsafe string ComputeHMACSHA256(string value, byte[] secret) /// The hashed . public static unsafe string ComputeHMACSHA384(string value, byte[] secret) { - using HMACSHA384 hmac = new(secret); - return CreateHMAC(value, hmac); + return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA384); } /// @@ -60,12 +68,11 @@ public static unsafe string ComputeHMACSHA384(string value, byte[] secret) /// The hashed . public static unsafe string ComputeHMACSHA512(string value, byte[] secret) { - using HMACSHA512 hmac = new(secret); - return CreateHMAC(value, hmac); + return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA512); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe string CreateHMAC(string value, HMAC hmac) + private static unsafe string CreateHMAC(string value, ReadOnlySpan secret, HashAlgorithmSizes hashSize) { int byteCount = Encoding.ASCII.GetByteCount(value); byte[]? buffer = null; @@ -80,8 +87,20 @@ private static unsafe string CreateHMAC(string value, HMAC hmac) Encoding.ASCII.GetBytes(value, bytes); // Safe to always stackalloc here. We max out at 64 bytes. - Span hash = stackalloc byte[hmac.HashSize / 8]; - hmac.TryComputeHash(bytes, hash, out int _); + Span hash = stackalloc byte[(int)hashSize]; + switch (hashSize) + { + default: + case HashAlgorithmSizes.HMACSHA256: + HMACSHA256.TryHashData(secret, bytes, hash, out _); + break; + case HashAlgorithmSizes.HMACSHA384: + HMACSHA384.TryHashData(secret, bytes, hash, out _); + break; + case HashAlgorithmSizes.HMACSHA512: + HMACSHA512.TryHashData(secret, bytes, hash, out _); + break; + } // Finally encode the hash to make it web safe. return HexEncoder.Encode(hash);