@@ -19,6 +19,16 @@ public static class HMACUtilities
19
19
/// </summary>
20
20
public const string TokenCommand = "hmac" ;
21
21
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
+
22
32
/// <summary>
23
33
/// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA256 hash function.
24
34
/// </summary>
@@ -30,8 +40,7 @@ public static class HMACUtilities
30
40
/// <returns>The hashed <see cref="string"/>.</returns>
31
41
public static unsafe string ComputeHMACSHA256 ( string value , byte [ ] secret )
32
42
{
33
- using HMACSHA256 hmac = new ( secret ) ;
34
- return CreateHMAC ( value , hmac ) ;
43
+ return CreateHMAC ( value , secret , HashAlgorithmSizes . HMACSHA256 ) ;
35
44
}
36
45
37
46
/// <summary>
@@ -45,8 +54,7 @@ public static unsafe string ComputeHMACSHA256(string value, byte[] secret)
45
54
/// <returns>The hashed <see cref="string"/>.</returns>
46
55
public static unsafe string ComputeHMACSHA384 ( string value , byte [ ] secret )
47
56
{
48
- using HMACSHA384 hmac = new ( secret ) ;
49
- return CreateHMAC ( value , hmac ) ;
57
+ return CreateHMAC ( value , secret , HashAlgorithmSizes . HMACSHA384 ) ;
50
58
}
51
59
52
60
/// <summary>
@@ -60,12 +68,11 @@ public static unsafe string ComputeHMACSHA384(string value, byte[] secret)
60
68
/// <returns>The hashed <see cref="string"/>.</returns>
61
69
public static unsafe string ComputeHMACSHA512 ( string value , byte [ ] secret )
62
70
{
63
- using HMACSHA512 hmac = new ( secret ) ;
64
- return CreateHMAC ( value , hmac ) ;
71
+ return CreateHMAC ( value , secret , HashAlgorithmSizes . HMACSHA512 ) ;
65
72
}
66
73
67
74
[ 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 )
69
76
{
70
77
int byteCount = Encoding . ASCII . GetByteCount ( value ) ;
71
78
byte [ ] ? buffer = null ;
@@ -80,8 +87,20 @@ private static unsafe string CreateHMAC(string value, HMAC hmac)
80
87
Encoding . ASCII . GetBytes ( value , bytes ) ;
81
88
82
89
// 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
+ }
85
104
86
105
// Finally encode the hash to make it web safe.
87
106
return HexEncoder . Encode ( hash ) ;
0 commit comments