如何对密码进行哈希处理
我想在手机上存储密码的哈希值,但我不知道该怎么做。我似乎只能找到加密方法。应该如何正确地对密码进行哈希处理?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我想在手机上存储密码的哈希值,但我不知道该怎么做。我似乎只能找到加密方法。应该如何正确地对密码进行哈希处理?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(12)
考虑到今天(2012 年)的最佳实践,这里的大多数其他答案都有些过时了。
.NET 中原生可用的最强大的密码哈希算法是 PBKDF2,由
Rfc2898DeriveBytes
类表示。以下代码位于本文的独立类中: 如何存储加盐密码哈希的另一个示例。基础知识非常简单,因此这里进行了细分:
步骤 1 使用加密 PRNG 创建盐值:
步骤 2 创建 Rfc2898DeriveBytes 并获取哈希值:
< strong>STEP 3 将盐和密码字节组合起来供以后使用:
STEP 4 将组合的 salt+hash 转换为字符串进行存储
STEP 5 验证用户- 根据存储的密码输入密码
注意:根据特定应用程序的性能要求,可以减小值
100000
。最小值应约为10000
。Most of the other answers here are somewhat outdated considering today's (year 2012) best practices.
The most robust password-hashing algorithm that's natively available in .NET is PBKDF2, represented by the
Rfc2898DeriveBytes
class.The following code is in a stand-alone class in this post: Another example of how to store a salted password hash. The basics are really easy, so here it is broken down:
STEP 1 Create the salt value with a cryptographic PRNG:
STEP 2 Create the Rfc2898DeriveBytes and get the hash value:
STEP 3 Combine the salt and password bytes for later use:
STEP 4 Turn the combined salt+hash into a string for storage
STEP 5 Verify the user-entered password against a stored password
Note: Depending on the performance requirements of your specific application, the value
100000
can be reduced. A minimum value should be around10000
.基于 csharptest.net 的出色答案,我为此编写了一个类:
用法:
示例哈希可能是这样的
:您可以看到,我还在哈希中包含了迭代,以便于使用,并且如果我们需要升级,也可以升级它。
如果您对 .net core 感兴趣,我在 代码审查。
Based on csharptest.net's great answer, I have written a Class for this:
Usage:
A sample hash could be this:
As you can see, I also have included the iterations in the hash for easy usage and the possibility to upgrade this, if we need to upgrade.
If you are interested in .net core, I also have a .net core version on Code Review.
更新:这个答案已经严重过时了。请使用 https://stackoverflow.com/a/10402129 或 https://stackoverflow.com/a/73125177。
您可以使用
或
要获取
data
作为字节数组,您可以使用并从
md5data
或sha1data
获取字符串UPDATE: THIS ANSWER IS SERIOUSLY OUTDATED. Please use the recommendations from https://stackoverflow.com/a/10402129 or https://stackoverflow.com/a/73125177 instead.
You can either use
or
To get
data
as byte array you could useand to get back string from
md5data
orsha1data
2022 (.NET 6+) 解决方案:
这里的大多数其他答案都是几年前写的,因此没有利用新版本 .NET 中引入的许多最新功能。现在可以更简单地实现同样的事情,并且样板文件和噪音也少得多。我提出的解决方案还提供了额外的稳健性,允许您将来修改设置(例如迭代计数等),而无需实际破坏旧的哈希值(如果您使用 接受答案提出的解决方案)。
优点:
使用新的静态
Rfc2898DeriveBytes.Pbkdf2()
方法,无需每次实例化和处置对象。使用新的< code>RandomNumberGenerator 类及其静态
GetBytes
方法(在 .NET 6 中引入)用于生成盐。接受的答案中使用的 RNGCryptoServiceProvider 类 已过时。使用
CryptographicOperations.FixedTimeEquals
方法(在 .NET Core 2.1 中引入)用于比较Verify
方法中的关键字节,而不是像已接受的答案那样手动进行比较。除了消除大量嘈杂的样板之外,这还可以消除定时攻击。使用 SHA-256 而不是默认的 SHA-1 作为底层算法,只是为了安全起见,因为后者是一种更强大、更可靠的算法。
Hash
方法返回的字符串具有以下结构:[键]:[盐]:[迭代]:[算法]
这是该解决方案最重要的优点,这意味着我们基本上包含有关用于在最终字符串中创建哈希的配置的元数据。这允许我们将来更改哈希器类中的设置(例如迭代次数、salt/key 大小等),而不会破坏使用旧设置创建的先前哈希值。这是可接受的例如,答案不考虑在内,因为它依赖“当前”配置值来验证哈希值。
其他要点:
Convert.ToHexString
和Convert.FromHexString
更改为Convert.ToBase64
和Convert.FromBase64
分别。其余逻辑保持完全相同。代码:
用法:
2022 (.NET 6+) solution:
Most of the other answers here were written years ago and are therefore not taking advantage of many of the more recent features introduced in newer versions of .NET. The same thing can now be achieved much more simply and with a lot less boilerplate and noise. The solution I'm proposing also provides extra robustness by allowing you to modify the settings (e.g. iterations count, etc.) in the future without actually breaking old hashes (which is what would happen if you used the accepted answer's proposed solution, for example).
Pros:
Uses the new static
Rfc2898DeriveBytes.Pbkdf2()
method introduced in .NET 6, eliminating the need to instantiate and also dispose the object every single time.Uses the new
RandomNumberGenerator
class and its staticGetBytes
method — introduced in .NET 6 — to generate the salt. TheRNGCryptoServiceProvider
class used in the accepted answer is obsolete.Uses the
CryptographicOperations.FixedTimeEquals
method (introduced in .NET Core 2.1) for comparing the key bytes in theVerify
method, instead of doing the comparison by hand — like the accepted answer is doing. This, in addition to removing a lot of noisy boilerplate, also nullifies timing attacks.Uses SHA-256 instead of the default SHA-1 as the underlying algorithm, just to be on the safe side, as the latter is a more robust and reliable algorithm.
The returned string from the
Hash
method has the following structure:[key]:[salt]:[iterations]:[algorithm]
This is the most important advantage of this solution, it means we're basically including metadata about the configurations used to create the hash in the final string. This allows us to change the settings (such as the number of iterations, salt/key size, etc.) in our hasher class in the future without breaking previous hashes created with the old settings. This is something that the accepted answer, for example, doesn't take into account, as it's relying on the "current" configuration values to verify hashes.
Other points:
Convert.ToHexString
andConvert.FromHexString
toConvert.ToBase64
andConvert.FromBase64
respectively. The rest of the logic remains exactly the same.The code:
Usage:
@csharptest.net 和 Christian Gollhardt 的回答非常好,非常感谢。但是在生产环境中运行此代码并包含数百万条记录后,我发现存在内存泄漏。 RNGCryptoServiceProvider 和 Rfc2898DeriveBytes 类派生自 IDisposable,但我们不会处置它们。如果有人需要处置版本,我将写下我的解决方案作为答案。
用法:
@csharptest.net's and Christian Gollhardt's answers are great, thank you very much. But after running this code on production with millions of record, I discovered there is a memory leak. RNGCryptoServiceProvider and Rfc2898DeriveBytes classes are derived from IDisposable but we don't dispose of them. I will write my solution as an answer if someone needs with disposed version.
Usage:
在 ASP.NET Core 中,使用
PasswordHasher< ;TUser>
.<子>
• 命名空间:
Microsoft.AspNetCore.Identity
• 程序集:
Microsoft.Extensions.Identity.Core.dll
(NuGet |要对密码进行哈希处理,请使用
HashPassword()
:要验证密码,请使用
VerifyHashedPassword()
:优点:
PasswordHasherOptions< /代码>
)。
缺点:
In ASP.NET Core, use
PasswordHasher<TUser>
.• Namespace:
Microsoft.AspNetCore.Identity
• Assembly:
Microsoft.Extensions.Identity.Core.dll
(NuGet | Source)To hash a password, use
HashPassword()
:To verify a password, use
VerifyHashedPassword()
:Pros:
PasswordHasherOptions
).Cons:
我使用哈希值和盐值进行密码加密(与 Asp.Net Membership 使用的哈希值相同):
I use a hash and a salt for my password encryption (it's the same hash that Asp.Net Membership uses):
我认为使用 KeyDerivation.Pbkdf2 比 Rfc2898DeriveBytes 更好。
示例及解释:
ASP.NET Core 中的哈希密码
这是本文中的示例代码。这是最低的安全级别。
要增加它,我将使用 KeyDerivationPrf.HMACSHA1 参数代替
KeyDerivationPrf.HMACSHA256 或 KeyDerivationPrf.HMACSHA512。
不要在密码哈希方面妥协。有许多数学上合理的方法可以优化密码哈希黑客攻击。后果可能是灾难性的。
一旦犯罪分子能够获得您用户的密码哈希表,这将是相对的
如果算法较弱或实现不正确,他很容易破解密码。
他有很多时间(时间x计算机能力)来破解密码。密码散列应该具有很强的加密强度,才能“花很多时间”
“不合理的时间”。
还有一点,添加
哈希验证需要时间(而且这是好事)。
当用户输入错误的用户名时,不需要时间来检查用户名是否正确。
当用户名正确时,我们开始密码验证 - 这是一个相对较长的过程。
对于黑客来说,很容易了解用户是否存在。
当用户名错误时,请确保不要立即返回答案。
不用说:永远不要回答哪里出了问题。只是一般“凭据错误”。
I think using KeyDerivation.Pbkdf2 is better than Rfc2898DeriveBytes.
Example and explanation:
Hash passwords in ASP.NET Core
This is a sample code from the article. And it's a minimum security level.
To increase it I would use instead of KeyDerivationPrf.HMACSHA1 parameter
KeyDerivationPrf.HMACSHA256 or KeyDerivationPrf.HMACSHA512.
Don't compromise on password hashing. There are many mathematically sound methods to optimize password hash hacking. Consequences could be disastrous.
Once a malefactor can get his hands on password hash table of your users it would be relatively
easy for him to crack passwords given algorithm is weak or implementation is incorrect.
He has a lot of time (time x computer power) to crack passwords. Password hashing should be cryptographically strong to turn "a lot of time"
to "unreasonable amount of time".
One more point to add
Hash verification takes time (and it's good).
When user enters wrong user name it's takes no time to check that user name is incorrect.
When user name is correct we start password verification - it's relatively long process.
For a hacker it would be very easy to understand if user exists or doesn't.
Make sure not to return immediate answer when user name is wrong.
Needless to say : never give an answer what is wrong. Just general "Credentials are wrong".
首先使用下面的类生成盐。每个用户都需要有不同的盐,我们可以将其与其他用户属性一起保存在数据库中。 rounds 值决定密码被哈希的次数。
有关更多详细信息: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.-ctor?view=netcore-3.1#System_Security_Cryptography_Rfc2898DeriveBytes__ctor_System_Byte___System_Byte___System_Int32_
我们可以从控制台应用程序如下。我使用相同的盐对密码进行了两次哈希处理。
Use the below class to Generate a Salt first. Each user needs to have a different salt, we can save it in the database along with the other user properties. The rounds value decides the number of times the password will be hashed.
For more details: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.-ctor?view=netcore-3.1#System_Security_Cryptography_Rfc2898DeriveBytes__ctor_System_Byte___System_Byte___System_Int32_
We can call it from a console application as follows. I have hashed the password twice using the same salt.
这是使用 .NET 7.0 的示例
Here's an example using .NET 7.0