[英]Generated sha1 key in PBKDF2 Python do not match in .NET Rfc2898
我有一個 python 代碼,它使用hashlib.pbkdf2_hmac
方法生成密碼的 PBKDF2 sha1 hash。 然后我在dotnet framework 4.5
程序中使用該密碼摘要來驗證它是否與相同的密碼。 C# 程序返回 false,這表明從 python 程序生成的 hash 不正確。
密鑰采用以下格式: #iterations|salt|key
。 然后,我使用該密鑰並嘗試使用 dotnet 框架應用程序使用 via 方法對其進行驗證:
public static bool IsValid(string testPassword, string originalDelimitedHash)
{
//extract original values from delimited hash text
var originalHashParts = originalDelimitedHash.Split('|');
var origIterations = Int32.Parse(originalHashParts[0]);
var origSalt = Convert.FromBase64String(originalHashParts[1]);
var originalHash = originalHashParts[2];
//generate hash from test password and original salt and iterations
var pbkdf2 = new Rfc2898DeriveBytes(testPassword, origSalt, origIterations, HashAlgorithmName.SHA1);
byte[] testHash = pbkdf2.GetBytes(20);
var hashStr = Convert.ToBase64String(testHash);
if (hashStr == originalHash)
return true;
return false;
}
我的 python 程序:
from hashlib import pbkdf2_hmac
from base64 import b64encode
from os import urandom
def generate_password_hash(password:string):
encodedPass = password.encode('utf8')
random_bytes = urandom(20)
salt = b64encode(random_bytes)
iterations = 5000
key = pbkdf2_hmac('sha1', encodedPass, salt, iterations, dklen=20)
result = f'{iterations}|{salt.decode("utf-8")}|{binascii.hexlify(key).decode("utf-8")}'
return result
因此,如果我的密碼是hDHzJnMg0O
,則上述python
方法的結果摘要將類似於5000|J5avBy0q5p9R/6cgxUpu6+6sW7o=|2445594504c9ffb54d1f11bbd0b385e3e37a5aca
因此,如果我將其提供給我的 C# IsValid
方法(見下文),它將返回false
,這意味着密碼不匹配
static void Main(string[] args)
{
var pass = "hDHzJnMg0O";
var hash = "5000|J5avBy0q5p9R/6cgxUpu6+6sW7o=|2445594504c9ffb54d1f11bbd0b385e3e37a5aca";
var isValid = IsValid(pass, hash); // returns False
}
Python 代碼:
b64encode(random_bytes)
作為 PBKDF2 調用的鹽。 這是相當不尋常的(但不是錯誤)。 通常,原始數據(即random_bytes
)作為鹽應用並傳遞給 PBKDF2 調用。 使用 Base64 編碼只會創建字符串。C# 代碼在這些方面有所不同,並且:
random_bytes
)進行 PBKDF2 調用,即來自 Python 端的鹽被 Base64 解碼。Changes in the C# code for compatibility with the Python code (of course the changes could also be made in the Python code, but the Python code seems to be the reference):
...
var origSalt = Encoding.UTF8.GetBytes(originalHashParts[1]); // Convert.FromBase64String(originalHashParts[1]);
...
var hashStr = Convert.ToHexString(testHash); // Convert.ToBase64String(testHash);
...
對於后者,使用了Convert.ToHexString()
,它從 .NET 5 開始可用。對於其他 .NET 版本,請參見此處的示例。
此外,由於比較了十六進制編碼的值,並且不同的實現在小寫字母(例如binascii.hexlify(key)
)和大寫字母(例如Convert.ToHexString(testHash)
)方面沒有標准化,因此統一轉換兩個字符串更加穩健,例如:
if (hashStr.ToUpper() == originalHash.ToUpper())
return true;
通過這些更改,可以使用 C# 代碼進行驗證。
編輯(關於評論中提到的 Python 代碼的更改):
If in the Python code random_bytes
is used as salt and the salt is Base64 encoded for concatenation, then in the C# code the Base64 encoded salt must be Base64 decoded again (as in the original C# code).
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.