我正在加密像这样的文本(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'); 如果我直接将文本
var text = "holds a long string..." var cipher = crypto.createCipher("aes128", "somepassword") var crypted = cipher.update(text, 'utf8', 'hex') crypted += cipher.final('hex');
如果我直接将文本保存到文件,则为N个字节.如果我保存加密,文件大小约为N * 2个字节.
制作加密文本的任何方法都尽可能接近N个字节?
像AES这样的现代密码适用于二进制数据.加密字符数据时,首先将其转换为二进制表示形式.这基本上是UTF-8编码所做的.加密后,您将获得任意二进制数据,当您尝试对其进行解码时,该数据不一定是有效的UTF-8编码(几乎所有编码都具有特殊结构).如果省略Cipher#update和Cipher#final中的output_encoding,则会得到一个Buffer,您可以将其连接或写入文件.它以二进制格式管理数据,但在打印时默认为Hex.当您将缓冲区写入文件时,文件大小将接近明文大小,但它永远不会达到它.
AES是块密码,只能加密正好16字节的单个块.像ECB或CBC这样的操作模式使您可以加密多个块.最后,像默认的PKCS#7填充这样的填充方案使您可以加密任意长度的文本.此填充总是在实际解密之前添加一些字节.确切地说,它增加了1到16个字节.
你可以使用cipher.setAutoPadding(false)来防止填充,但是你需要自己填充.你也可以使用像CTR这样的流模式(“aes-128-ctr”),但是你需要提供一个12字节的唯一IV(nonce),因为它具有任何安全性.此随机数不一定是秘密的,但您必须将其传输到解密器.
最后,密文与明文的大小完全相同是不可能的.总有一些东西会膨胀密文.
切勿使用crypto.createCipher.您需要使用随机密码来获得语义安全性.使用crypto.createCipheriv和一个新的随机IV.对于CTR模式,IV必须是唯一的,对于CBC模式,它必须是不可预测的.
始终使用经过验证的加密.它使您能够检测错误的密钥和(恶意)篡改密文. Here’s使用AES-GCM的示例.