【问题标题】:Calculate a MD5 hash from a string从字符串计算 MD5 哈希
【发布时间】:2012-07-12 07:57:08
【问题描述】:

我使用以下 C# 代码从字符串计算 MD5 哈希。 它运行良好并生成一个 32 个字符的十六进制字符串,如下所示: 900150983cd24fb0d6963f7d28e17f72

string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";

//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);

// and then convert tmpHash to string...

有没有办法使用这样的代码来生成 16 个字符的十六进制字符串(或 12 个字符的字符串)? 32个字符的十六进制字符串很好,但我觉得客户输入代码会很无聊!

【问题讨论】:

  • MD5CryptoServiceProvider 实例应该被处理

标签: c# md5


【解决方案1】:

这里是精简版。

private string CreateMD5(string myText)
{
    var hash = System.Security.Cryptography.MD5.Create()
        .ComputeHash(System.Text.Encoding.ASCII.GetBytes(myText ?? ""));
    return string.Join("", Enumerable.Range(0, hash.Length).Select(i => hash[i].ToString("x2")));
}

【讨论】:

    【解决方案2】:

    我想最好在字符串MD5中使用UTF-8编码。

    public static string MD5(this string s)
    {
        using var provider = System.Security.Cryptography.MD5.Create();        
        StringBuilder builder = new StringBuilder();                           
    
        foreach (byte b in provider.ComputeHash(Encoding.UTF8.GetBytes(s)))
            builder.Append(b.ToString("x2").ToLower());
    
        return builder.ToString();        
    }
    

    【讨论】:

      【解决方案3】:
          public static string GetMD5(string encryptString)
          {
              var passByteCrypt = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(encryptString));
      
              return ByteArrayToString(passByteCrypt);
          }
          public static string ByteArrayToString(byte[] bytes)
          {
              var output = new StringBuilder(bytes.Length);
      
              foreach (var t in bytes)
              {
                  output.Append(t.ToString("X2"));
              }
      
              return output.ToString().ToLower();
          }
      

      这是简单的 md5 ByteCrypt

      【讨论】:

        【解决方案4】:
        public static string Md5(string input, bool isLowercase = false)
        {
            using (var md5 = MD5.Create())
            {
                var byteHash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
                var hash = BitConverter.ToString(byteHash).Replace("-", "");
                return (isLowercase) ? hash.ToLower() : hash;
            }
        }
        

        【讨论】:

          【解决方案5】:

          扩展Anant Dabhianswer

          辅助方法:

          using System.Text;
          
          namespace XYZ.Helpers
          {
              public static class EncryptionHelper
              {
                  public static string ToMD5(this string input)
                  {
                      // Use input string to calculate MD5 hash
                      using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
                      {
                          byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
                          byte[] hashBytes = md5.ComputeHash(inputBytes);
          
                          // Convert the byte array to hexadecimal string
                          StringBuilder sb = new StringBuilder();
                          for (int i = 0; i < hashBytes.Length; i++)
                          {
                              sb.Append(hashBytes[i].ToString("X2"));
                          }
                          return sb.ToString();
                      }
                  }
              }
          }
          

          【讨论】:

            【解决方案6】:

            这是UTF8 的实用函数,如果需要,可以用ASCII 替换:

                public static byte[] MD5Hash(string message)
                {
                    return MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(message));
                }
            

            【讨论】:

            • 这不会处理MD5的实例
            【解决方案7】:

            根据MSDN

            创建 MD5:

            public static string CreateMD5(string input)
            {
                // Use input string to calculate MD5 hash
                using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
                {
                    byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
                    byte[] hashBytes = md5.ComputeHash(inputBytes);
            
                    // Convert the byte array to hexadecimal string
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < hashBytes.Length; i++)
                    {
                        sb.Append(hashBytes[i].ToString("X2"));
                    }
                    return sb.ToString();
                }
            }
            

            【讨论】:

            • 如果你从某个地方复制/粘贴,你应该总是说明你从哪里得到代码,否则它被归类为剽窃。
            • MD5类实现了IDisposable,记得dispose你的实例。 ;)
            • 一般来说你应该散列一个无损文本编码,比如UTF8。
            • @PrashantPimpale MD5 是一种摘要算法。把它想象成把一头牛变成一块牛排。
            【解决方案8】:

            Idk 任何关于 16 个字符的十六进制字符串....

            using System;
            using System.Security.Cryptography;
            using System.Text;
            

            但这是我在一行中创建 MD5 哈希的方法。

            string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
            

            【讨论】:

              【解决方案9】:

              我想提供一个替代方案,在我的测试 (.NET 4.7.2) 中,它的执行速度至少比 craigdfrench's answer 快 10%:

              public static string GetMD5Hash(string text)
              {
                  using ( var md5 = MD5.Create() )
                  {
                      byte[] computedHash = md5.ComputeHash( Encoding.UTF8.GetBytes(text) );
                      return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
                  }
              }
              

              如果您更喜欢在顶部使用using System.Runtime.Remoting.Metadata.W3cXsd2001;,可以使方法主体更易于阅读:

              using ( var md5 = MD5.Create() )
              {
                  return new SoapHexBinary( md5.ComputeHash( Encoding.UTF8.GetBytes(text) ) ).ToString();
              }
              

              很明显,但为了完整起见,在 OP 的上下文中,它将被用作:

              sSourceData = "MySourceData";
              tmpHash = GetMD5Hash(sSourceData);
              

              【讨论】:

                【解决方案10】:

                此解决方案需要 c# 8 并利用 Span&lt;T&gt;。请注意,如果需要,您仍然需要调用 .Replace("-", string.Empty).ToLowerInvariant() 来格式化结果。

                public static string CreateMD5(ReadOnlySpan<char> input)
                {
                    var encoding = System.Text.Encoding.UTF8;
                    var inputByteCount = encoding.GetByteCount(input);
                    using var md5 = System.Security.Cryptography.MD5.Create();
                
                    Span<byte> bytes = inputByteCount < 1024
                        ? stackalloc byte[inputByteCount]
                        : new byte[inputByteCount];
                    Span<byte> destination = stackalloc byte[md5.HashSize / 8];
                
                    encoding.GetBytes(input, bytes);
                
                    // checking the result is not required because this only returns false if "(destination.Length < HashSizeValue/8)", which is never true in this case
                    md5.TryComputeHash(bytes, destination, out int _bytesWritten);
                
                    return BitConverter.ToString(destination.ToArray());
                }
                

                【讨论】:

                  【解决方案11】:
                  // given, a password in a string
                  string password = @"1234abcd";
                  
                  // byte array representation of that string
                  byte[] encodedPassword = new UTF8Encoding().GetBytes(password);
                  
                  // need MD5 to calculate the hash
                  byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword);
                  
                  // string representation (similar to UNIX format)
                  string encoded = BitConverter.ToString(hash)
                     // without dashes
                     .Replace("-", string.Empty)
                     // make lowercase
                     .ToLower();
                  
                  // encoded contains the hash you want
                  

                  【讨论】:

                  • 为什么“类似于UNIX格式”?有什么不完全一样的?
                  • 这给出了与在线 md5 检查器不同的结果。还是只有我??
                  • @bh_earth0 似乎 BitConverter 在 windows 和 linux 上的工作方式不同,请参阅这个问题:stackoverflow.com/questions/11454004/…
                  【解决方案12】:

                  .NET Core 2.1 及更高版本的现有答案的更快替代方案:

                  public static string CreateMD5(string s)
                  {
                      using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
                      {
                          var encoding = Encoding.ASCII;
                          var data = encoding.GetBytes(s);
                  
                          Span<byte> hashBytes = stackalloc byte[16];
                          md5.TryComputeHash(data, hashBytes, out int written);
                          if(written != hashBytes.Length)
                              throw new OverflowException();
                  
                  
                          Span<char> stringBuffer = stackalloc char[32];
                          for (int i = 0; i < hashBytes.Length; i++)
                          {
                              hashBytes[i].TryFormat(stringBuffer.Slice(2 * i), out _, "x2");
                          }
                          return new string(stringBuffer);
                      }
                  }
                  

                  如果您确定您的字符串足够小并用 unsafe int GetBytes(ReadOnlySpan chars, Span bytes) 替代 encoding.GetBytes 替换,您可以进一步优化它。

                  【讨论】:

                    【解决方案13】:

                    https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?view=netframework-4.7.2

                    using System;
                    using System.Security.Cryptography;
                    using System.Text;
                    
                        static string GetMd5Hash(string input)
                                {
                                    using (MD5 md5Hash = MD5.Create())
                                    {
                    
                                        // Convert the input string to a byte array and compute the hash.
                                        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
                    
                                        // Create a new Stringbuilder to collect the bytes
                                        // and create a string.
                                        StringBuilder sBuilder = new StringBuilder();
                    
                                        // Loop through each byte of the hashed data 
                                        // and format each one as a hexadecimal string.
                                        for (int i = 0; i < data.Length; i++)
                                        {
                                            sBuilder.Append(data[i].ToString("x2"));
                                        }
                    
                                        // Return the hexadecimal string.
                                        return sBuilder.ToString();
                                    }
                                }
                    
                                // Verify a hash against a string.
                                static bool VerifyMd5Hash(string input, string hash)
                                {
                                    // Hash the input.
                                    string hashOfInput = GetMd5Hash(input);
                    
                                    // Create a StringComparer an compare the hashes.
                                    StringComparer comparer = StringComparer.OrdinalIgnoreCase;
                    
                                    return 0 == comparer.Compare(hashOfInput, hash);
                    
                                }
                    

                    【讨论】:

                      【解决方案14】:

                      支持字符串和文件流。

                      例子

                      string hashString = EasyMD5.Hash("My String");
                      
                      string hashFile = EasyMD5.Hash(System.IO.File.OpenRead("myFile.txt"));
                      

                      -

                         class EasyMD5
                              {
                                  private static string GetMd5Hash(byte[] data)
                                  {
                                      StringBuilder sBuilder = new StringBuilder();
                                      for (int i = 0; i < data.Length; i++)
                                          sBuilder.Append(data[i].ToString("x2"));
                                      return sBuilder.ToString();
                                  }
                      
                                  private static bool VerifyMd5Hash(byte[] data, string hash)
                                  {
                                      return 0 == StringComparer.OrdinalIgnoreCase.Compare(GetMd5Hash(data), hash);
                                  }
                      
                                  public static string Hash(string data)
                                  {
                                      using (var md5 = MD5.Create())
                                          return GetMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)));
                                  }
                                  public static string Hash(FileStream data)
                                  {
                                      using (var md5 = MD5.Create())
                                          return GetMd5Hash(md5.ComputeHash(data));
                                  }
                      
                                  public static bool Verify(string data, string hash)
                                  {
                                      using (var md5 = MD5.Create())
                                          return VerifyMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)), hash);
                                  }
                      
                                  public static bool Verify(FileStream data, string hash)
                                  {
                                      using (var md5 = MD5.Create())
                                          return VerifyMd5Hash(md5.ComputeHash(data), hash);
                                  }
                              }
                      

                      【讨论】:

                        【解决方案15】:
                        System.Text.StringBuilder hash = new System.Text.StringBuilder();
                                System.Security.Cryptography.MD5CryptoServiceProvider md5provider = new System.Security.Cryptography.MD5CryptoServiceProvider();
                                byte[] bytes = md5provider.ComputeHash(new System.Text.UTF8Encoding().GetBytes(YourEntryString));
                        
                                for (int i = 0; i < bytes.Length; i++)
                                {
                                    hash.Append(bytes[i].ToString("x2")); //lowerCase; X2 if uppercase desired
                                }
                                return hash.ToString();
                        

                        【讨论】:

                          【解决方案16】:

                          尝试使用 LINQ 创建 MD5 哈希的字符串表示,但是,没有一个答案是 LINQ 解决方案,因此将其添加到可用解决方案的大杂烩中。

                          string result;
                          using (MD5 hash = MD5.Create())
                          {
                              result = String.Join
                              (
                                  "",
                                  from ba in hash.ComputeHash
                                  (
                                      Encoding.UTF8.GetBytes(observedText)
                                  ) 
                                  select ba.ToString("x2")
                              );
                          }
                          

                          【讨论】:

                          • 单行,在方法语法中:return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x =&gt; x.ToString("x2") ) );
                          • ... 在这种情况下,我建议改为return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x =&gt; x.ToString("x2") ) );。它有点短,可能更清晰的意图,并且执行速度略快(
                          【解决方案17】:
                          StringBuilder sb= new StringBuilder();
                          for (int i = 0; i < tmpHash.Length; i++)
                          {
                             sb.Append(tmpHash[i].ToString("x2"));
                          }
                          

                          【讨论】:

                            【解决方案18】:

                            您可以使用Convert.ToBase64String 将 MD5 的 16 字节输出转换为 ~24 字符字符串。在不降低安全性的情况下好一点。 (以j9JIbSY8HuT89/pwdC8jlw== 为例)

                            【讨论】:

                            • 一个不错的解决方法,但我怀疑他的 OP 是否希望它区分大小写并带有特殊字符...
                            • 在尝试将 MD5 哈希(来自 Azure Blob 属性)转换为字符串时,这对我来说效果很好。它生成与 Azure 存储容器完全相同的字符串。
                            【解决方案19】:

                            一个 MD5 哈希是 128 位,所以你不能用少于 32 个字符的十六进制表示它...

                            【讨论】:

                              【解决方案20】:

                              完全取决于您要达到的目标。从技术上讲,您可以只取 MD5 哈希结果的前 12 个字符,但 MD5 的规范是生成一个 32 字符的字符。

                              减小散列的大小会降低安全性,并增加发生冲突和系统被破坏的机会。

                              如果您让我们更多地了解您正在努力实现的目标,或许我们可以提供更多帮助。

                              【讨论】:

                              • 感谢您的回答。并对我的错误解释感到抱歉。我想为 Windows 发布一个应用程序,用户应该购买使用我的应用程序的许可证,所以我的应用程序请求两个字段: USERNAME: ... 和 KEY: .... 我想散列 USERNAME 并创建 KEY ,则用户应输入特定的 USERNAME 和 KEY。我的问题是 KEY 应该是 12 个字符,(但在 MD5 哈希中,我得到 32 个字符的 KEY)。请帮帮我,我真的需要它。
                              猜你喜欢
                              • 2011-12-20
                              • 2012-04-14
                              • 1970-01-01
                              • 2011-08-24
                              • 2011-12-08
                              • 2011-06-14
                              • 2020-09-24
                              • 2012-10-10
                              • 1970-01-01
                              相关资源
                              最近更新 更多