用Sha256哈希一个字符串

Nat*_*ten 136 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,与我的朋友php以及在线生成器(例如This generator)相比,此代码提供了显着不同的结果.

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

Quu*_*one 150

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字符的测试用例,例如é?,看看您的结果是否仍然匹配.如果没有,你将不得不弄清楚你的朋友正在使用什么编码; 它可能是在Unicode发明之前流行的8位"代码页"之一.(再次,我认为Windows是任何人仍然需要担心"代码页"的主要原因.)

  • @Elmue"您的评论不正确:UTF16是Unicode." 你错了."Unicode"是一种为字形分配数字(代码点)的标准.除了代理对,它没有说明如何将这些数字表示为字节.UTF16指定代码点< - >字节.Unicode指定字形< - >代码点. (4认同)
  • @Elmue,您可能会高兴地了解到"按UTF8编码的字节排序"和"按Unicode代码点排序"是等效的!(就像"通过UTF16编码的`short`s"排序一样,但*不是*"按UTF16编码的字节排序"除非您使用的是大端系统,而Windows不是.)但是,"排序"在Unicode中实际上是一个复杂的主题,应该保存一天. (3认同)
  • @Elmue对你错误的答案不那么自信.试试看; 你会感到惊讶 惊喜是令人愉快还是令人不愉快完全取决于你.:) (2认同)
  • @Elmue,"*如果你想进行不区分大小写的比较怎么办?*"如果你想做这种东西,你还需要转换UTF-16中的字节.它固定长度的事实并没有帮助. (2认同)
  • "不被其他人使用"是非常有趣的声明,因为Java内部处理字符串为UTF-16也... (2认同)
  • @Elmue UTF-16没有固定宽度的字符.大多数字符是两个字节,但不是全部 - 有些需要4个字节来编码,例如,某些罕见的中文/日文/韩文字符.UCS-2是真正的固定宽度,但Windows自Windows 2000以来一直使用UTF-16.此外,由于分割在多个代码平面上,在排序包含稀有字符的中文时可能会有惊喜; 即使没有这些字符,你想要哪种排序方法?中文有不止一个逻辑顺序. (2认同)

Nic*_*dum 99

我也遇到了另一种实现方式的问题,但是我忘记了自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;
}
Run Code Online (Sandbox Code Playgroud)

当我输入类似的东西时abcdefghi2013,它会给出不同的结果并导致我的登录模块出错.然后我试图修改代码由Quuxplusone建议,改变了从编码以同样的方式ASCIIUTF8那么它终于成功了!

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();
}
Run Code Online (Sandbox Code Playgroud)

再次感谢Quuxplusone的精彩和详细解答!:)


Ami*_*adi 19

新的 .NET 5+ 解决方案:

\n

如果您使用 .NET 5 或更高版本,现在只需3 行代码即可实现此目的。

\n
string QuickHash(string input)\n{\n    var inputBytes = Encoding.UTF8.GetBytes(input);\n    var inputHash = SHA256.HashData(inputBytes);\n    return Convert.ToHexString(inputHash);\n}\n\nstring hash = QuickHash("...");\n
Run Code Online (Sandbox Code Playgroud)\n

上面的代码:

\n
    \n
  • HashData在类上使用新的静态方法SHA256以避免实例化并每次都必须处理新实例。
  • \n
  • 使用新Convert.ToHexString方法将哈希字节数组转换为十六进制字符串;消除使用字符串生成器等的麻烦。
  • \n
  • 使用新SHA256类而不是旧的(现已过时)SHA256Managed类。
  • \n
  • 使用 UTF-8 编码将输入字符串转换为字节数组,这是接受的答案推荐的。
  • \n
\n

注意:您不应该使用此方法对用户密码进行哈希处理。即使添加盐,通用哈希函数(例如 SHA-256)也不再适合用于密码。这对于散列您知道具有高熵的字符串非常有用,例如随机生成的长会话令牌等。为了存储密码,您必须考虑专门为此目的设计的较慢的哈希函数,例如 Bcrypt、Scrypt 或 PBKDF2(后者在 .NET \xe2\x80\x94 中本地可用,请参阅

\n


Aut*_*uto 11

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

你得到不同结果的原因是因为你没有使用相同的字符串编码。您为计算 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/


vit*_*ira 7

我正在寻找并测试这些答案,Visual Studio 向我展示了 SHA256Managed 现在已过时(此处

因此,我使用 SHA256 类来代替:

Encoding enc = Encoding.UTF8;
var hashBuilder = new StringBuilder();
using var hash = SHA256.Create();
byte[] result = hash.ComputeHash(enc.GetBytes(yourStringToHash));
foreach (var b in result)
    hashBuilder.Append(b.ToString("x2"));
string result = hashBuilder.ToString();
Run Code Online (Sandbox Code Playgroud)


Rac*_*hel 5

在 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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 我不会使用 `ASCII` 而是使用 `byte[] arrBytes = System.Text.Encoding.UTF8.GetBytes(strData)`。 (5认同)

ARC*_*ARC 5

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));
            }
        }
Run Code Online (Sandbox Code Playgroud)


Erç*_*ğlu 5

有史以来最短和最快的方式。只有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);
Run Code Online (Sandbox Code Playgroud)