Skip to content

Commit 74424f7

Browse files
Merge pull request #330 from jevgenigeurtsen/feature/oneshot-hmac
Use HMAC one-shot methods instead of instances
2 parents 93d73f0 + a32e159 commit 74424f7

File tree

1 file changed

+28
-9
lines changed

1 file changed

+28
-9
lines changed

src/ImageSharp.Web/HMACUtilities.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ public static class HMACUtilities
1919
/// </summary>
2020
public const string TokenCommand = "hmac";
2121

22+
/// <summary>
23+
/// HMAC hash algorithms and their respective hash sizes in bytes.
24+
/// </summary>
25+
private enum HashAlgorithmSizes
26+
{
27+
HMACSHA256 = 32,
28+
HMACSHA384 = 48,
29+
HMACSHA512 = 64
30+
}
31+
2232
/// <summary>
2333
/// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA256 hash function.
2434
/// </summary>
@@ -30,8 +40,7 @@ public static class HMACUtilities
3040
/// <returns>The hashed <see cref="string"/>.</returns>
3141
public static unsafe string ComputeHMACSHA256(string value, byte[] secret)
3242
{
33-
using HMACSHA256 hmac = new(secret);
34-
return CreateHMAC(value, hmac);
43+
return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA256);
3544
}
3645

3746
/// <summary>
@@ -45,8 +54,7 @@ public static unsafe string ComputeHMACSHA256(string value, byte[] secret)
4554
/// <returns>The hashed <see cref="string"/>.</returns>
4655
public static unsafe string ComputeHMACSHA384(string value, byte[] secret)
4756
{
48-
using HMACSHA384 hmac = new(secret);
49-
return CreateHMAC(value, hmac);
57+
return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA384);
5058
}
5159

5260
/// <summary>
@@ -60,12 +68,11 @@ public static unsafe string ComputeHMACSHA384(string value, byte[] secret)
6068
/// <returns>The hashed <see cref="string"/>.</returns>
6169
public static unsafe string ComputeHMACSHA512(string value, byte[] secret)
6270
{
63-
using HMACSHA512 hmac = new(secret);
64-
return CreateHMAC(value, hmac);
71+
return CreateHMAC(value, secret, HashAlgorithmSizes.HMACSHA512);
6572
}
6673

6774
[MethodImpl(MethodImplOptions.AggressiveInlining)]
68-
private static unsafe string CreateHMAC(string value, HMAC hmac)
75+
private static unsafe string CreateHMAC(string value, ReadOnlySpan<byte> secret, HashAlgorithmSizes hashSize)
6976
{
7077
int byteCount = Encoding.ASCII.GetByteCount(value);
7178
byte[]? buffer = null;
@@ -80,8 +87,20 @@ private static unsafe string CreateHMAC(string value, HMAC hmac)
8087
Encoding.ASCII.GetBytes(value, bytes);
8188

8289
// Safe to always stackalloc here. We max out at 64 bytes.
83-
Span<byte> hash = stackalloc byte[hmac.HashSize / 8];
84-
hmac.TryComputeHash(bytes, hash, out int _);
90+
Span<byte> hash = stackalloc byte[(int)hashSize];
91+
switch (hashSize)
92+
{
93+
default:
94+
case HashAlgorithmSizes.HMACSHA256:
95+
HMACSHA256.TryHashData(secret, bytes, hash, out _);
96+
break;
97+
case HashAlgorithmSizes.HMACSHA384:
98+
HMACSHA384.TryHashData(secret, bytes, hash, out _);
99+
break;
100+
case HashAlgorithmSizes.HMACSHA512:
101+
HMACSHA512.TryHashData(secret, bytes, hash, out _);
102+
break;
103+
}
85104

86105
// Finally encode the hash to make it web safe.
87106
return HexEncoder.Encode(hash);

0 commit comments

Comments
 (0)