Nodejs createCipher 与 createCipheriv

Posted

技术标签:

【中文标题】Nodejs createCipher 与 createCipheriv【英文标题】:Nodejs createCipher vs createCipheriv 【发布时间】:2017-10-17 07:13:51 【问题描述】:

我目前正在尝试使用 NodeJS 加密静态数据,我在 Node API 文档中读到 createCipher 不是 recommended。

crypto.createCipher() 的实现使用 OpenSSL 函数 EVP_BytesToKey,摘要算法设置为 MD5, 一次迭代,没有盐。盐的缺乏允许字典攻击 因为相同的密码总是创建相同的密钥。低迭代 计数和非加密安全哈希算法允许密码 非常迅速地进行测试。

根据 OpenSSL 的建议,使用 pbkdf2 代替 EVP_BytesToKey 建议开发者派生出一个密钥和IV 他们自己使用 crypto.pbkdf2() 并使用 crypto.createCipheriv() 创建密码对象。

createCipher 仍然是加密静态数据的可行且安全的方法吗?这种方法是否应该被视为已弃用? 消息灵通的攻击者可能解密数据吗?

是否应该始终首选使用 createCipheriv 的解决方案而不是 createCipher

任何其他细节或建议表示赞赏。

【问题讨论】:

【参考方案1】:

createCipher 是否仍然是加密静态数据的可行且安全的方法?

虽然当然不建议使用已弃用的 API 调用,但可以使用 createCipher 创建安全系统。为此,给定的“密码”必须足够强大以承受离线攻击,并且可能是并行攻击。为此,给定的密码必须有足够的熵(必须足够随机)才能被猜到。例如,您可以使用密码管理器创建约 80 位或更高位的密码并使用它们。

是否应该始终首选使用 createCipheriv 的解决方案而不是 createCipher

是的,如果仅仅因为作者已经警告过您并且对您的代码的任何审查都必须重新考虑createCipher 是否仍然可行。如果该方法曾经从 CryptoJS 中删除(不太可能,但毕竟它已被弃用),那么您的代码将不再运行。

不过,如果您直接使用密码作为密钥,使用createCipheriv安全性低于createCipher。您仍应使用正确的基于密码的密钥派生函数(例如 PBKDF2)来派生输出密钥材料 - 如更新的文档中所述。

任何其他细节或建议表示赞赏。

在大多数情况下,您希望使用更高端的加密/解密方法,例如加密消息语法(CMS,在 PKCS#7 中指定)、PGP 或类似的高端协议/容器格式。

如果您确实需要直接使用密码,您应该尝试看看是否可以选择 GCM 提供的身份验证加密

【讨论】:

似乎值得一提,如果createCipher 用于“常见的分组密码模式(例如 CTR),IV 重用”是一个巨大的安全问题,“对机密性来说是灾难性的”。看来已弃用的createCipher api 并没有阻止使用这些密码模式。见:-github.com/nodejs/node/pull/13821#issuecomment-309900506-crypto.stackexchange.com/questions/2991/…-github.com/nodejs/node/pull/13941 啊,现在该方法的文档中提到了在计数器模式下使用密码进行 IV 重用,并且现在发出警告。用户不应在 crypto.createCipher() 中使用具有计数器模式的密码(例如 CTR、GCM 或 CCM)。使用它们时会发出警告,以避免 IV 重用导致漏洞的风险。对于在 GCM 中重用 IV 的情况,请参阅 Nonce-Disrespecting Adversaries 了解详细信息。 nodejs.org/docs/latest-v6.x/api/…【参考方案2】:

现已弃用的 createCipher 函数不允许使用唯一的 iv,这就是首选 createCipheriv 的原因。

在使用任何密钥派生功能派生密钥时,它无助于保护密文免受 iv 阻止的字典攻击。

【讨论】:

【参考方案3】:

iv 类似于用于密码散列的盐,使黑客难以解密内容。

您可以在这里阅读更多内容:https://auth0.com/blog/adding-salt-to-hashing-a-better-way-to-store-passwords/

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review【参考方案4】:

iv - 代表https://en.wikipedia.org/wiki/Initialization_vectorcreateCipheriv/createDecipheriv 更可取, 用法示例:

const crypto = require('crypto') function encrypt(text) var cipher = crypto.createCipheriv('aes-256-cbc', new Buffer('passwordpasswordpasswordpassword'), new Buffer('vectorvector1234')) var crypted = cipher.update(text, 'utf8', 'hex') crypted += cipher.final('hex') return crypted function decrypt(text) var decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer('passwordpasswordpasswordpassword'), new Buffer('vectorvector1234')) var dec = decipher.update(text, 'hex', 'utf8') dec += decipher.final('utf8') return dec

【讨论】:

为什么更可取?

以上是关于Nodejs createCipher 与 createCipheriv的主要内容,如果未能解决你的问题,请参考以下文章

javascript 从密码短语计算密钥+ IV(createCipher到createCipheriv迁移脚本)

crypto node createcipher 对应java啥方法

关于nodejs访问mysql的思考

使用 Websockets 和 Nodejs 上传文件

react 真的需要前端 ENV 上的 nodeJS 吗?

使用 Nodejs HTTP 服务器的自定义 HTTP 方法