我正在像这样加密文本(node.js):
var text = "holds a long string..."
var cipher = crypto.createCipher("aes128", "somepassword")
var crypted = cipher.update(text, 'utf8', 'hex')
crypted += cipher.final('hex');
如果我直接把text
存到一个文件里,就是N个字节。如果我保存 crypted
,文件大小约为 N * 2 字节。
有什么方法可以使密文尽可能接近N字节?
最佳答案
像 AES 这样的现代密码适用于二进制数据。当您加密字符数据时,它首先被转换为二进制表示。这基本上就是 UTF-8 编码的作用。加密后,您会得到任意二进制数据,当您尝试对其进行解码时,它不一定是有效的 UTF-8 编码(几乎所有编码都有特殊结构)。
如果您从 Cipher#update
和 Cipher#final
中省略了 output_encoding
,您将得到一个 Buffer
,您可以将其连接或写入文件。它以二进制格式管理数据,但打印时默认为十六进制。当您将缓冲区写入文件时,文件大小将接近明文大小,但永远达不到。
AES 是一种 block 密码,只能加密恰好 16 字节的单个 block 。 ECB 或 CBC 等操作模式使您能够加密多个 block 。最后,像默认 PKCS#7 填充这样的填充方案使您能够加密任意长度的文本。此填充总是在实际解密之前添加一些字节。准确地说,它增加了 1 到 16 个字节。
您可以使用 cipher.setAutoPadding(false)
来防止填充,但是您需要自己填充。您也可以使用像 CTR(“aes-128-ctr”)这样的流模式,但是您需要为其提供 12 字节的唯一 IV(随机数)有什么保障。这个 nonce 不必是 secret 的,但你必须将它传输到解密器。
最后密文真的不可能和明文大小完全一样。总有一些东西会膨胀密文。
切勿使用 crypto.createCipher
。您需要使用随机 密码来获得语义安全。使用带有新鲜随机 IV 的 crypto.createCipheriv
。对于 CTR 模式,IV 必须是唯一的,对于 CBC 模式,它必须是不可预测的。
始终使用经过身份验证的加密。它使您能够检测错误的 key 和(恶意的)密文篡改。 Here's AES-GCM 示例。
关于node.js - 如何在不增加太多大小的情况下使用 crypto 加密文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34872151/