diff --git a/src/Umbraco.Core/Security/BackOfficeUserStore.cs b/src/Umbraco.Core/Security/BackOfficeUserStore.cs
index 889c7004d7..7d5774c870 100644
--- a/src/Umbraco.Core/Security/BackOfficeUserStore.cs
+++ b/src/Umbraco.Core/Security/BackOfficeUserStore.cs
@@ -494,7 +494,7 @@ namespace Umbraco.Core.Security
//the stamp cannot be null, so if it is currently null then we'll just return a hash of the password
return Task.FromResult(user.SecurityStamp.IsNullOrWhiteSpace()
- ? user.PasswordHash.ToMd5()
+ ? user.PasswordHash.GenerateHash()
: user.SecurityStamp);
}
diff --git a/src/Umbraco.Core/StringExtensions.cs b/src/Umbraco.Core/StringExtensions.cs
index 225ac99ff7..f540305325 100644
--- a/src/Umbraco.Core/StringExtensions.cs
+++ b/src/Umbraco.Core/StringExtensions.cs
@@ -701,67 +701,72 @@ namespace Umbraco.Core
return val;
}
+ ///
+ /// Generates a hash of a string based on the FIPS compliance setting.
+ ///
+ /// Referrs to itself
+ /// The hashed string
+ public static string GenerateHash(this string str)
+ {
+ return CryptoConfig.AllowOnlyFipsAlgorithms
+ ? str.ToSHA1()
+ : str.ToMd5();
+ }
+
///
/// Converts the string to MD5
///
- /// referrs to itself
- /// the md5 hashed string
+ /// Referrs to itself
+ /// The MD5 hashed string
public static string ToMd5(this string stringToConvert)
{
- //create an instance of the MD5CryptoServiceProvider
- var md5Provider = new MD5CryptoServiceProvider();
-
- //convert our string into byte array
- var byteArray = Encoding.UTF8.GetBytes(stringToConvert);
-
- //get the hashed values created by our MD5CryptoServiceProvider
- var hashedByteArray = md5Provider.ComputeHash(byteArray);
-
- //create a StringBuilder object
- var stringBuilder = new StringBuilder();
-
- //loop to each each byte
- foreach (var b in hashedByteArray)
- {
- //append it to our StringBuilder
- stringBuilder.Append(b.ToString("x2").ToLower());
- }
-
- //return the hashed value
- return stringBuilder.ToString();
+ return stringToConvert.GenerateHash("MD5");
}
///
/// Converts the string to SHA1
///
/// referrs to itself
- /// the md5 hashed string
+ /// The SHA1 hashed string
public static string ToSHA1(this string stringToConvert)
{
- //create an instance of the SHA1CryptoServiceProvider
- var md5Provider = new SHA1CryptoServiceProvider();
-
- //convert our string into byte array
- var byteArray = Encoding.UTF8.GetBytes(stringToConvert);
-
- //get the hashed values created by our SHA1CryptoServiceProvider
- var hashedByteArray = md5Provider.ComputeHash(byteArray);
-
- //create a StringBuilder object
- var stringBuilder = new StringBuilder();
-
- //loop to each each byte
- foreach (var b in hashedByteArray)
- {
- //append it to our StringBuilder
- stringBuilder.Append(b.ToString("x2").ToLower());
- }
-
- //return the hashed value
- return stringBuilder.ToString();
+ return stringToConvert.GenerateHash("SHA1");
}
+ /// Generate a hash of a string based on the hashType passed in
+ ///
+ /// Referrs to itself
+ /// String with the hash type. See remarks section of the CryptoConfig Class in MSDN docs for a list of possible values.
+ /// The hashed string
+ private static string GenerateHash(this string str, string hashType)
+ {
+ //create an instance of the correct hashing provider based on the type passed in
+ var hasher = HashAlgorithm.Create(hashType);
+ if (hasher == null) throw new InvalidOperationException("No hashing type found by name " + hashType);
+ using (hasher)
+ {
+ //convert our string into byte array
+ var byteArray = Encoding.UTF8.GetBytes(str);
+
+ //get the hashed values created by our selected provider
+ var hashedByteArray = hasher.ComputeHash(byteArray);
+
+ //create a StringBuilder object
+ var stringBuilder = new StringBuilder();
+
+ //loop to each each byte
+ foreach (var b in hashedByteArray)
+ {
+ //append it to our StringBuilder
+ stringBuilder.Append(b.ToString("x2").ToLower());
+ }
+
+ //return the hashed value
+ return stringBuilder.ToString();
+ }
+ }
+
///
/// Decodes a string that was encoded with UrlTokenEncode
///
@@ -1465,10 +1470,7 @@ namespace Umbraco.Core
///
internal static Guid ToGuid(this string text)
{
- var md5 = MD5.Create();
- byte[] myStringBytes = Encoding.ASCII.GetBytes(text);
- byte[] hash = md5.ComputeHash(myStringBytes);
- return new Guid(hash);
+ return new Guid(text.GenerateHash());
}
}
}
diff --git a/src/Umbraco.Web/Editors/GravatarController.cs b/src/Umbraco.Web/Editors/GravatarController.cs
index f1e184dce7..23c4a731c2 100644
--- a/src/Umbraco.Web/Editors/GravatarController.cs
+++ b/src/Umbraco.Web/Editors/GravatarController.cs
@@ -1,5 +1,6 @@
using System;
using System.Net;
+using System.Security.Cryptography;
using Umbraco.Core;
using Umbraco.Web.Mvc;
@@ -13,6 +14,14 @@ namespace Umbraco.Web.Editors
{
public string GetCurrentUserGravatarUrl()
{
+ // If FIPS is required, never check the Gravatar service as it only supports MD5 hashing.
+ // Unfortunately, if the FIPS setting is enabled on Windows, using MD5 will throw an exception
+ // and the website will not run.
+ if (CryptoConfig.AllowOnlyFipsAlgorithms)
+ {
+ return null;
+ }
+
var userService = Services.UserService;
var user = userService.GetUserById(UmbracoContext.Security.CurrentUser.Id);
var gravatarHash = user.Email.ToMd5();
diff --git a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs
index 72093b19a8..eedc2cafca 100644
--- a/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/UserModelMapper.cs
@@ -23,7 +23,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService)))
.ForMember(
detail => detail.EmailHash,
- opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().ToMd5()))
+ opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().GenerateHash()))
.ForMember(detail => detail.SecondsUntilTimeout, opt => opt.Ignore());
config.CreateMap()
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(detail => detail.AllowedSections, opt => opt.MapFrom(user => user.AllowedSections))
.ForMember(
detail => detail.EmailHash,
- opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().ToMd5()))
+ opt => opt.MapFrom(user => user.Email.ToLowerInvariant().Trim().GenerateHash()))
.ForMember(detail => detail.SecondsUntilTimeout, opt => opt.Ignore());
config.CreateMap()
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 5befbda7cf..b2d6539b67 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -1238,20 +1238,30 @@ namespace Umbraco.Web
return _stringUtilities.ReplaceLineBreaksForHtml(text);
}
- ///
- /// Returns an MD5 hash of the string specified
- ///
- /// The text to create a hash from
- /// Md5 has of the string
- public string CreateMd5Hash(string text)
- {
- return text.ToMd5();
- }
+ ///
+ /// Returns an MD5 hash of the string specified
+ ///
+ /// The text to create a hash from
+ /// Md5 hash of the string
+ public string CreateMd5Hash(string text)
+ {
+ return text.ToMd5();
+ }
- ///
- /// Strips all html tags from a given string, all contents of the tags will remain.
- ///
- public HtmlString StripHtml(IHtmlString html, params string[] tags)
+ ///
+ /// Returns a FIPS compliant hash of the string specified
+ ///
+ /// The text to create a hash from
+ /// hash of the string
+ public string CreateHash(string text)
+ {
+ return text.GenerateHash();
+ }
+
+ ///
+ /// Strips all html tags from a given string, all contents of the tags will remain.
+ ///
+ public HtmlString StripHtml(IHtmlString html, params string[] tags)
{
return StripHtml(html.ToHtmlString(), tags);
}
diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs
index 8bd94aa5b6..f728cd05ac 100644
--- a/src/Umbraco.Web/umbraco.presentation/library.cs
+++ b/src/Umbraco.Web/umbraco.presentation/library.cs
@@ -663,7 +663,8 @@ namespace umbraco
/// Md5 has of the string
public static string md5(string text)
{
- return text.ToMd5();
+ //return text.ToMd5();
+ return text.GenerateHash();
}
///
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs
index d03dca1d6d..a06df51f5e 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/plugins/tinymce3/GzipCompressor.cs
@@ -12,6 +12,7 @@ using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
+using Umbraco.Core;
namespace umbraco.presentation.plugins.tinymce3
{
@@ -91,7 +92,7 @@ namespace umbraco.presentation.plugins.tinymce3
key += item.Data;
}
- key = MD5(key);
+ key = Hash(key);
if (this.NoCompression) {
this.SendPlainText(key, to_stream);
return;
@@ -224,12 +225,9 @@ namespace umbraco.presentation.plugins.tinymce3
}
}
- private string MD5(string str) {
- MD5 md5 = new MD5CryptoServiceProvider();
- byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str));
- str = BitConverter.ToString(result);
-
- return str.Replace("-", "");
+ private string Hash(string str)
+ {
+ return str.GenerateHash();
}
#endregion
diff --git a/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs b/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs
index 56d1b414c5..72a894f32f 100644
--- a/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs
+++ b/src/UmbracoExamine/LocalStorage/AzureLocalStorageDirectory.cs
@@ -16,7 +16,7 @@ namespace UmbracoExamine.LocalStorage
{
public DirectoryInfo GetLocalStorageDirectory(NameValueCollection config, string configuredPath)
{
- var appDomainHash = HttpRuntime.AppDomainAppId.ToMd5();
+ var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "LuceneDir",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
diff --git a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs
index e3c7a22bd0..cddf6bc5dd 100644
--- a/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs
+++ b/src/umbraco.MacroEngines/RazorCore/RazorMacroEngine.cs
@@ -26,8 +26,8 @@ namespace umbraco.MacroEngines
return "~/" + physicalPath;
}
- public string GetMd5(string text) {
- return text.ToMd5();
+ public string GetHash(string text) {
+ return text.GenerateHash();
}
///
@@ -145,7 +145,7 @@ namespace umbraco.MacroEngines
//Get Rid Of Whitespace From Start/End
razorSyntax = razorSyntax.Trim();
//Use MD5 as a cache key
- var syntaxMd5 = GetMd5(razorSyntax);
+ var syntaxMd5 = GetHash(razorSyntax);
var fileName = "inline-" + syntaxMd5 + "." + scriptLanguage;
return CreateTemporaryRazorFile(razorSyntax, fileName, true);
}
diff --git a/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs b/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs
index cbd2fc24d8..d84453fa03 100644
--- a/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs
+++ b/src/umbraco.editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs
@@ -12,6 +12,7 @@ using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
+using Umbraco.Core;
namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
{
@@ -93,7 +94,7 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
key += item.Data;
}
- key = MD5(key);
+ key = Hash(key);
if (this.NoCompression) {
this.SendPlainText(key, to_stream);
return;
@@ -226,12 +227,9 @@ namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin
}
}
- private string MD5(string str) {
- MD5 md5 = new MD5CryptoServiceProvider();
- byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str));
- str = BitConverter.ToString(result);
-
- return str.Replace("-", "");
+ private string Hash(string str)
+ {
+ return str.GenerateHash();
}
#endregion