Clean up some usage of SHA1 and SHA256 in the code base (#24696)
* AntiForgery: Use SHA256 one-shot * AuthN: Use SHA256 one-shot APIs * MVC/Razor: Cleanup SHA256 references * WebSockets: Use SHA1 one-shots * dotnet-openapi: Use preferred SHA256 factory * SignalR: Prefer RNG.Fill over RNG.GetBytes
This commit is contained in:
parent
adea6638cc
commit
bbf7c8780c
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.DataProtection;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
|
|
@ -35,12 +35,8 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
private static string ComputeCookieName(string applicationId)
|
||||
{
|
||||
using (var sha256 = CryptographyAlgorithms.CreateSHA256())
|
||||
{
|
||||
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(applicationId));
|
||||
var subHash = hash.Take(8).ToArray();
|
||||
return WebEncoders.Base64UrlEncode(subHash);
|
||||
}
|
||||
byte[] fullHash = SHA256.HashData(Encoding.UTF8.GetBytes(applicationId));
|
||||
return WebEncoders.Base64UrlEncode(fullHash, 0, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
private MemoryStream? _stream;
|
||||
private BinaryReader? _reader;
|
||||
private BinaryWriter? _writer;
|
||||
private SHA256? _sha256;
|
||||
|
||||
public MemoryStream Stream
|
||||
{
|
||||
|
|
@ -82,23 +81,6 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
}
|
||||
}
|
||||
|
||||
public SHA256 Sha256
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sha256 == null)
|
||||
{
|
||||
_sha256 = CryptographyAlgorithms.CreateSHA256();
|
||||
}
|
||||
|
||||
return _sha256;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_sha256 = value;
|
||||
}
|
||||
}
|
||||
|
||||
public char[] GetChars(int count)
|
||||
{
|
||||
if (_chars == null || _chars.Length < count)
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery
|
||||
{
|
||||
internal static class CryptographyAlgorithms
|
||||
{
|
||||
public static SHA256 CreateSHA256()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SHA256.Create();
|
||||
}
|
||||
// SHA256.Create is documented to throw this exception on FIPS compliant machines.
|
||||
// See: https://msdn.microsoft.com/en-us/library/z08hz7ad%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
|
||||
catch (System.Reflection.TargetInvocationException)
|
||||
{
|
||||
// Fallback to a FIPS compliant SHA256 algorithm.
|
||||
return new SHA256CryptoServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace Microsoft.AspNetCore.Antiforgery
|
||||
|
|
@ -134,9 +135,13 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
|
||||
writer.Flush();
|
||||
|
||||
var sha256 = serializationContext.Sha256;
|
||||
var stream = serializationContext.Stream;
|
||||
var bytes = sha256.ComputeHash(stream.ToArray(), 0, checked((int)stream.Length));
|
||||
bool success = serializationContext.Stream.TryGetBuffer(out ArraySegment<byte> buffer);
|
||||
if (!success)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
var bytes = SHA256.HashData(buffer);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,23 +110,20 @@ namespace Microsoft.AspNetCore.WebSockets
|
|||
// this concatenated value to obtain a 20-byte value and base64-encoding"
|
||||
// https://tools.ietf.org/html/rfc6455#section-4.2.2
|
||||
|
||||
using (var algorithm = SHA1.Create())
|
||||
// requestKey is already verified to be small (24 bytes) by 'IsRequestKeyValid()' and everything is 1:1 mapping to UTF8 bytes
|
||||
// so this can be hardcoded to 60 bytes for the requestKey + static websocket string
|
||||
Span<byte> mergedBytes = stackalloc byte[60];
|
||||
Encoding.UTF8.GetBytes(requestKey, mergedBytes);
|
||||
EncodedWebSocketKey.CopyTo(mergedBytes.Slice(24));
|
||||
|
||||
Span<byte> hashedBytes = stackalloc byte[20];
|
||||
var written = SHA1.HashData(mergedBytes, hashedBytes);
|
||||
if (written != 20)
|
||||
{
|
||||
// requestKey is already verified to be small (24 bytes) by 'IsRequestKeyValid()' and everything is 1:1 mapping to UTF8 bytes
|
||||
// so this can be hardcoded to 60 bytes for the requestKey + static websocket string
|
||||
Span<byte> mergedBytes = stackalloc byte[60];
|
||||
Encoding.UTF8.GetBytes(requestKey, mergedBytes);
|
||||
EncodedWebSocketKey.CopyTo(mergedBytes.Slice(24));
|
||||
|
||||
Span<byte> hashedBytes = stackalloc byte[20];
|
||||
var success = algorithm.TryComputeHash(mergedBytes, hashedBytes, out var written);
|
||||
if (!success || written != 20)
|
||||
{
|
||||
throw new InvalidOperationException("Could not compute the hash for the 'Sec-WebSocket-Accept' header.");
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(hashedBytes);
|
||||
throw new InvalidOperationException("Could not compute the hash for the 'Sec-WebSocket-Accept' header.");
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(hashedBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
|
||||
{
|
||||
internal static class CryptographyAlgorithms
|
||||
{
|
||||
public static SHA256 CreateSHA256()
|
||||
{
|
||||
try
|
||||
{
|
||||
return SHA256.Create();
|
||||
}
|
||||
// SHA256.Create is documented to throw this exception on FIPS compliant machines.
|
||||
// See: https://msdn.microsoft.com/en-us/library/z08hz7ad%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
|
||||
catch (System.Reflection.TargetInvocationException)
|
||||
{
|
||||
// Fallback to a FIPS compliant SHA256 algorithm.
|
||||
return new SHA256CryptoServiceProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
|
@ -97,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
|
|||
|
||||
private static string GetHashForFile(IFileInfo fileInfo)
|
||||
{
|
||||
using (var sha256 = CryptographyAlgorithms.CreateSHA256())
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
using (var readStream = fileInfo.CreateReadStream())
|
||||
{
|
||||
|
|
@ -107,4 +108,4 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Infrastructure
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Infrastructure;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
||||
|
|
@ -180,12 +179,9 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache
|
|||
// The key is typically too long to be useful, so we use a cryptographic hash
|
||||
// as the actual key (better randomization and key distribution, so small vary
|
||||
// values will generate dramatically different keys).
|
||||
using (var sha256 = CryptographyAlgorithms.CreateSHA256())
|
||||
{
|
||||
var contentBytes = Encoding.UTF8.GetBytes(key);
|
||||
var hashedBytes = sha256.ComputeHash(contentBytes);
|
||||
return Convert.ToBase64String(hashedBytes);
|
||||
}
|
||||
var contentBytes = Encoding.UTF8.GetBytes(key);
|
||||
var hashedBytes = SHA256.HashData(contentBytes);
|
||||
return Convert.ToBase64String(hashedBytes);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
|
|||
|
|
@ -68,8 +68,7 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
|
|||
// Store this for use during the code redemption.
|
||||
properties.Items.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var challengeBytes = SHA256.HashData(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var codeChallenge = WebEncoders.Base64UrlEncode(challengeBytes);
|
||||
|
||||
queryStrings[OAuthConstants.CodeChallengeKey] = codeChallenge;
|
||||
|
|
|
|||
|
|
@ -280,8 +280,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
// Store this for use during the code redemption.
|
||||
properties.Items.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var challengeBytes = SHA256.HashData(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var codeChallenge = WebEncoders.Base64UrlEncode(challengeBytes);
|
||||
|
||||
parameters[OAuthConstants.CodeChallengeKey] = codeChallenge;
|
||||
|
|
|
|||
|
|
@ -375,8 +375,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
// Store this for use during the code redemption. See RunAuthorizationCodeReceivedEventAsync.
|
||||
properties.Items.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
|
||||
|
||||
using var sha256 = SHA256.Create();
|
||||
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var challengeBytes = SHA256.HashData(Encoding.UTF8.GetBytes(codeVerifier));
|
||||
var codeChallenge = WebEncoders.Base64UrlEncode(challengeBytes);
|
||||
|
||||
message.Parameters.Add(OAuthConstants.CodeChallengeKey, codeChallenge);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
|||
// TODO: Consider making this configurable? At least for testing?
|
||||
private static readonly TimeSpan _heartbeatTickRate = TimeSpan.FromSeconds(1);
|
||||
|
||||
private static readonly RNGCryptoServiceProvider _keyGenerator = new RNGCryptoServiceProvider();
|
||||
|
||||
private readonly ConcurrentDictionary<string, (HttpConnectionContext Connection, ValueStopwatch Timer)> _connections =
|
||||
new ConcurrentDictionary<string, (HttpConnectionContext Connection, ValueStopwatch Timer)>(StringComparer.Ordinal);
|
||||
private readonly TimerAwaitable _nextHeartbeat;
|
||||
|
|
@ -113,7 +111,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Internal
|
|||
// 128 bit buffer / 8 bits per byte = 16 bytes
|
||||
Span<byte> buffer = stackalloc byte[16];
|
||||
// Generate the id with RNGCrypto because we want a cryptographically random id, which GUID is not
|
||||
_keyGenerator.GetBytes(buffer);
|
||||
RandomNumberGenerator.Fill(buffer);
|
||||
return WebEncoders.Base64UrlEncode(buffer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -513,19 +513,7 @@ namespace Microsoft.DotNet.OpenApi.Commands
|
|||
|
||||
private static byte[] GetHash(Stream stream)
|
||||
{
|
||||
SHA256 algorithm;
|
||||
try
|
||||
{
|
||||
algorithm = SHA256.Create();
|
||||
}
|
||||
catch (TargetInvocationException)
|
||||
{
|
||||
// SHA256.Create is documented to throw this exception on FIPS-compliant machines. See
|
||||
// https://msdn.microsoft.com/en-us/library/z08hz7ad Fall back to a FIPS-compliant SHA256 algorithm.
|
||||
algorithm = new SHA256CryptoServiceProvider();
|
||||
}
|
||||
|
||||
using (algorithm)
|
||||
using (var algorithm = SHA256.Create())
|
||||
{
|
||||
return algorithm.ComputeHash(stream);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue