c#中的哈希字符串

Posted

技术标签:

【中文标题】c#中的哈希字符串【英文标题】:Hash string in c# 【发布时间】:2011-04-28 09:38:32 【问题描述】:

我在尝试获取 c# 中的哈希字符串时遇到问题。

我已经尝试了几个网站,但大多数都使用文件来获取哈希值。其他用于字符串的有点太复杂了。我找到了这样的网络 Windows 身份验证示例:

FormsAuthentication.HashPasswordForStoringInConfigFile(tbxPassword.Text.Trim(), "md5")

我需要使用散列来使包含文件名的字符串更安全。我该怎么做?

例子:

string file  = "username";
string hash = ??????(username); 

我应该使用另一种哈希算法而不是“md5”吗?

【问题讨论】:

【参考方案1】:
using System.Security.Cryptography;

public static byte[] GetHash(string inputString)

    using (HashAlgorithm algorithm = SHA256.Create())
        return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));


public static string GetHashString(string inputString)

    StringBuilder sb = new StringBuilder();
    foreach (byte b in GetHash(inputString))
        sb.Append(b.ToString("X2"));

    return sb.ToString();

补充说明

由于 MD5 和 SHA1 是obsolete and insecure 算法,本方案使用 SHA256。或者,您可以使用 cmets 中指出的 BCrypt 或 Scrypt。 此外,请考虑“salting”您的哈希值并使用经过验证的加密算法,如 cmets 中所指出的那样。

【讨论】:

不要使用 MD5 或 SHA1,它们是过时且不安全的算法。至少使用 SHA256,甚至更好地使用 BCrypt 或 Scrypt。 查看使用 SCrypt 的示例:***.com/questions/20042977/… @Muh 它可以很容易地用于校验和,因为它比 SHA512 快得多。但确实要存储密码,不推荐,对。 b.ToString("X2") 是什么意思? 仅供参考,如果您使用散列作为加密散列,则使用MD5或SHA1是完全合法的,例如作为内容的哈希值进行比较。 MD5 的优势(例如)是计算速度,它们不安全的事实是无关紧要的。【参考方案2】:

获取用于密码存储目的的哈希字符串的最快方法是以下代码:

    internal static string GetStringSha256Hash(string text)
    
        if (String.IsNullOrEmpty(text))
            return String.Empty;

        using (var sha = new System.Security.Cryptography.SHA256Managed())
        
            byte[] textData = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] hash = sha.ComputeHash(textData);
            return BitConverter.ToString(hash).Replace("-", String.Empty);
        
    

备注:

如果经常调用该方法,则sha变量的创建应重构为类字段; 输出显示为编码的十六进制字符串;

【讨论】:

SHA1Managed 类不是很昂贵。它消耗大约 130 个字节并将它们初始化为某个静态值,但仅此而已。所以在大多数情况下应该不存在性能问题。 另外SHA1ManagedIDisposable,因此需要将其用法包装到using 块中。 Dispose 方法的目的是清除内部缓冲区。否则将面临内存攻击的风险。 @MuhammadRehanSaeed 当我说SHA1Managed 并不昂贵时,我的意思是它的创建不是。此外,散列算法不一定成本很高。当你想找到碰撞时,它只需要(非常)昂贵。 @King_Fisher - 这是不可能的!哈希是单向函数,信息丢失。如果需要解密,则需要使用加密方法而不是散列。顺便说一句,加密密码是一种不好的做法。【参考方案3】:

我不太了解您问题的全部范围,但如果您只需要字符串的哈希值,那么很容易得到。

只需使用 GetHashCode 方法即可。

像这样:

string hash = username.GetHashCode();

【讨论】:

是的,它正在寻找什么。但它的代码是个大错误。显示 write like int hash = "username".GetHasCode(); 为什么要把用户名放在双引号中?这将得到单词“用户名”的哈希值,现在是用户名变量中的内容。 不要存储来自 GetHashCode 的值,32x 和 64x 是不同的 这是一种创建密码哈希的不好方法。使用 GetHashCode() 您不能假设不同计算机会生成相同的数字。使用 Sha1 哈希方法什么的(我稍后会发布一个示例) 需要注意的是GetHashCode不是一个加密安全的散列算法。至少使用 SHA256,甚至更好地使用 BCrypt 或 Scrypt 作为安全算法。【参考方案4】:

我认为您要寻找的不是散列,而是加密。使用散列,您将无法从“散列”变量中检索原始文件名。有了加密就可以了,而且很安全。

有关 .NET 加密的更多信息,请参阅 AES in ASP.NET with VB.NET。

【讨论】:

是的,我认为是加密,但我只想比较结果哈希。重定向页面后。 您想将散列文件名与什么进行比较?【参考方案5】:

如果性能不是主要问题,您也可以使用以下任何一种方法: (如果您希望哈希字符串为大写,请将"x2" 替换为"X2"。)

public static string SHA256ToString(string s) 

    using (var alg = SHA256.Create())
        return string.Join(null, alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Select(x => x.ToString("x2")));

或:

public static string SHA256ToString(string s)
            
    using (var alg = SHA256.Create())
        return alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Aggregate(new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();

【讨论】:

【参考方案6】:

有史以来最短、最快的方式。只有 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);

【讨论】:

另一个使用 StringBuilder 和 Linq 的 1 行版本 public static string Hash(string value) => string.IsNullOrEmpty(value) ?值:SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(value)).Aggregate(new StringBuilder(), (sb, b) => sb.Append(b.ToString("X2"))).ToString ();【参考方案7】:
//Secure & Encrypte Data
    public static string HashSHA1(string value)
    
        var sha1 = SHA1.Create();
        var inputBytes = Encoding.ASCII.GetBytes(value);
        var hash = sha1.ComputeHash(inputBytes);
        var sb = new StringBuilder();
        for (var i = 0; i < hash.Length; i++)
        
            sb.Append(hash[i].ToString("X2"));
        
        return sb.ToString();
    

【讨论】:

请勿使用此链接中的 SHA1,SHA1 是一种过时且不安全的算法。至少使用 SHA256,甚至更好地使用 BCrypt 或 Scrypt。 查看使用 SCrypt 的示例:***.com/questions/20042977/…【参考方案8】:

这里的所有哈希代码示例都已过时。在 .NET 5 中,为我们提供了一种新的哈希数据方法,它速度翻倍,并且内存分配为零。那不是很酷吗?您只需要在您最喜欢的哈希算法类上使用新的静态HashData(byte[])

byte[] buffer = Encoding.UTF8.GetBytes(input);
byte[] digest = SHA256.HashData(buffer);

Microsoft 有一个 new rule in its analyzer 来检测旧的用法并用新的 API 替换它们。

【讨论】:

安全散列的整个要点,例如密码,是它需要缓慢地产生散列。这就是提供防御暴力破解的方法。如果您使用计算速度快的散列算法,那么破解它会容易得多 @Servy 你的观点是正确的,但与我的帖子完全无关。 这根本不是无关的。因为速度超快而提出解决方案意味着提出一个必然不安全的解决方案,因为速度慢是其安全性的关键组成部分。 @Servy 计算时间取决于您选择的算法。散列算法的传统实现在 CPU 和内存方面性能不佳。这意味着在正常情况下,它们会不必要地给您的服务器增加更多负载。如果您想要安全,您仍然需要明智地选择算法,但这并不意味着您应该选择实施不佳的遗留 API。

以上是关于c#中的哈希字符串的主要内容,如果未能解决你的问题,请参考以下文章

C#上位机开发(十五)—— 计算字符串哈希值和文件哈希值

Redis在C#中的使用及Redis的封装

帮助在 C# 中包含字符串数组的哈希表

C#多维数组,ArrayList,还是哈希表?

C# 存储数字的安全方式?

什么方法可以在c#中将Hash改回它的字符串