首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成的sha1键在.NET Rfc2898中与.NET Rfc2898不匹配

生成的sha1键在.NET Rfc2898中与.NET Rfc2898不匹配
EN

Stack Overflow用户
提问于 2022-07-28 10:31:15
回答 1查看 198关注 0票数 1

我有一个python代码,它使用PBKDF2方法生成密码的sha1散列。然后,我在一个dotnet framework 4.5程序中使用这个密码摘要来根据相同的密码验证它。C#程序返回false,这意味着从python程序生成的散列是不正确的。

关键是这种格式:#iterations|salt|key。然后,我接受这个密钥,并尝试使用一个使用via方法的dotnet框架应用程序来验证它:

代码语言:javascript
复制
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程序:

代码语言:javascript
复制
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,这意味着密码不匹配

代码语言:javascript
复制
static void Main(string[] args)
{
    var pass = "hDHzJnMg0O";

    var hash = "5000|J5avBy0q5p9R/6cgxUpu6+6sW7o=|2445594504c9ffb54d1f11bbd0b385e3e37a5aca";
    var isValid = IsValid(pass, hash); // returns False
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-28 17:10:31

Python代码:

  • 使用b64encode(random_bytes)作为PBKDF2调用的salt。这是相当不寻常的(但不是一个bug)。通常,原始数据(即random_bytes )作为salt应用并传递给PBKDF2调用。使用Base64编码,将只创建字符串。
  • 十六进制编码键(即PBKDF2调用的返回值)。

C#代码在这些点上是不同的,并且:

decoded.

  • Base64使用原始数据(即来自Python端的random_bytes )来进行PBKDF2调用,也就是说,来自Python端的salt是Base64

  • 编码密钥(即PBKDF2调用的返回值)

为了与Python代码兼容而更改C#代码(当然,也可以在Python代码中进行更改,但Python代码似乎是参考):

代码语言:javascript
复制
...
var origSalt = Encoding.UTF8.GetBytes(originalHashParts[1]); // Convert.FromBase64String(originalHashParts[1]);
...
var hashStr = Convert.ToHexString(testHash); // Convert.ToBase64String(testHash);
...

对于后者,使用了Convert.ToHexString(),这在.NET 5之后就可以使用了。

此外,由于对十六进制编码的值进行了比较,对于小写字母(例如binascii.hexlify(key))和大写字母(例如Convert.ToHexString(testHash)),不同的实现没有标准化,因此统一地转换这两个字符串是更可靠的,例如:

代码语言:javascript
复制
if (hashStr.ToUpper() == originalHash.ToUpper())
    return true;

通过这些更改,使用C#代码进行验证是可行的。

编辑(关于注释中处理的Python代码的更改):

如果在Python中使用random_bytes作为salt,而salt被编码为Base64以进行级联,那么在C#代码中,必须再次对Base64编码的salt进行Base64解码(与原始C#代码一样)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73151352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档