如何使用 CryptoJS 成功解密在 Node 中通过 OpenSSL 生成的 AES-256 加密内容.js



上下文

我有一个 Node.js AWS Lambda 函数,它充当自定义授权方并由 AWS API 网关触发,它应该从授权标头(AES-256 加密的 JSON(中获取令牌,并使用 CryptoJS 和秘密密码对其进行解密。仅供参考,令牌不是 JWT。 我已经遵循了CryptoJS文档,但它只是不起作用。我已经阅读了数十篇帖子和文章,令我惊讶的是,我找不到像我这样的简单方法的人

步骤和代码

1(我有一个名为token.json的文件,其中包含一个字符串化的JSON对象:

"{"user_id":1,"name":"user","time":"2019-09-27 13:58:22","env":"dev"}"

2( 按照 CryptoJS 示例,在我正在执行的终端中:openssl enc -aes-256-cbc -in token.json -out encrypted-json-token -pass pass:"password" -e -A -base64

我正在使用-A选项来获取一行字符串。 根据openssl enc --help

-A 与 -[base64|a] 一起使用,将 base64 缓冲区指定为单行

3( 我正在获取该输出、加密令牌,并将其作为 HTTP 请求中的Authorization标头的值发送,该请求由 AWS API 网关解析,该标头获取并将其传递给我的 Lambda 函数。

4( 在 Lambda 函数中:

const AES = require('crypto-js/aes');
const Utf8 = require('crypto-js/enc-utf8');
module.exports.authenticate = function authenticate(event, context, callback) {
...
try {
const token = event.authorizationToken;
const decryptedToken = AES.decrypt(token, 'password').toString(Utf8);
const parsedToken = JSON.parse(decryptedToken);
}
catch(error){
// log error
}
...
}

解密的结果是一个空字符串,因此解析为 JSON 失败。

结语

我之所以调用.toString(Utf8),是因为根据这个和这个,解密操作的输出是一个Word Array 对象,我需要将其转回原始字符串形式,这应该是字符串化的 JSON 令牌。 此外,我正在使用无服务器离线插件在本地模拟 API 网关来测试所有这些。

TL;DR:使用-K标志传递编码为十六进制的实际 AES 密钥。

如果您仔细阅读openssl enc的文档,您会注意到-pass(-k(和-K标志之间存在差异 - 第一个实际上是密码,第二个是实际密钥。

如果您使用-pass,您实际上是在传递一个任意字符串密码,该密码通过(过时且不安全的(KDFEVP_KDF提供。 如果使用-K,则可以将真正的 AES 密钥作为十六进制字符串传递。

由于EVP_KDF不安全,我推荐后者。

最新更新