验证Python Passlib在.NET中生成的PBKDF2 SHA512哈希

2024-06-09 01:22:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在迁移一个使用Passlib 1.6.2生成密码哈希的平台。加密密码的代码是(使用轮数的默认值调用哈希):

from passlib.hash import pbkdf2_sha512 as pb

def hash(cleartext, rounds=10001):
    return pb.encrypt(cleartext, rounds=rounds)

输出格式如下(对于密码“Patient3”(没有引号)):

^{pr2}$

和“测试123”

$pbkdf2-sha512$10001$2ZuTslYKAYDQGiPkfA.B8A$ChsEXEjanEToQcPJiuVaKk0Ls3n0YK7gnxsu59rxWOawl/iKgo0XSWyaAfhFV0.Yu3QqfehB4dc7yGGsIW.ARQ

我可以看出这代表着:

  • 算法SHA512
  • 迭代10001
  • 盐0dr7v7eWUmptrfW.9z6HkA(可能)

Passlib算法在their site上定义,内容如下:

All of the pbkdf2 hashes defined by passlib follow the same format, $pbkdf2-digest$rounds$salt$checksum.

$pbkdf2-digest$ is used as the Modular Crypt Format identifier ($pbkdf2-sha256$ in the example). digest - this specifies the particular cryptographic hash used in conjunction with HMAC to form PBKDF2’s pseudorandom function for that particular hash (sha256 in the example). rounds - the number of iterations that should be performed. this is encoded as a positive decimal number with no zero-padding (6400 in the example). salt - this is the adapted base64 encoding of the raw salt bytes passed into the PBKDF2 function. checksum - this is the adapted base64 encoding of the raw derived key bytes returned from the PBKDF2 function. Each scheme uses the digest size of its specific hash algorithm (digest) as the size of the raw derived key. This is enlarged by approximately 4/3 by the base64 encoding, resulting in a checksum size of 27, 43, and 86 for each of the respective algorithms listed above.

我找到了passlib.net,它看起来有点像一个废弃的beta版本,它使用了'$6$'作为算法。我无法让它验证密码。我试着把算法改成6美元,但我怀疑实际上也改变了盐。在

我也尝试过将PWDTK与salt和hash的不同值一起使用,但可能是我错误地分割了影子密码,或者在一些不该提供$的地方。在

在.NET中,有没有方法可以根据这个哈希值验证密码?或者另一个不需要Python代理或让用户重新提供密码的解决方案?在


Tags: ofthein算法密码byisas
2条回答

我使用zaph的逻辑和JimmiTh在SO answer上的代码,快速地构建了一个.NET实现。我已经将代码放在GitHub(这不是生产准备就绪)。它似乎可以与我们的用户群中的一些例子一起工作。在

正如扎弗所说的逻辑是:

  1. 拆分散列以查找迭代计数、salt和散列密码。(我假设了算法,但你要验证它)。您将有一个由5个值组成的数组,其中包含[0]-Nothing、[1]-算法、[2]-迭代、[3]-Salt和{}-Hash
  2. 将salt转换为标准Base64编码,方法是将“.”字符替换为“+”字符,并附加“==”。在
  3. 将密码、salt和迭代计数传递给PBKDF2-HMAC-SHA512生成器。在
  4. 通过将任何“+”字符替换为“.”字符并去掉后面的“==”,将其转换回原始的base64格式。在
  5. 将原始散列(拆分字符串中的元素4)与转换后的值进行比较,如果它们相等,则得到一个匹配项。在

通过将密码传递到PBKDF HMAC-SHA-256哈希方法,然后将生成的哈希与保存的哈希部分(从Base64版本转换回来)进行比较来验证哈希。在

将哈希保存为二进制,然后分离哈希 使用UTF-8编码将密码转换为二进制 PBKDF2,HMAC,SHA-256(toBinary(密码,salt,10001)==哈希 密码:“Patient3”

$pbkdf2-sha512$10001$0dr7v7eWUmptrfW.9z6HkA$W9J9AMVMKAP17OOSCQDXDV2HJSVZLPF8RRA8I7P/b5746rghZ8WrgEjDpvXG5hLz1UeNLzgFa81Drbx2b7.hg

分解为(字符串转换为标准Base64(将“.”更改为“+”,并添加尾随的“=”填充:

pbkdf2 - sha512
10001
0dr7v7eWUmptrfW+9z6HkA==
w9j9AMVmKAP17OosCqDxDv2hjsvzlLpF8Rra8I7p/b5746rghZ8WrgEjDpvXG5hLz1UeNLzgFa81Drbx2b7+hg==

解码为十六进制:

^{pr2}$

这是有意义的:16字节(128位)salt和64字节(512位)SHA-512哈希。在

使用“t3-8”UTF转换成二进制数组 将salt从修改的BASE64编码转换为16字节二进制数组 使用迭代计数od 10001 使用HMAC和SHA-512将其输入PBKDF2

我明白了

C3D8FD00C5662803F5ECEA2C0AA0F10EFDA18ECBF394BA45F11ADAF08EE9FDBE7BE3AAE0859F16AE01230E9BD71B984BCF551E34BCE015AF350EB6F1D9BEFE86

当Base64编码时,用“.”替换“+”字符并去掉后面的“=”字符返回: w9j9AMVmKAP17OosCqDxDv2hjsvzlLpF8Rra8I7p/b5746rghZ8WrgEjDpvXG5hLz1UeNLzgFa81Drbx2b7.hg

相关问题 更多 >