您好,登錄后才能下訂單哦!
這篇文章主要介紹.NET6中哈希算法怎么用,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
微軟在 .NET 6 中引入一些更簡(jiǎn)單的 API 來(lái)使用 HMAC 哈希算法(MD5/SHA1/SHA256/SHA384/SHA512)
微軟的叫法叫做 HMAC One-Shoot method, HMAC 算法在普通的哈希算法基礎(chǔ)上增加了一個(gè) key,通過(guò) key 提升了安全性,能夠有效避免密碼泄露被彩虹表反推出真實(shí)密碼, JWT(Json Web Token) 除了可以使用 RSA 方式外也支持使用 HMAC 。
新增的 API 定義如下:
namespace System.Security.Cryptography { public partial class HMACMD5 { public static byte[] HashData(byte[] key, byte[] source); public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source); public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination); public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten); } public partial class HMACSHA1 { public static byte[] HashData(byte[] key, byte[] source); public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source); public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination); public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten); } public partial class HMACSHA256 { public static byte[] HashData(byte[] key, byte[] source); public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source); public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination); public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten); } public partial class HMACSHA384 { public static byte[] HashData(byte[] key, byte[] source); public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source); public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination); public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten); } public partial class HMACSHA512 { public static byte[] HashData(byte[] key, byte[] source); public static byte[] HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source); public static int HashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination); public static bool TryHashData(ReadOnlySpan<byte> key, ReadOnlySpan<byte> source, Span<byte> destination, out int bytesWritten); } }
在之前的版本中想要實(shí)現(xiàn)計(jì)算 HMAC 算法會(huì)比較復(fù)雜,之前實(shí)現(xiàn)了一個(gè) HashHelper 來(lái)封裝了常用的 Hash 算法和 HMAC 算法,HashHelper 部分代碼如下,完整代碼可以從 Github 獲取:https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Helpers/HashHelper.cs
/// <summary> /// 獲取哈希之后的字符串 /// </summary> /// <param name="type">哈希類型</param> /// <param name="source">源</param> /// <param name="key">key</param> /// <param name="isLower">是否是小寫</param> /// <returns>哈希算法處理之后的字符串</returns> public static string GetHashedString(HashType type, byte[] source, byte[]? key, bool isLower = false) { Guard.NotNull(source, nameof(source)); if (source.Length == 0) { return string.Empty; } var hashedBytes = GetHashedBytes(type, source, key); var sbText = new StringBuilder(); if (isLower) { foreach (var b in hashedBytes) { sbText.Append(b.ToString("x2")); } } else { foreach (var b in hashedBytes) { sbText.Append(b.ToString("X2")); } } return sbText.ToString(); } /// <summary> /// 計(jì)算字符串Hash值 /// </summary> /// <param name="type">hash類型</param> /// <param name="str">要hash的字符串</param> /// <returns>hash過(guò)的字節(jié)數(shù)組</returns> public static byte[] GetHashedBytes(HashType type, string str) => GetHashedBytes(type, str, Encoding.UTF8); /// <summary> /// 計(jì)算字符串Hash值 /// </summary> /// <param name="type">hash類型</param> /// <param name="str">要hash的字符串</param> /// <param name="encoding">編碼類型</param> /// <returns>hash過(guò)的字節(jié)數(shù)組</returns> public static byte[] GetHashedBytes(HashType type, string str, Encoding encoding) { Guard.NotNull(str, nameof(str)); if (str == string.Empty) { return Array.Empty<byte>(); } var bytes = encoding.GetBytes(str); return GetHashedBytes(type, bytes); } /// <summary> /// 獲取Hash后的字節(jié)數(shù)組 /// </summary> /// <param name="type">哈希類型</param> /// <param name="bytes">原字節(jié)數(shù)組</param> /// <returns></returns> public static byte[] GetHashedBytes(HashType type, byte[] bytes) => GetHashedBytes(type, bytes, null); /// <summary> /// 獲取Hash后的字節(jié)數(shù)組 /// </summary> /// <param name="type">哈希類型</param> /// <param name="key">key</param> /// <param name="bytes">原字節(jié)數(shù)組</param> /// <returns></returns> public static byte[] GetHashedBytes(HashType type, byte[] bytes, byte[]? key) { Guard.NotNull(bytes, nameof(bytes)); if (bytes.Length == 0) { return bytes; } HashAlgorithm algorithm = null!; try { if (key == null) { algorithm = type switch { HashType.SHA1 => new SHA1Managed(), HashType.SHA256 => new SHA256Managed(), HashType.SHA384 => new SHA384Managed(), HashType.SHA512 => new SHA512Managed(), _ => MD5.Create() }; } else { algorithm = type switch { HashType.SHA1 => new HMACSHA1(key), HashType.SHA256 => new HMACSHA256(key), HashType.SHA384 => new HMACSHA384(key), HashType.SHA512 => new HMACSHA512(key), _ => new HMACMD5(key) }; } return algorithm.ComputeHash(bytes); } finally { algorithm.Dispose(); } }
使用示例如下:
HashHelper.GetHashedBytes(HashType.MD5, "test"); HashHelper.GetHashedBytes(HashType.MD5, "test".GetBytes()); HashHelper.GetHashedBytes(HashType.MD5, "test", "testKey"); HashHelper.GetHashedBytes(HashType.MD5, "test".GetBytes(), "testKey".GetBytes()); HashHelper.GetHashedString(HashType.MD5, "test"); HashHelper.GetHashedString(HashType.SHA1, "test".GetBytes()); HashHelper.GetHashedString(HashType.SHA256, "test", "testKey"); HashHelper.GetHashedString(HashType.MD5, "test".GetBytes(), "testKey".GetBytes());
有了新的 API 以后可以怎么簡(jiǎn)化呢,來(lái)看下面的示例:
var bytes = "test".GetBytes(); var keyBytes = "test-key".GetBytes(); // HMACMD5 var hmd5V1 = HMACMD5.HashData(keyBytes, bytes); var hmd5V2 = HashHelper.GetHashedBytes(HashType.MD5, bytes, keyBytes); Console.WriteLine(hmd5V2.SequenceEqual(hmd5V1)); // HMACSHA1 var hsha1V1 = HMACSHA1.HashData(keyBytes, bytes); var hsha1V2 = HashHelper.GetHashedBytes(HashType.SHA1, bytes, keyBytes); Console.WriteLine(hsha1V2.SequenceEqual(hsha1V1)); // HMACSHA256 var hsha256V1 = HMACSHA256.HashData(keyBytes, bytes); var hsha256V2 = HashHelper.GetHashedBytes(HashType.SHA256, bytes, keyBytes); Console.WriteLine(hsha256V2.SequenceEqual(hsha256V1)); // HMACSHA384 var hsha384V1 = HMACSHA384.HashData(keyBytes ,bytes); var hsha384V2 = HashHelper.GetHashedBytes(HashType.SHA384, bytes, keyBytes); Console.WriteLine(hsha384V2.SequenceEqual(hsha384V1)); // HMACSHA512 var hsha512V1 = HMACSHA512.HashData(keyBytes ,bytes); var hsha512V2 = HashHelper.GetHashedBytes(HashType.SHA512, bytes, keyBytes); Console.WriteLine(hsha512V2.SequenceEqual(hsha512V1));
直接使用對(duì)應(yīng)的 HMAC 哈希算法的 HashData 方法即可,傳入對(duì)應(yīng)的 key 和 原始內(nèi)容就可以了,上面是和我們 HashHelper 封裝的方法進(jìn)行對(duì)比,看結(jié)果是否一致,都是一致的,輸出結(jié)果如下:
對(duì)于普通的哈希算法,微軟其實(shí)在 .NET 5 就已經(jīng)支持了上面的用法,可以嘗試一下下面的代碼:
var bytes = "test".GetBytes(); // MD5 var md5V1 = MD5.HashData(bytes); var md5V2 = HashHelper.GetHashedBytes(HashType.MD5, bytes); Console.WriteLine(md5V2.SequenceEqual(md5V1)); // SHA1 var sha1V1 = SHA1.HashData(bytes); var sha1V2 = HashHelper.GetHashedBytes(HashType.SHA1, bytes); Console.WriteLine(sha1V2.SequenceEqual(sha1V1)); // SHA256 var sha256V1 = SHA256.HashData(bytes); var sha256V2 = HashHelper.GetHashedBytes(HashType.SHA256, bytes); Console.WriteLine(sha256V2.SequenceEqual(sha256V1)); // SHA384 var sha384V1 = SHA384.HashData(bytes); var sha384V2 = HashHelper.GetHashedBytes(HashType.SHA384, bytes); Console.WriteLine(sha384V2.SequenceEqual(sha384V1)); // SHA512 var sha512V1 = SHA512.HashData(bytes); var sha512V2 = HashHelper.GetHashedBytes(HashType.SHA512, bytes); Console.WriteLine(sha512V2.SequenceEqual(sha512V1));
很多時(shí)候我們可能都會(huì)要使用 MD5 或者 SHA1 之后的字符串,不知道為什么微軟沒(méi)有直接獲取一個(gè)字符串的方法,如果有這樣一個(gè)方法,就會(huì)更方便了,相比之后,感覺(jué)還是自己封裝的 HashHelper 使用起來(lái)更舒服一些,哈哈,這樣的靜態(tài)方法不夠抽象如果要?jiǎng)討B(tài)替換哈希算法代碼可能就有點(diǎn)...
以上是“.NET6中哈希算法怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。