.net core中你的MD5用对了吗?

  • .net core中你的MD5用对了吗?已关闭评论
  • 134 次浏览
  • A+
所属分类:.NET技术
摘要

本文的项目环境为 .net 6.0 (.net 5.0 以上都支持)在 .net 中获取字符串的 MD5 相信是非常容易的事情吧, 但是随便在网上搜一搜发现流传的版本还不少呢,比如:


本文的项目环境为 .net 6.0 (.net 5.0 以上都支持)

在 .net 中获取字符串的 MD5 相信是非常容易的事情吧, 但是随便在网上搜一搜发现流传的版本还不少呢,比如:

  1. StringBuilder 版本(应该算是官方版本了,使用的人最多,我发现在 ABP 中也是使用的这个)

  2. BitConverter 版本

  3. StringConcat 版本 (字符串拼接,用的人很少,估计都知道性能不好)

但是它们是否是最佳实现? 我们来测试一下

StringBuilder 版本

public static string Md5_StringBuilder(string input) {     using var md5 = MD5.Create();     var inputBytes = Encoding.UTF8.GetBytes(input);     var hashBytes = md5.ComputeHash(inputBytes);     var sb = new StringBuilder();     foreach (var hashByte in hashBytes)     {         sb.Append(hashByte.ToString("X2"));     }     return sb.ToString(); } 

BitConverter 版本

public static string Md5_BitConverter(string input) {     using var md5 = MD5.Create();     var inputBytes = Encoding.UTF8.GetBytes(input);     var hashBytes = md5.ComputeHash(inputBytes);     return BitConverter.ToString(hashBytes).Replace("-", ""); } 

StringConcat 版本

public static string Md5_StringConcat(string input) {     using var md5 = MD5.Create();     var inputBytes = Encoding.UTF8.GetBytes(input);     var hashBytes = md5.ComputeHash(inputBytes);     var output = string.Empty;     foreach (var hashByte in hashBytes)     {         output += hashByte.ToString("X2");     }     return output; } 

性能对比

先上我测试得到的数据(本机配置: 4 核 8 线程, 测试结果可能不一致)

.net core中你的MD5用对了吗?

看结果,的确是字符串拼接性能最差,但是 StringBuilder 好像也不是很高效啊,那个什么 Static 是啥玩意,怎么性能这么好,相对于 StringBuilder, 单线程性能提高了 3 倍, 多线性提高了 5 倍???

没错,这就是我要说的, 从 .net 5.0 开始提供了 2 个非常高效的方法

  • Convert.ToHexString
  • MD5.HashData

Convert.ToHexString 实例版本

public static string MD5_HexConvert_Instance(string input) {     using var md5 = MD5.Create();     var inputBytes = Encoding.UTF8.GetBytes(input);     var hashBytes = md5.ComputeHash(inputBytes);     return Convert.ToHexString(hashBytes); } 

MD5.HashData 静态版本(强烈建议)

public static string MD5_HexConvert_Static(string input) {     var inputBytes = Encoding.UTF8.GetBytes(input);     var hashBytes = MD5.HashData(inputBytes);     return Convert.ToHexString(hashBytes); } 

总结

  • 强烈建议 使用 MD5.HashData + Convert.ToHexString, 代码性能最高,也最简洁,只有 3 行

  • 一定不要 忘记释放 MD5,我看网上很多在使用实例版本 MD5.Create() 后都没有 Dispose, 这会导致 内存泄漏!!!

最后放上我的完整的测试代码

using System.Text; using System.Security.Cryptography; using System.Diagnostics;  namespace ConsoleTest;  class Program {     public static string Md5_StringBuilder(string input)     {         using var md5 = MD5.Create();         var inputBytes = Encoding.UTF8.GetBytes(input);         var hashBytes = md5.ComputeHash(inputBytes);         var sb = new StringBuilder();         foreach (var hashByte in hashBytes)         {             sb.Append(hashByte.ToString("X2"));         }         return sb.ToString();     }      public static string Md5_StringConcat(string input)     {         using var md5 = MD5.Create();         var inputBytes = Encoding.UTF8.GetBytes(input);         var hashBytes = md5.ComputeHash(inputBytes);         var output = string.Empty;         foreach (var hashByte in hashBytes)         {             output += hashByte.ToString("X2");         }         return output;     }      public static string Md5_BitConverter(string input)     {         using var md5 = MD5.Create();         var inputBytes = Encoding.UTF8.GetBytes(input);         var hashBytes = md5.ComputeHash(inputBytes);         return BitConverter.ToString(hashBytes).Replace("-", "");     }      public static string MD5_HexConvert_Instance(string input)     {         using var md5 = MD5.Create();         var inputBytes = Encoding.UTF8.GetBytes(input);         var hashBytes = md5.ComputeHash(inputBytes);         return Convert.ToHexString(hashBytes);     }      public static string MD5_HexConvert_Static(string input)     {         var inputBytes = Encoding.UTF8.GetBytes(input);         var hashBytes = MD5.HashData(inputBytes);         return Convert.ToHexString(hashBytes);     }      private const int LOOPCOUNT = 100_0000;     private static void CalcTime(Func<string, string> func, bool parallel = true)     {         Stopwatch stopwatch = Stopwatch.StartNew();          if (parallel)         {             Parallel.For(0, LOOPCOUNT, i =>             {                 func("123456");             });         }         else         {             for (int i = 0; i < LOOPCOUNT; i++)             {                 func("123456");             }         }          stopwatch.Stop();         Console.WriteLine($"{func.Method.Name,32}: {stopwatch.ElapsedMilliseconds,4}ms");     }      static void Main()     {         Test();          Console.ReadKey();     }      private static void Test()     {         var functions = new List<Func<string, string>>         {             Md5_StringConcat,             Md5_StringBuilder,             Md5_BitConverter,             MD5_HexConvert_Instance,             MD5_HexConvert_Static,         };          foreach (var func in functions)         {             Console.WriteLine($"{func.Method.Name,32}: {func("123456")}");         }          Console.WriteLine($"n单线程 {LOOPCOUNT} 次用时统计:");         foreach (var func in functions)         {             CalcTime(func, false);         }           Console.WriteLine($"n多线程 {LOOPCOUNT} 次用时统计:");         foreach (var func in functions)         {             CalcTime(func, true);         }     } }