如何在Python中使用scrypt生成密码和salt的散列

2024-05-15 17:23:00 发布

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

我想使用scrypt为用户的密码和盐创建一个散列。我找到了tworeferences,但有些东西我不明白。

它们使用scrypt加密和解密函数。一个加密随机字符串,另一个加密salt(这看起来是错误的,因为只有密码而不是salt用于解密)。看起来decrypt函数被用来验证密码/salt,作为解密的副作用。

基于我所了解的一点,我想要的是一个密钥派生函数(KDF),而不是加密/解密,并且KDF可能由scrypt生成并用于加密/解密。实际的KDF是在幕后使用的,我担心盲目地遵循这些示例会导致错误。如果使用scrypt encrypt/decrypt函数来生成和验证密码,我就不理解正在加密的字符串的角色。它的内容或长度有关系吗?


Tags: 函数字符串用户密码示例错误密钥encrypt
2条回答

这两个参考资料都完全错了。不要和encryptdecrypt混在一起:只要使用hash

KDF没有直接公开,但是hash已经足够接近了。(事实上,在我看来,它甚至更好,因为它混合了PBKDF2三明治的馅料。)

This example code同时适用于python2.7和python3.2。它使用PyCrypto、passlib和py-scrypt,但只需要需要py-scrypt。

您需要使用类似于passlib.utils.consteq的连续时间比较函数来减轻计时攻击。

您还需要仔细选择参数。默认logN=14,r=8,p=1表示使用16 MiB内存的1“轮”。在服务器上,您可能需要10、8、8之类的东西——更少的RAM,更多的CPU。您应该在您的硬件上的您的预期负载下计时。

你说得对-这两个链接使用的scrypt函数是scrypt文件加密实用程序,而不是底层的kdf。我一直在缓慢地为python创建一个独立的基于scrypt的密码散列,我自己也遇到了这个问题。

scrypt文件实用程序执行以下操作:选择特定于系统的scrypt的n/r/p参数&;min time参数。然后它生成一个32字节的salt,然后调用scrypt(n,r,p,salt,pwd)来创建一个64字节的密钥。该工具返回的二进制字符串由以下部分组成:1)包含n、r、p值和以二进制编码的salt的头;2)头的sha256校验和;3)使用密钥的前32个字节的hmac-sha256有符号校验和副本。然后,它使用密钥的剩余32字节对输入数据进行AES加密。

我可以看到这其中的一些含义:

  1. 输入数据没有意义,因为它实际上并不影响正在使用的salt,encrypt()每次都会生成一个新的salt。

  2. 您不能手动配置n、r、p工作负载,也不能以任何其他方式配置工作负载,只能使用笨拙的min time参数。这并不是没有安全感,而是控制工作因素的一种相当尴尬的方式。

  3. 在decrypt调用重新生成密钥并将其与hmac进行比较之后,如果您的密码错误,它将拒绝那里的所有内容-但是如果它是正确的,它将继续对数据包进行解密。这是攻击者不需要执行的大量额外工作—他们甚至不需要派生64个字节,只需要32个字节来检查签名。这个问题并不能使它完全不安全,但是做你的攻击者不希望做的工作。

  4. 无法配置salt密钥、派生密钥大小等。当前值并没有那么差,但仍然不是理想值。

  5. 解密实用程序的“最长时间”限制对于密码散列是错误的-每次调用解密时,它都会估计系统的速度,并对是否可以在最长时间内计算密钥进行一些“猜测”-这是攻击者不必做的更多开销(请参阅3),但这也意味着解密可能会在系统负载过重的情况下开始拒绝密码。

  6. 我不确定为什么Colin Percival没有将kdf&;参数选择代码作为公共api的一部分,但事实上它在源代码中显式地标记为“private”-甚至没有导出用于链接。这使我犹豫,不想在没有更多研究的情况下直接访问它。

总之,我们需要的是一个能够存储scrypt的好的散列格式,以及一个公开底层kdf和参数选择算法的实现。我目前正在为passlib做这项工作,但还没有引起太多的注意

不过,归根结底,这些网站的说明是“好的”,我只需要使用一个空字符串作为文件内容,并注意额外的开销和问题。

相关问题 更多 >