crypto.pbkdf2 是异步的,如何将其视为同步?

Posted

技术标签:

【中文标题】crypto.pbkdf2 是异步的,如何将其视为同步?【英文标题】:crypto.pbkdf2 is asynchronous, how do I treat it as synchronous? 【发布时间】:2012-12-23 13:47:31 【问题描述】:

我在 node.js 中使用 pbkdf2 来散列密码。

我的问题是我正在响应身份验证请求,并且我正在验证传递的凭据是否正确。我假设 pbkdf2 是异步的,因为它可能需要大量时间(取决于迭代的大小)。然而,将剩余的身份验证逻辑移动到一个单独的方法中以利用回调似乎有点难看。

有没有比使用计时器或将所有连续的身份验证逻辑放入单独的函数更好的方法?我知道大多数人会说我应该使用回调,但在我的用例中这没有意义。在将 pbkdf2 应用于传递的密码之前,我无法继续进行身份验证。

【问题讨论】:

【参考方案1】:

根据Node.js crypto docs,PBKDF2 函数有异步版本和同步版本。

crypto.pbkdf2(密码、盐、迭代、keylen、回调)

异步 ​​PBKDF2 应用伪随机函数 HMAC-SHA1 推导 来自给定密码、盐和迭代的给定长度的密钥。 回调有两个参数(err, derivedKey)

crypto.pbkdf2Sync(密码、盐、迭代、keylen)

同步 PBKDF2 函数。返回 derivedKey 或抛出错误。

【讨论】:

谢谢凯文,我不知道为什么我去年没有看到。如果它有效,那么这是一个更好的答案,因为它是我真正想要的。当我有机会时,我会重新审视代码并进行测试。 第五个参数是摘要。 crypto.pbkdf2Sync(密码、盐、迭代、keylen、摘要)【参考方案2】:

我可以为您的问题提供两种解决方案。

第一个是使用一些库来包装异步调用。你可以试试node-sync 或node-promise。 node-sync 更适合您的需求。

第二种解决方案是使用bcrypt而不是crypto:

var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(password, salt);

bcrypt 是 node.js 中用于密码哈希的特殊库。它比内置加密模块更安全,并提供一些有用的方法,如hashSynccompareSync

【讨论】:

我是否认为 bcrypt 是基于河豚的(根据 node.bcrypt.js 项目的***链接)?我使用的 pbkdf2 盐大于 128 位,迭代次数为 10000 次,这是 NIST 批准的,而河豚 bcrypt 则不是(请参阅 wikipedia artical)。我只是对您关于 bcrypt 更安全的评论感到好奇。就我的目的而言,这是最有可能的。不是那么重要,但我想使用最安全的方法。 @Metalskin,我进行了更多调查。 Bcrypt 在较短的路径短语上更强,但在长度超过 55 个字符的路径短语上开始失去pbkdf2。但是它们都足够安全,因此没有真正的区别。请参阅this answer 了解更多信息。 感谢链接真的很有帮助,我认为我不会超过 55 个字符,所以使用 bcrypt 应该没问题。看起来 scrypt 会更好,但我找不到 node.js 的任何活动项目。 当我说没有真正的区别时,我的意思是实际上不可能取消散列 pbkdf2-hashed 字符串。对于平均大小的密码短语(8 个字符),Bcrypt 的强度要高十倍。但“十次不可能”只是一个“不可能”。

以上是关于crypto.pbkdf2 是异步的,如何将其视为同步?的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs crypto.pbkdf2 结果与 CryptoJS.PBKDF2 不同

如何在php hash_pbkdf2中使用字节数组类型的nodejs crypto pbkdf2 salt

使用 HMAC SHA-1 的 PBKDF2 如何返回超过 20 个字节?

使用 pbkdf2 的 SALT 和 HASH

如何让macos将文档包视为文件?

为啥 Firestore 返回一个集合引用,但我的程序将其视为一个数组?