我知道带有缓冲区的 AES 256 CBC 可以提供不同的加密,但其长度66。 这是我的代码
const crypto = require('crypto');
const ENCRYPTION_KEY = 'Must256bytes(32characters)secret';
const IV_LENGTH = 16;
function encrypt(text) {
let iv = crypto.randomBytes(IV_LENGTH);
let cipher = crypto.createCipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let encrypted = cipher.update(text.toString());
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + 'XX' + encrypted.toString('hex');
}
function decrypt(text) {
let textParts = text.split('XX');
let iv = new Buffer(textParts.shift(), 'hex');
let encryptedText = new Buffer(textParts.join('XX'), 'hex');
let decipher = crypto.createDecipheriv('aes-256-cbc', new Buffer(ENCRYPTION_KEY), iv);
let decrypted = decipher.update(encryptedText);
try{
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}catch(Err){
return 'NULL';
}
}
问题是加密数据长度为 66,即使文本为 1
那么是否有任何加密和解密方法应该每次给出不同的加密数据,并且文本为 1 时少于 10 个字符(根据我的示例)
谢谢
最佳答案
是的。您可以获得 5 个字节(或 10 个十六进制字符)或更少的密文。但如此短的密文是有问题的。
基本上有两种方法。我将从更简单的开始。
计数器模式(CTR)
您可以将 CTR(计数器)模式与随机数一起使用。使用 CTR 模式加密 X 字节会得到恰好 X 字节的结果。 CTR模式不需要将明文填充到 block 大小的N倍。
此随机数(使用过一次的数字)必须是唯一的数字,否则您的明文将面临暴露的直接危险。你不能仅仅依赖一个随机数;由于生日限制,4 字节随机数具有很高的重复概率。
因此,您要么需要单独存储随机数,要么在密文中包含 4 字节随机数。然而,如果你设法重复使用随机数,那么你就完蛋了。对于如此少量的字节,这意味着您基本上必须保留一个 4 字节计数器,这意味着必须存储状态。
通常,CTR 模式加密例程要求您提供 IV 而不是随机数。这只是初始计数器值。您必须通过获取随机数来构造该值,然后用零值字节对其进行右填充,直到达到 16 字节(AES 的 block 大小)。
您可以找到示例代码here ,别忘了点赞哦。 Rob 还提供了一些示例代码 in his answer .
格式保留加密(FPE)
通过格式保留加密,加密的输出使用精确的位数或什至值作为输入的可能值。听起来不错,但 FPE 由一堆相对复杂的算法组成。基本上你必须在 JavaScript 中找到一个加密库来实现它。
请注意,使用 FPE,相同的消息将始终加密为相同的密文。根据应用程序的不同,这可能是也可能不是问题。
<小时/>注释:
- 您使用的是十六进制编码,这不是最密集的编码,您可以使用 Base 64 甚至 ASCII 85 编码。
- 首先将 IV 和密文连接为字节然后执行编码会更有效。如果 IV 的大小是静态的,则可以简单地使用常量而不是分隔符。
- 您的 key 应由随机字节组成,而不是文本字符串。密码需要使用密码哈希进行转换。
关于node.js - nodejs crypto 是否有加密和解密文本,每次都应该给出不同的加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50307269/