用Sha256哈希一个字符串

时间:2012-09-13 23:32:24

标签: c# string hash sha256

我尝试使用SHA256散列字符串,我使用以下代码:

using System;
using System.Security.Cryptography;
using System.Text;
 public class Hash
    {
    public static string getHashSha256(string text)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(text);
        SHA256Managed hashstring = new SHA256Managed();
        byte[] hash = hashstring.ComputeHash(bytes);
        string hashString = string.Empty;
        foreach (byte x in hash)
        {
            hashString += String.Format("{0:x2}", x);
        }
        return hashString;
    }
}

但是,与我的朋友php以及在线生成器(例如This generator

相比,此代码会产生显着不同的结果

有谁知道错误是什么?不同的基础?

7 个答案:

答案 0 :(得分:144)

Encoding.Unicode是微软对UTF-16的误导性名称(双宽编码,由于历史原因在Windows世界中使用但未被其他任何人使用)。 http://msdn.microsoft.com/en-us/library/system.text.encoding.unicode.aspx

如果你检查bytes数组,你会发现每隔一个字节都是0x00(因为双宽编码)。

您应该使用Encoding.UTF8.GetBytes代替。

但是,根据您是否认为终止'\0'字节是您正在散列的数据的一部分,您将看到不同的结果。散列两个字节"Hi"将得到与散列三个字节"Hi"不同的结果。你必须决定你想做什么。 (据推测,你想要做你朋友的PHP代码所做的任何事情。)

对于ASCII文本,Encoding.UTF8肯定是合适的。如果您的目标是完美与您朋友的代码兼容,即使在非ASCII输入上,您最好还是尝试使用非{ASCII}字符的一些测试用例,例如é和{ {1}}并查看您的结果是否仍然匹配。如果没有,你将不得不弄清楚你的朋友正在使用什么编码;它可能是在Unicode发明之前流行的8位“代码页”之一。 (同样,我认为Windows是任何人仍然需要担心“代码页”的主要原因。)

答案 1 :(得分:91)

我还遇到了另一种实施方式的问题,但我忘记了自2年前以来我在哪里获得它。

static string sha256(string randomString)
{
    var crypt = new SHA256Managed();
    string hash = String.Empty;
    byte[] crypto = crypt.ComputeHash(Encoding.ASCII.GetBytes(randomString));
    foreach (byte theByte in crypto)
    {
        hash += theByte.ToString("x2");
    }
    return hash;
}

当我因某种原因输入类似abcdefghi2013的内容时,它会给出不同的结果并导致我的登录模块出错。 然后我尝试以与Quuxplusone建议相同的方式修改代码,并将编码从ASCII更改为UTF8,然后它终于有效了!

static string sha256(string randomString)
{
    var crypt = new System.Security.Cryptography.SHA256Managed();
    var hash = new System.Text.StringBuilder();
    byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
    foreach (byte theByte in crypto)
    {
        hash.Append(theByte.ToString("x2"));
    }
    return hash.ToString();
}

再次感谢Quuxplusone精彩而详细的回答! :)

答案 2 :(得分:4)

在PHP版本中,您可以发送' true'在最后一个参数中,但默认为' false'。传递' sha256'以下算法相当于默认的PHP哈希函数。作为第一个参数:

public static string GetSha256FromString(string strData)
    {
        var message = Encoding.ASCII.GetBytes(strData);
        SHA256Managed hashString = new SHA256Managed();
        string hex = "";

        var hashValue = hashString.ComputeHash(message);
        foreach (byte x in hashValue)
        {
            hex += String.Format("{0:x2}", x);
        }
        return hex;
    }

答案 3 :(得分:2)

有史以来最短,最快的方法。只有1行!

public static string StringSha256Hash(string text) =>
    string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);

答案 4 :(得分:1)

public string EncryptPassword(string password, string saltorusername)
        {
            using (var sha256 = SHA256.Create())
            {
                var saltedPassword = string.Format("{0}{1}", salt, password);
                byte[] saltedPasswordAsBytes = Encoding.UTF8.GetBytes(saltedPassword);
                return Convert.ToBase64String(sha256.ComputeHash(saltedPasswordAsBytes));
            }
        }

答案 5 :(得分:1)

public static string ComputeSHA256Hash(string text)
{
    using (var sha256 = new SHA256Managed())
    {
        return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(text))).Replace("-", "");
    }                
}

之所以得到不同的结果,是因为您没有使用相同的字符串编码。您为计算SHA256的在线网站放置的链接使用UTF8编码,而在您的示例中,您使用Unicode编码。它们是两种不同的编码,因此您不会得到相同的结果。在上面的示例中,您将获得链接网站的相同SHA256哈希。您还需要在PHP中使用相同的编码。

每个软件开发人员绝对,肯定必须了解Unicode和字符集的绝对最低要求(无借口!)

https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/

答案 6 :(得分:-2)

在.NET Core 3.1中对我有用。
但是不在.NET 5预览版7中。

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

namespace PortalAplicaciones.Shared.Models
{
    public class Encriptar
    {
        public static string EncriptaPassWord(string Password)
        {
            try
            {
                SHA256Managed hasher = new SHA256Managed();

                byte[] pwdBytes = new UTF8Encoding().GetBytes(Password);
                byte[] keyBytes = hasher.ComputeHash(pwdBytes);

                hasher.Dispose();
                return Convert.ToBase64String(keyBytes);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }  
    }
}