Skip to content

Commit 919be00

Browse files
authored
Improve usage of hashing for trimmer friendliness
* Avoid rooting hash types for PBKDF2 key adjustment * Rewrite HashOneShotHelpers in terms of HashProviderDispenser.
1 parent c8e4f1e commit 919be00

File tree

2 files changed

+120
-57
lines changed

2 files changed

+120
-57
lines changed

src/libraries/Common/src/System/Security/Cryptography/HashOneShotHelpers.cs

+113-45
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using Internal.Cryptography;
5+
using System.Diagnostics;
56
using System.IO;
67

78
namespace System.Security.Cryptography
@@ -12,18 +13,11 @@ internal static class HashOneShotHelpers
1213
{
1314
internal static byte[] HashData(HashAlgorithmName hashAlgorithm, ReadOnlySpan<byte> source)
1415
{
15-
return hashAlgorithm.Name switch
16-
{
17-
HashAlgorithmNames.SHA256 => SHA256.HashData(source),
18-
HashAlgorithmNames.SHA1 => SHA1.HashData(source),
19-
HashAlgorithmNames.SHA512 => SHA512.HashData(source),
20-
HashAlgorithmNames.SHA384 => SHA384.HashData(source),
21-
HashAlgorithmNames.SHA3_256 => SHA3_256.HashData(source),
22-
HashAlgorithmNames.SHA3_384 => SHA3_384.HashData(source),
23-
HashAlgorithmNames.SHA3_512 => SHA3_512.HashData(source),
24-
HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.HashData(source),
25-
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)),
26-
};
16+
int hashSizeInBytes = HashSize(hashAlgorithm);
17+
byte[] result = new byte[hashSizeInBytes];
18+
int written = HashProviderDispenser.OneShotHashProvider.HashData(hashAlgorithm.Name!, source, result);
19+
Debug.Assert(written == hashSizeInBytes);
20+
return result;
2721
}
2822

2923
internal static bool TryHashData(
@@ -32,34 +26,30 @@ internal static bool TryHashData(
3226
Span<byte> destination,
3327
out int bytesWritten)
3428
{
35-
return hashAlgorithm.Name switch
29+
int hashSizeInBytes = HashSize(hashAlgorithm);
30+
31+
if (destination.Length < hashSizeInBytes)
3632
{
37-
HashAlgorithmNames.SHA256 => SHA256.TryHashData(source, destination, out bytesWritten),
38-
HashAlgorithmNames.SHA1 => SHA1.TryHashData(source, destination, out bytesWritten),
39-
HashAlgorithmNames.SHA512 => SHA512.TryHashData(source, destination, out bytesWritten),
40-
HashAlgorithmNames.SHA384 => SHA384.TryHashData(source, destination, out bytesWritten),
41-
HashAlgorithmNames.SHA3_256 => SHA3_256.TryHashData(source, destination, out bytesWritten),
42-
HashAlgorithmNames.SHA3_384 => SHA3_384.TryHashData(source, destination, out bytesWritten),
43-
HashAlgorithmNames.SHA3_512 => SHA3_512.TryHashData(source, destination, out bytesWritten),
44-
HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.TryHashData(source, destination, out bytesWritten),
45-
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)),
46-
};
33+
bytesWritten = 0;
34+
return false;
35+
}
36+
37+
bytesWritten = HashProviderDispenser.OneShotHashProvider.HashData(hashAlgorithm.Name!, source, destination);
38+
Debug.Assert(bytesWritten == hashSizeInBytes);
39+
return true;
4740
}
4841

4942
internal static byte[] HashData(HashAlgorithmName hashAlgorithm, Stream source)
5043
{
51-
return hashAlgorithm.Name switch
44+
ArgumentNullException.ThrowIfNull(source);
45+
46+
if (!source.CanRead)
5247
{
53-
HashAlgorithmNames.SHA256 => SHA256.HashData(source),
54-
HashAlgorithmNames.SHA1 => SHA1.HashData(source),
55-
HashAlgorithmNames.SHA512 => SHA512.HashData(source),
56-
HashAlgorithmNames.SHA384 => SHA384.HashData(source),
57-
HashAlgorithmNames.SHA3_256 => SHA3_256.HashData(source),
58-
HashAlgorithmNames.SHA3_384 => SHA3_384.HashData(source),
59-
HashAlgorithmNames.SHA3_512 => SHA3_512.HashData(source),
60-
HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.HashData(source),
61-
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)),
62-
};
48+
throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source));
49+
}
50+
51+
int hashSizeInBytes = HashSize(hashAlgorithm);
52+
return LiteHashProvider.HashStream(hashAlgorithm.Name!, hashSizeInBytes, source);
6353
}
6454

6555
internal static int MacData(
@@ -68,18 +58,96 @@ internal static int MacData(
6858
ReadOnlySpan<byte> source,
6959
Span<byte> destination)
7060
{
71-
return hashAlgorithm.Name switch
61+
int macSizeInBytes = MacSize(hashAlgorithm);
62+
63+
if (destination.Length < macSizeInBytes)
64+
{
65+
throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination));
66+
}
67+
68+
int written = HashProviderDispenser.OneShotHashProvider.MacData(hashAlgorithm.Name!, key, source, destination);
69+
Debug.Assert(written == macSizeInBytes);
70+
return written;
71+
}
72+
73+
private static int HashSize(HashAlgorithmName hashAlgorithm)
74+
{
75+
switch (hashAlgorithm.Name)
7276
{
73-
HashAlgorithmNames.SHA256 => HMACSHA256.HashData(key, source, destination),
74-
HashAlgorithmNames.SHA1 => HMACSHA1.HashData(key, source, destination),
75-
HashAlgorithmNames.SHA512 => HMACSHA512.HashData(key, source, destination),
76-
HashAlgorithmNames.SHA384 => HMACSHA384.HashData(key, source, destination),
77-
HashAlgorithmNames.SHA3_256 => HMACSHA3_256.HashData(key, source, destination),
78-
HashAlgorithmNames.SHA3_384 => HMACSHA3_384.HashData(key, source, destination),
79-
HashAlgorithmNames.SHA3_512 => HMACSHA3_512.HashData(key, source, destination),
80-
HashAlgorithmNames.MD5 when Helpers.HasMD5 => HMACMD5.HashData(key, source, destination),
81-
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)),
82-
};
77+
case HashAlgorithmNames.SHA256:
78+
return SHA256.HashSizeInBytes;
79+
case HashAlgorithmNames.SHA1:
80+
return SHA1.HashSizeInBytes;
81+
case HashAlgorithmNames.SHA512:
82+
return SHA512.HashSizeInBytes;
83+
case HashAlgorithmNames.SHA384:
84+
return SHA384.HashSizeInBytes;
85+
case HashAlgorithmNames.SHA3_256:
86+
if (!HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_256))
87+
{
88+
throw new PlatformNotSupportedException();
89+
}
90+
91+
return SHA3_256.HashSizeInBytes;
92+
case HashAlgorithmNames.SHA3_384:
93+
if (!HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_384))
94+
{
95+
throw new PlatformNotSupportedException();
96+
}
97+
98+
return SHA3_384.HashSizeInBytes;
99+
case HashAlgorithmNames.SHA3_512:
100+
if (!HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_512))
101+
{
102+
throw new PlatformNotSupportedException();
103+
}
104+
105+
return SHA3_512.HashSizeInBytes;
106+
case HashAlgorithmNames.MD5 when Helpers.HasMD5:
107+
return MD5.HashSizeInBytes;
108+
default:
109+
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name));
110+
}
111+
}
112+
113+
private static int MacSize(HashAlgorithmName hashAlgorithm)
114+
{
115+
switch (hashAlgorithm.Name)
116+
{
117+
case HashAlgorithmNames.SHA256:
118+
return HMACSHA256.HashSizeInBytes;
119+
case HashAlgorithmNames.SHA1:
120+
return HMACSHA1.HashSizeInBytes;
121+
case HashAlgorithmNames.SHA512:
122+
return HMACSHA512.HashSizeInBytes;
123+
case HashAlgorithmNames.SHA384:
124+
return HMACSHA384.HashSizeInBytes;
125+
case HashAlgorithmNames.SHA3_256:
126+
if (!HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_256))
127+
{
128+
throw new PlatformNotSupportedException();
129+
}
130+
131+
return HMACSHA3_256.HashSizeInBytes;
132+
case HashAlgorithmNames.SHA3_384:
133+
if (!HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_384))
134+
{
135+
throw new PlatformNotSupportedException();
136+
}
137+
138+
return HMACSHA3_384.HashSizeInBytes;
139+
case HashAlgorithmNames.SHA3_512:
140+
if (!HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_512))
141+
{
142+
throw new PlatformNotSupportedException();
143+
}
144+
145+
return HMACSHA3_512.HashSizeInBytes;
146+
case HashAlgorithmNames.MD5 when Helpers.HasMD5:
147+
return HMACMD5.HashSizeInBytes;
148+
default:
149+
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name));
150+
}
83151
}
84152
}
85153
}

src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Windows.cs

+7-12
Original file line numberDiff line numberDiff line change
@@ -86,25 +86,20 @@ private static unsafe void FillKeyDerivation(
8686
switch (hashAlgorithmName)
8787
{
8888
case HashAlgorithmNames.SHA1:
89-
hashBufferSize = SHA1.HashData(password, hashBuffer);
90-
break;
9189
case HashAlgorithmNames.SHA256:
92-
hashBufferSize = SHA256.HashData(password, hashBuffer);
93-
break;
9490
case HashAlgorithmNames.SHA384:
95-
hashBufferSize = SHA384.HashData(password, hashBuffer);
96-
break;
9791
case HashAlgorithmNames.SHA512:
98-
hashBufferSize = SHA512.HashData(password, hashBuffer);
92+
hashBufferSize = HashProviderDispenser.OneShotHashProvider.HashData(hashAlgorithmName, password, hashBuffer);
9993
break;
10094
case HashAlgorithmNames.SHA3_256:
101-
hashBufferSize = SHA3_256.HashData(password, hashBuffer);
102-
break;
10395
case HashAlgorithmNames.SHA3_384:
104-
hashBufferSize = SHA3_384.HashData(password, hashBuffer);
105-
break;
10696
case HashAlgorithmNames.SHA3_512:
107-
hashBufferSize = SHA3_512.HashData(password, hashBuffer);
97+
if (!HashProviderDispenser.HashSupported(hashAlgorithmName))
98+
{
99+
throw new PlatformNotSupportedException();
100+
}
101+
102+
hashBufferSize = HashProviderDispenser.OneShotHashProvider.HashData(hashAlgorithmName, password, hashBuffer);
108103
break;
109104
default:
110105
Debug.Fail($"Unexpected hash algorithm '{hashAlgorithmName}'");

0 commit comments

Comments
 (0)