使用 NodeJS 加密与使用 Python 加密不匹配 (cryptography.fernet)

问题描述 投票:0回答:2

这里是密码学新手。我正在尝试在 NodeJS 中编写一个脚本来加密字符串并生成与使用 cryptography.fernet 库的 Python 脚本的输出相匹配的输出。我的总体目标是使用原始密钥来加密 Node 中的消息,稍后将使用 Python 进行解密。

我的 Python 代码示例:

from cryptography.fernet import Fernet

key = Fernet.generate_key() # For example: 6saGtiTFEXej729GUWSeAyQdIpRFdGhfY2XFUDpvsu8=
f = Fernet(key)
message = 'Hello World'
encoded = message.encode()
encrypted = f.encrypt(encoded)

产生输出:

gAAAAABhJs_E-dDVp_UrLK6PWLpukDAM0OT5M6bfcqvVoCvg7r63NSi4OWOamLpABuYQG-5wsts_9h7cLbCsWmctArXcGqelXz_BXl_o2C7KM9o7_eq7VTc=

我的 Node 脚本使用内置 Crypto 模块,并且还必须使用与我的 Python 程序中使用的相同的 32 字节密钥。我知道 fernet 使用 AES-128-CBC 作为其算法,所以这就是我在 Node 脚本中使用的算法。

我的 NodeJS 代码:

const crypto = require("crypto");

const key = '6saGtiTFEXej729GUWSeAyQdIpRFdGhfY2XFUDpvsu8=';
const algorithm = 'aes-128-cbc';
const message = 'Hello World';
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = cipher.update(message, 'utf8', 'hex') + cipher.final('hex');

这给了我:

Error: Invalid key length

我的第一个问题是我不确定如何转换密钥以使其具有正确的长度。通过查看 fernet 的源代码,我还知道密钥分为两部分:前 16 个字节是

signing_key
,最后 16 个字节是
encryption_key
- 我还没有找到太多关于是否/如何我的信息需要在我的 Node 实现中处理原始密钥的这两部分。

由于我是新手,所以我对如何实现我所追求的目标有点困惑。非常感谢任何提示或建议。

python node.js encryption cryptography fernet
2个回答
0
投票

Fernet 格式的规范可以在 https://github.com/fernet/spec/blob/master/Spec.md

找到

他们指定了生成步骤和验证步骤,这里是生成步骤,它应该为您的实现提供足够的信息:

  • 在时间戳字段中记录当前时间。
  • 选择独特的 IV。
  • 构造密文:
    • 根据 RFC 5652 第 6.3 节,将消息填充为 16 字节(128 位)的倍数。这与 PKCS #7 v1.5 和所有版本的 SSL/TLS 中使用的填充技术相同(参见 RFC 5246,TLS 1.2 的第 6.2.3.2 节)。
    • 使用所选 IV 和用户提供的加密密钥,在 CBC 模式下使用 AES 128 加密填充消息。
  • 使用用户提供的签名密钥如上所述计算 HMAC 字段。
  • 按照上述格式将所有字段连接在一起。
  • base64url 对整个令牌进行编码。

从中我们可以看到签名密钥(完整密钥的前半部分)用于 HMAC,而后半部分用于 AES128-CBC,因此只需将密钥分成两个单独的元素(从十六进制字符串进行适当的转换)字节)应该足以使用 Node.js 加密模块 (https://nodejs.org/en/knowledge/cryptography/how-to-use-crypto-module/) 构建您自己的实现。


0
投票

key = Fernet.generate_key() 它永远不会匹配,因为它会在每个请求上生成一个随机密钥。

© www.soinside.com 2019 - 2024. All rights reserved.