【问题标题】:Encryption with NodeJS doesn't match encryption using Python (cryptography.fernet)使用 NodeJS 的加密与使用 Python (cryptography.fernet) 的加密不匹配
【发布时间】:2021-10-26 02:05:10
【问题描述】:

这里是密码学新手。我正在尝试在 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 实现中处理这两个原始键。

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

【问题讨论】:

  • Fernet 生成的密钥不是二进制的,而是 Base64 编码的,因此只需先使用 Base64 解码器,然后将二进制数据分成两部分(通常连接 iv | key) .使用这两个数据作为加密函数的输入(不生成随机 iv)。

标签: python node.js encryption cryptography fernet


【解决方案1】:

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 节)。
    • 在 CBC 模式下使用 AES 128 使用所选 IV 和用户提供的加密密钥对填充消息进行加密。
  • 使用用户提供的签名密钥计算上述 HMAC 字段。
  • 按照上述格式将所有字段连接在一起。
  • base64url 对整个令牌进行编码。

从这里我们可以看到,签名密钥(完整密钥的前半部分)用于 HMAC,而后半部分用于 AES128-CBC,因此只需将密钥分成两个单独的元素(从hex string to bytes) 应该足以使用 Node.js 加密模块 (https://nodejs.org/en/knowledge/cryptography/how-to-use-crypto-module/) 来构建您自己的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多