PBKDF2 不在 C# 中返回明文和散列期望值
PBKDF2 is not returning plaintext and hashed expected value in C#
我正在尝试在 C# 中使用 PBKDF2 创建密码,然后我正在尝试检索该密码。
var masterPwd = "masterPassword";
var service = "www.google.com";
byte[] salt = CreateSalt(16);
var encodedPwd = CreateMasterPassword(masterPwd, salt);
var decoded = CreateMasterPassword(encodedPwd, salt);
定义了以下函数:
public static byte[] CreateSalt(int size)
{
var salt = new byte[size];
using (var random = new RNGCryptoServiceProvider())
{
random.GetNonZeroBytes(salt);
}
return salt;
}
public static string CreateMasterPassword(string password, byte[] salt)
{
string PassHash = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return PassHash;
}
这样的话,decoded不应该和masterPwd一样吗?
我认为您对 PBKDF2 的作用有些误解。它不是一个你可以恢复明文数据的加密函数(让我们把蛮力放在一边,因为它不是 'intended use')。相反,它是一种 "slow" 哈希机制,通常被描述为 "one way".
PBKDF2是密钥推导函数,但也用于存储密码。这是 PBKDF2 用于密码存储时的典型流程。
- 用户创建了一个带有密码的网站帐户。该站点生成一个随机盐,然后将 PBKD2 应用于带有盐的密码,并存储结果和盐。盐以纯文本形式存储。
- 当用户需要再次登录时,站点要求输入用户名和密码。它查找该用户的盐,然后将 PBKDF2 重新应用到用户输入的密码。
- 它将存储的哈希值与用户输入的哈希值进行比较。如果哈希值相等,则网站知道他们输入的密码正确。
这种方法意味着网站不会以它可能知道的方式存储密码。这允许网站否认知道密码。
如果那是你想要做的,那么你应该如何使用它。
如果您确实需要一种方法来拥有 "two way" 算法,那么这就是从散列到加密。在这个地方将使用对称算法,解决密钥和 IV 管理的所有麻烦问题。您很可能想看一下构建在对称密码(如 libsodium)之上的高度抽象。
libsodium 是一个很好的抽象,建立在原语之上,可以消除猜测如何使用它们的工作。如果提供简单的API,如"encrypt this thing with this password",它能正确地从密码中导出加密密钥,对加密进行某种形式的认证,并受到信息安全专家的好评。
我正在尝试在 C# 中使用 PBKDF2 创建密码,然后我正在尝试检索该密码。
var masterPwd = "masterPassword";
var service = "www.google.com";
byte[] salt = CreateSalt(16);
var encodedPwd = CreateMasterPassword(masterPwd, salt);
var decoded = CreateMasterPassword(encodedPwd, salt);
定义了以下函数:
public static byte[] CreateSalt(int size)
{
var salt = new byte[size];
using (var random = new RNGCryptoServiceProvider())
{
random.GetNonZeroBytes(salt);
}
return salt;
}
public static string CreateMasterPassword(string password, byte[] salt)
{
string PassHash = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: password,
salt: salt,
prf: KeyDerivationPrf.HMACSHA256,
iterationCount: 10000,
numBytesRequested: 256 / 8));
return PassHash;
}
这样的话,decoded不应该和masterPwd一样吗?
我认为您对 PBKDF2 的作用有些误解。它不是一个你可以恢复明文数据的加密函数(让我们把蛮力放在一边,因为它不是 'intended use')。相反,它是一种 "slow" 哈希机制,通常被描述为 "one way".
PBKDF2是密钥推导函数,但也用于存储密码。这是 PBKDF2 用于密码存储时的典型流程。
- 用户创建了一个带有密码的网站帐户。该站点生成一个随机盐,然后将 PBKD2 应用于带有盐的密码,并存储结果和盐。盐以纯文本形式存储。
- 当用户需要再次登录时,站点要求输入用户名和密码。它查找该用户的盐,然后将 PBKDF2 重新应用到用户输入的密码。
- 它将存储的哈希值与用户输入的哈希值进行比较。如果哈希值相等,则网站知道他们输入的密码正确。
这种方法意味着网站不会以它可能知道的方式存储密码。这允许网站否认知道密码。
如果那是你想要做的,那么你应该如何使用它。
如果您确实需要一种方法来拥有 "two way" 算法,那么这就是从散列到加密。在这个地方将使用对称算法,解决密钥和 IV 管理的所有麻烦问题。您很可能想看一下构建在对称密码(如 libsodium)之上的高度抽象。
libsodium 是一个很好的抽象,建立在原语之上,可以消除猜测如何使用它们的工作。如果提供简单的API,如"encrypt this thing with this password",它能正确地从密码中导出加密密钥,对加密进行某种形式的认证,并受到信息安全专家的好评。