你说得对 - 这两个链接处理的是 scrypt 文件加密实用工具,而不是底层的 kdf。我一直在努力创建一个基于独立的 scrypt 的密码哈希算法,也遇到了这个问题。
scrypt 文件实用工具的功能如下:选择特定于您的系统的 scrypt 的 n/r/p 参数和“最小时间”参数。然后生成一个 32 字节的盐,并调用 scrypt(n,r,p,salt,pwd)
创建一个 64 字节的密钥。该工具返回的二进制字符串由以下内容组成:1) 包含 n、r、p 值的头文件,以及以二进制编码的盐;2) 头文件的 sha256 校验和;3) 使用密钥的前 32 个字节对校验和进行 hmac-sha256 签名的副本。接下来,它使用密钥的剩余 32 个字节对输入数据进行 AES 加密。
我可以看到其中有几个含义:
输入数据是无意义的,因为它实际上不会影响使用的盐,而且每次加密()都会生成一个新的盐。
你不能手动配置 n、r、p 工作负载,也不能通过任何方式除了笨拙的最小时间参数。这并不是不安全的,但这是一个非常笨拙的控制工作因素的方法。
在解密调用重新生成密钥并将其与 hmac 进行比较之后,如果你的密码不正确,它将在那里拒绝所有内容 - 但如果正确,它将继续“同时”解密数据包。这是攻击者不必执行的大量额外工作 - 他们甚至不需要推导出 64 个字节,只需要推导出检查签名所需的 32 个字节。这个问题并不使它“不安全”,但做一些攻击者不需要的工作是绝不可取的。
没有办法配置盐密钥、派生密钥大小等。目前的值还不错,但仍然不是理想的。
解密工具的“最大时间”限制在密码哈希方面是错误的 - 每次调用解密时,它都会估计您系统的速度,并根据此进行一些“猜测”,以确定是否可以在最大时间内计算出密钥 - 这比攻击者多做了更多额外的工作(见#3),但这也意味着在系统负载过重时,解密可能会开始拒绝密码。
我不确定为什么Colin Percival没有将kdf和参数选择代码作为公共API的一部分,但实际上,在源代码中明确将其标记为“私有”-甚至不导出链接。这使我不敢直接访问它,需要进行更多的研究。
总之,需要一个可以存储scrypt的良好哈希格式,以及一个公开底层kdf和参数选择算法的实现。我目前正在为passlib自己开发,但它还没有得到太多关注:(
总的来说,那些网站的说明是“可以”的,我只会将空字符串用作文件内容,并注意额外的开销和问题。
encrypt
和decrypt
:直接使用hash
。hash
足够接近。(实际上,我认为它甚至更好,因为它将填充PBKDF2三明治的混合物。)
这个示例代码适用于python2.7和python3.2。它使用PyCrypto、passlib和py-scrypt,但只需要py-scrypt。passlib.utils.consteq
这样的恒定时间比较函数来减轻时间攻击。