如何使用具有可变消息大小的CryptoJS CTR模式(随机数计数器和偏移量)



当使用cryptoJS在AES(CTR模式(中加密和解密消息时,AES算法依赖于nonce(数字一次(值来混淆流块并防止重放攻击。在cryptoJS中,要设置你的随机数:

const cli_verify = CryptoJS.AES.encrypt(CryptoJS.enc.Latin1.parse(originalString), key, {
mode: CryptoJS.mode.CTR,
iv: iv,
padding: CryptoJS.pad.NoPadding
});

同样,在解密邮件时,您可以使用相同的方法:

const decryptedString = CryptoJS.AES.decrypt(encryptedStringB64, key, {
mode: CryptoJS.mode.CTR,
iv: iv,
padding: CryptoJS.pad.NoPadding
}).toString(CryptoJS.enc.Latin1); 

但是:如果你这样做,你需要自己跟踪随机数。这是a(痛苦,b(如果你开始处理可变大小的消息(即不是16字节的倍数(,这真的很困难。

我已经拆开了另一边我正在与之交谈的AES库,并弄清楚了随机数计数器和偏移量的工作原理。基本上,如果您开始发送非常小的消息,例如 4 个字节,则 4 个字节将使用流的前 4 个字节进行解密,并且偏移量将增加到 4 以跟踪这一点。如果随后加密 6 个字节,则使用流的下一个 6 个字节(不增加随机数(,并将偏移量更新为 10...如果下一次传输是 143 字节,您可以看到这如何开始变得复杂起来。使用当前流的最后 6 个字节,增加随机数,依此类推。

我的问题是:如何让CryptoJS在会话期间为您处理此问题。我尝试在第一次调用中设置 IV、填充和模式,然后在下一次调用中将其留空,但它不起作用。这是一个很棒的图书馆,我敢肯定它就在那里。只是不清楚如何使用它。

您可以改用渐进式加密 api,这确实会正确更新随机数/计数器。

var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");

// encrypt
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, {
mode: CryptoJS.mode.CTR,
iv: iv,
padding: CryptoJS.pad.NoPadding
});
var ciphertextPart1 = aesEncryptor.process("Message Part 1");
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
var ciphertextPart4 = aesEncryptor.finalize();
​
// decrypt
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, {
mode: CryptoJS.mode.CTR,
iv: iv,
padding: CryptoJS.pad.NoPadding
});    ​
var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
var plaintextPart5 = aesDecryptor.finalize();

根据上述代码片段最初来自 https://cryptojs.gitbook.io/docs/。

如果处理的输入与块大小不匹配(如本例所示(,则在调用 finalize 之前,您将无法获得所有输出。

您可能会发现需要调用 finalize 才能从与块大小不匹配但仍希望继续使用加密器/解密器的输入中获取输出。这样做的用例是需要在客户端和服务器之间同步随机数的地方。如果在输入和块大小不匹配时在完成后调用进程,则 api 不起作用。克隆 api 在块大小和输入不匹配的情况下也无法正常工作(在这种情况下,这实际上是您想要做的(。

但是,如果您跟踪会话期间发送和接收的所有输入,则可以在调用 finalize 后重新构建会话。这可以通过在调用 finalize 以获取最终输出之前调用进程将以前的输入重播到新的加密器/解密器来完成。在这种情况下,在调用 finalize 后,您需要从输出中获取与输入中相同的字节数,因为加密器/解密器可能包含一些以前的输出,就像输入块大小不匹配的情况一样。

最新更新