在 .NET 中使用 PBKDF2 和 HKDF 进行密码散列
Password hashing using PBKDF2 and HKDF in .NET
我的任务是编写一种计算密码哈希值的新方法,以取代我们认为还不够安全的旧方法。不久前,我阅读了 Security Driven .NET 一书,其中我了解到重要的部分是使用具有可配置旋转量的算法(而不是简单的哈希),而在 .NET 中推荐的算法是称为 PBKDF2
用于密码处理。我还读到,作为对 ASP.NET 如何处理密码的改进,如果通过使用 PBKDF2 创建的方式将存储在数据库中的结果哈希以加密方式绑定到用户(名称或 ID),那就太好了主密钥,然后使用用户名(或 ID)使用 HKDF 创建派生密钥。但同样,这是我从一本书上读到的肤浅知识,我目前还没有接触过,所以我无法重新检查我的记忆是否正确。
此外,我以前没有使用过 .NET DerivedBytes API,所以我可能做错了。所以我的问题是:我在下面的代码中做的事情对吗?我是否正确使用了 API?这个实现是 "sufficiently secure" 吗?还是我做错了什么,完全消除了所有的安全性?
protected override byte[] ComputeHash(string user, string salt, string password)
{
var userBytes = user.ToBytes();
using (var pbkdf2 = new PBKDF2(MacFactories.HMACSHA512, password.ToBytes(), salt.ToBytes()))
{
var masterKey = pbkdf2.GetBytes(128);
using (var hkdf = new HKDF(MacFactories.HMACSHA512, masterKey, userBytes, userBytes))
{
return hkdf.GetBytes(64);
}
}
}
你有正确的 idea/approach - 这是一个稍微好一点的实现:
byte[] ComputeHash(string user, string salt, string password)
{
using (var pbkdf2 = new PBKDF2(HMACFactories.HMACSHA512, password, salt.ToBytes()))
using (var hkdf = new HKDF(HMACFactories.HMACSHA512, pbkdf2.GetBytes(64), user.ToBytes()))
return hkdf.GetBytes(64);
}
您不应该向 pbkdf2
请求比底层 PRF 的字节长度更多的字节(在您的例子中,SHA512 产生 64 个字节)。
您可以将 hkdf
上下文保留为 null
,因为您似乎不需要它。
对于可能想知道上述代码使用哪个库的其他人 - Inferno crypto。
我的任务是编写一种计算密码哈希值的新方法,以取代我们认为还不够安全的旧方法。不久前,我阅读了 Security Driven .NET 一书,其中我了解到重要的部分是使用具有可配置旋转量的算法(而不是简单的哈希),而在 .NET 中推荐的算法是称为 PBKDF2
用于密码处理。我还读到,作为对 ASP.NET 如何处理密码的改进,如果通过使用 PBKDF2 创建的方式将存储在数据库中的结果哈希以加密方式绑定到用户(名称或 ID),那就太好了主密钥,然后使用用户名(或 ID)使用 HKDF 创建派生密钥。但同样,这是我从一本书上读到的肤浅知识,我目前还没有接触过,所以我无法重新检查我的记忆是否正确。
此外,我以前没有使用过 .NET DerivedBytes API,所以我可能做错了。所以我的问题是:我在下面的代码中做的事情对吗?我是否正确使用了 API?这个实现是 "sufficiently secure" 吗?还是我做错了什么,完全消除了所有的安全性?
protected override byte[] ComputeHash(string user, string salt, string password)
{
var userBytes = user.ToBytes();
using (var pbkdf2 = new PBKDF2(MacFactories.HMACSHA512, password.ToBytes(), salt.ToBytes()))
{
var masterKey = pbkdf2.GetBytes(128);
using (var hkdf = new HKDF(MacFactories.HMACSHA512, masterKey, userBytes, userBytes))
{
return hkdf.GetBytes(64);
}
}
}
你有正确的 idea/approach - 这是一个稍微好一点的实现:
byte[] ComputeHash(string user, string salt, string password)
{
using (var pbkdf2 = new PBKDF2(HMACFactories.HMACSHA512, password, salt.ToBytes()))
using (var hkdf = new HKDF(HMACFactories.HMACSHA512, pbkdf2.GetBytes(64), user.ToBytes()))
return hkdf.GetBytes(64);
}
您不应该向 pbkdf2
请求比底层 PRF 的字节长度更多的字节(在您的例子中,SHA512 产生 64 个字节)。
您可以将 hkdf
上下文保留为 null
,因为您似乎不需要它。
对于可能想知道上述代码使用哪个库的其他人 - Inferno crypto。