From edb5baf81c07e3e9db8c3019439414094acb6ef8 Mon Sep 17 00:00:00 2001 From: "N. Taylor Mullen" Date: Tue, 9 Aug 2016 11:44:52 -0700 Subject: [PATCH] Change SHA256 algorithm to work on FIPS-compliant machines. #5103 --- .../Cache/CacheTagKey.cs | 15 ++++---- .../Internal/CryptographyAlgorithms.cs | 38 +++++++++++++++++++ .../Internal/FileVersionProvider.cs | 2 +- 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/CryptographyAlgorithms.cs diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Cache/CacheTagKey.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Cache/CacheTagKey.cs index 3abaea6627..f46295d3de 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Cache/CacheTagKey.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Cache/CacheTagKey.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.TagHelpers.Internal; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Internal; @@ -151,10 +152,10 @@ 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 sha = SHA256.Create()) + using (var sha256 = CryptographyAlgorithms.CreateSHA256()) { var contentBytes = Encoding.UTF8.GetBytes(key); - var hashedBytes = sha.ComputeHash(contentBytes); + var hashedBytes = sha256.ComputeHash(contentBytes); return Convert.ToBase64String(hashedBytes); } } @@ -183,14 +184,14 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache AreSame(_headers, other._headers) && AreSame(_queries, other._queries) && AreSame(_routeValues, other._routeValues) && - _varyByUser == other._varyByUser && + _varyByUser == other._varyByUser && (!_varyByUser || string.Equals(other._username, _username, StringComparison.Ordinal)); } /// public override int GetHashCode() { - // The hashcode is intentionally not using the computed + // The hashcode is intentionally not using the computed // stringified key in order to prevent string allocations // in the common case where it's not explicitly required. @@ -219,7 +220,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache return _hashcode.Value; } - + private static IList> ExtractCollection(string keys, TSourceCollection collection, Func accessor) { if (string.IsNullOrEmpty(keys)) @@ -244,7 +245,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache return result; } - + private static void AddStringCollection( StringBuilder builder, string collectionName, @@ -275,7 +276,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache .Append(CacheKeyTokenSeparator) .Append(item.Value); } - + builder.Append(")"); } diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/CryptographyAlgorithms.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/CryptographyAlgorithms.cs new file mode 100644 index 0000000000..569c34ea7b --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/CryptographyAlgorithms.cs @@ -0,0 +1,38 @@ +// 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.TagHelpers.Internal +{ + public static class CryptographyAlgorithms + { +#if NETSTANDARD1_6 + public static SHA256 CreateSHA256() + { + var sha256 = SHA256.Create(); + + return sha256; + } +#else + public static SHA256 CreateSHA256() + { + SHA256 sha256; + + try + { + sha256 = 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. + sha256 = new SHA256CryptoServiceProvider(); + } + + return sha256; + } +#endif + } +} diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/FileVersionProvider.cs b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/FileVersionProvider.cs index c20d81145b..88ec50b513 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/FileVersionProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Internal/FileVersionProvider.cs @@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Internal private static string GetHashForFile(IFileInfo fileInfo) { - using (var sha256 = SHA256.Create()) + using (var sha256 = CryptographyAlgorithms.CreateSHA256()) { using (var readStream = fileInfo.CreateReadStream()) {