使用 ASP.NET 的 Crypto 类进行密码哈希处理






4.60/5 (28投票s)
本文概述了 ASP.NET Crypto 类中密码的哈希处理过程。
引言
本文将介绍密码学概念以及 ASP.NET 中用于简化编码的命名空间和类,以便快速完成加密,并且代码更短。
背景
密码学和保护数据一直是所有计算机程序员和爱好者关注的重点。这使得他们能够保护服务器并防止任何未经授权的数据访问。通常,黑客会尝试通过使用用户的密码登录来获取用户账户数据的访问权限。这就是为什么始终建议首先加密用户账户的密码和其他敏感信息,然后再将其存储到数据库中,因为类似 SQL 注入的方法可以轻松揭示数据库中存储的数据,黑客可能会因此获取其中存储的信息。
密码学
密码学是一种用于保护敏感信息和数据免遭其他可能出于非法活动目的使用这些数据的各方的方法。
ASP.NET 中的密码学
ASP.NET 是一种服务器端编程语言,它提供了许多基于 .NET 框架构建的新命名空间,使程序员能够轻松地专注于网站的 UI 和 UX,而不是网站运行的核心功能和流程。
ASP.NET 团队在 Web Pages 框架的 System.Web.Helpers
命名空间中提供了一个名为 Crypto
的新类。
哈希和 Crypto 技术
值得注意的是,需要解释什么是哈希以及如何使用它来保存密码。
哈希是一个将密码(从人类可理解的形式)转换为不可理解的 `string` 形式的过程。该 `string` 既不能直接也不能间接被人理解。哈希用于在任何意义上更改密码,以便任何有权查看数据库中数据的人都无法获得密码以用于任何目的使用用户的帐户。
加盐 (Salting) 是另一种使哈希过程更快的技术。盐仅仅是一串额外的字符,您在哈希过程开始之前将其添加到输入中。这将产生一个更强的哈希结果,并且返回的 `string` 将比以前更强。但是,加盐需要您保存哈希密码时使用的盐,因为盐无法重新生成。
同样值得注意的是,一旦哈希,`string` 就无法转换回哈希时输入的原始 `string`。
加盐只是一个额外的层,将添加到密码中。如下图所示,加盐后的密码与发送的密码不同。它在其上添加了额外的字符。它通过为不同用户存储相同密码的不同哈希值来发挥作用。例如,在下图中,两个相同的用户使用相同的密码“bob”,但他们的盐(在注册时生成)不同,因此他们相同的密码以不同的方式保存。
加盐用于尽量减少因黑客尝试英文拼写的所有可能的排列组合而导致的任何错误或黑客攻击问题。
使用 Crypto 类
Crypto 类包含了 .NET 编程中可用的密码学的简化版本,并且这些方法足够简单,任何 Web 开发人员都可以轻松地在他们的 Web 应用程序中保护密码。
该类是一个 `static` 类,这意味着您无法创建该类的实例。
使用方法
`Crypto` 类公开了以下方法,用于在 ASP.NET 哈希处理过程中进行工作。
string GenerateSalt()
此方法生成一个新的 Salt,在哈希处理开始前添加到输入 `string` 中。此 `string` 需要保存,因为生成完全匹配的 Salt 几乎是不可能的。
string Hash()
此函数使用默认的 (SHA-256) 算法哈希输入的 `string`,或者用户可以为 ASP.NET 指定要使用的算法来哈希密码。
string HashPassword()
此函数返回用户传入的输入的 `string` 的 RFC 2898 哈希值。
string SHA1()
返回提供的 `string` 的 SHA1 哈希值。
string SHA256()
与上面相同,但使用的算法是 SHA-256。
bool VerifyHashedPassword()
开发人员可以在用户身份验证时使用此方法。因为此方法会检查用户发送的密码。用户对应的 Salt 将存储在数据库中,该 Salt 将被添加到用户提供的 `Password string` 中,然后进行哈希处理,生成哈希值。如果数据库中的哈希值与用户的哈希值匹配,则返回 `true`。
在网站中使用
您可以直接在您的 Web Pages 应用程序中使用这些函数,因为 Web Pages 应用程序已经包含了 `System.Web.Helpers` 命名空间;Crypto 在 .cshtml 文件中可用。
您可以使用我附加到此提示的 ASP.NET 示例网站来测试该类,或者阅读此提示来理解这个概念。网站的 HTML 标记可以更改为这样:
<form method="post">
<p>Write the string as a password that would be encrypted using
<span style="color: #0094ff;
font-family: Consolas;">Crypto</span> class of ASP.NET Web Pages.</p>
<input type="password" name="password" autofocus />
<input type="submit" value="Submit" />
</form>
<div>
<p>Password: @password</p>
<p>MD5 Hashed result: @hashed</p>
<p>SHA256 result: @sha256</p>
<p>SHA1 result: @sha1</p>
<p>Salt: @salt</p>
<p>HashedPassword: @hashedPassword</p>
<p>Verify: @verify.ToString()</p>
</div>
注意:上面的 HTML 使用 Razor 脚本将服务器中的变量数据输入到 HTML 标记中。
服务器端代码现在将如下所示:
// Create the variables...
// Remember: This password is just being shown to show the actual text being passed,
// In real applications you shouldn't show the password to the User.
var password = "";
var hashed = "";
var sha256 = "";
var sha1 = "";
var salt = "";
var hashedPassword = "";
var verify = false;
// If the request is a POST request, then
if (IsPost)
{
// Get the password
password = Request.Form["password"];
// Run the functions on the code,
hashed = Crypto.Hash(password, "MD5");
sha256 = Crypto.SHA256(password);
sha1 = Crypto.SHA1(password);
salt = Crypto.GenerateSalt();
hashedPassword = Crypto.HashPassword(password);
// First parameter is the previously hashed string using a Salt
verify = Crypto.VerifyHashedPassword("{hash_password_here}", password);
}
如何使用 Salt
我不小心忘记了展示如何在密码哈希中使用 Salt,感谢 Waqas 的评论,以便我也可以提及这部分。实际上,Salt 只是一个随机字符串,它被附加(或前置)到密码字符串。Salt 的使用和需求是为了克服彩虹表攻击和字典攻击的问题。Salt 是一个字典攻击或彩虹表可能没有的随机字符串。
在代码中,它将是这样的:
hashedPassword = Crypto.HashPassword(salt + password); // prepending the salt
个人建议:始终为每个用户和他们的每个密码生成一个新的 Salt。使用相同的 Salt 会使攻击者更容易确定正在附加或前置的字符串。将其设置为真正的随机性将解决这个问题。即使攻击者获得了其中一个账户的 Salt,由于随机 Salt 的存在,他们也永远无法获取其他密码。
虽然使用他们电子邮件的前几个字符可能看起来有效。但这样做既不强大也不安全。
Crypto.Hash 方法
`Crypto.Hash()` 方法可以接受两个参数,一个参数是您用于哈希的 `string`,第二个参数是使用的算法。在本文中,我使用了 MD5 算法;默认是 SHA-256。我使用了 MD5,因为 Crypto 的其他代码不会使用 MD5 算法哈希密码。它是一种不安全的算法,很容易被破解并转换回人类可读的正确密码;即原始密码。
您应该始终使用 SHA-256 算法或 SHA-1 而不是 MD5。
Crypto.HashPassword 方法
此方法是您在 ASP.NET 应用程序中哈希密码的主要且推荐的方法。您将密码作为参数传递,函数会对其进行哈希处理。根据此方法的 MSDN 文档,其注意事项如下:
引用密码哈希使用 RFC 2898 算法生成,使用 128 位 Salt、256 位子密钥和 1000 次迭代。生成的哈希字节流的格式是 {0x00, salt, subkey},在返回之前会进行 base-64 编码。
这使得密码哈希非常强大,并且 `Crypto.VerifyHashedPassword()` 可以轻松验证密码是否正确或错误。
运行应用程序进行测试
运行网页,输入密码“CodeProject
”,您将看到以下网页。
请注意,在 Verify 前面有一个“False
”,这是因为我们没有传递正确的 Hash 代码来检查 CodeProject 密码。让我们将结果中的哈希密码粘贴到 Visual Studio(或您使用的任何 IDE)的源代码中。复制 `HashedPassword` 前面的文本,并粘贴到返回 `VerifyHashedPassword` 的函数中,如下所示:
verify = Crypto.VerifyHashedPassword("{here}", password);
完成后,再次提交密码,“CodeProject
”;这次再次提交相同的密码。
您将看到这次它没有报错。尽管您会注意到哈希密码 `string` 发生了变化。这使我们能够检查密码,即使以不同的方式保存相同的密码。
是的,对字母大小写有安全性;小写或大写。您可以尝试将密码写成小写“codeproject
”并查看这次它不会验证密码。
这对于保存密码并再次验证它们以进行用户身份验证非常有用。ASP.NET 团队在使整个过程非常简单易懂方面付出了很多努力,以便新开发人员可以专注于 Web 应用程序的 UX,只需编写一行代码即可生成和保存哈希密码以提高安全性。
关注点
基于 MD5 的算法很容易被破解,而基于 SHA-1 或 SHA-256 的算法更强大,不容易被破解。ASP.NET 拥有强大的命名空间和类集,可以在 Web 应用程序编程中使用,这使得程序员可以专注于 UX 而不是后端编码来创建 Salt 等等。
添加 Salt 使哈希密码更难被破解。
一旦哈希,就无法转换回原样。
历史
- 帖子第一版