PHP / Javascript AES 128 CFB 加密/解密 CryptoJS OpenSSL

PHP / Javascript AES 128 CFB Encryption / Decryption CryptoJS OpenSSL

正在PHP

解密
function decrypt($encryptedText){
    $key = "1234567890123456";
    $decrypted = openssl_decrypt(substr(base64_decode($encryptedText), 16), "AES-128-CFB", $key, OPENSSL_RAW_DATA, substr(base64_decode($encryptedText), 0, 16));
    return $decrypted;
}
$encryptedText = "1EwMDT20BELrEixvrSGswDC4GZIn5BWGor6MP6ERi9Ux";
echo decrypt($encryptedText);

将输出“解密消息”

我正在尝试在 Javascript

中复制它
var key = '1234567890123456';
var base64data = CryptoJS.enc.Base64.parse("1EwMDT20BELrEixvrSGswDC4GZIn5BWGor6MP6ERi9Ux");
var encrypted = new CryptoJS.lib.WordArray.init(base64data.words.slice(4));
var iv = new CryptoJS.lib.WordArray.init(base64data.words.slice(0, 4));
var cipher = CryptoJS.lib.CipherParams.create({ ciphertext: encrypted });
var decrypted = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(key), {iv: iv, mode: CryptoJS.mode.CFB});
console.log("Decrypted: "+decrypted.toString(CryptoJS.enc.Utf8));

我得到一个空洞的回应,如果我能提供任何帮助,我将不胜感激。 谢谢

CFB是流密码模式,即不使用填充。

在填充模式下,密文的长度始终对应于块大小的整数倍,即 AES 为 16 字节。这意味着密文总是由 complete WordArray 组成(一个 WordArray 的大小为 4 个字节)。

在没有padding的模式下,比如CFB,密文和明文一样长,所以最后的WordArray 一般不完全部分密文。
例如消息 Decrypted Message 的长度为 17 个字节,即由 5 WordArrays 组成,最后一个只有 one 有效字节。
因此,必须为 encrypted 指定有效字节数:base64data.sigBytes - 16(减去 16 是必要的,因为 base64data 也包含 IV)。

此外,填充必须显式禁用。

经过这两个修改,解密成功:

var key = '1234567890123456';
var base64data = CryptoJS.enc.Base64.parse("1EwMDT20BELrEixvrSGswDC4GZIn5BWGor6MP6ERi9Ux");
var encrypted = new CryptoJS.lib.WordArray.init(base64data.words.slice(4), base64data.sigBytes - 16); // consider significant bytes
var iv = new CryptoJS.lib.WordArray.init(base64data.words.slice(0, 4));
var cipher = CryptoJS.lib.CipherParams.create({ ciphertext: encrypted });
var decrypted = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(key), {iv: iv, mode: CryptoJS.mode.CFB, padding: CryptoJS.pad.NoPadding}); // disable padding
document.getElementById("pt").innerHTML = "Decrypted: " + decrypted.toString(CryptoJS.enc.Utf8);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<p style="font-family:'Courier New', monospace;" id="pt"></p>

顺便说一下,CFB 有不同的变体。这里,两个代码都使用全块 CFB (CFB128)。