CryptoJS 不忠实地解密非拉丁字符

CryptoJS not decrypting non-Latin characters faithfully

我正在尝试使用 CryptoJS AES,如下所示:

var msg = "café";
var key = "something";
var c = CryptoJS.AES.encrypt(msg, key).toString();
CryptoJS.AES.decrypt(c, key).toString(CryptoJS.enc.Latin1);

很遗憾,这个 returns café,而不是 café。显然 Latin1 不是正确的编码,但我找不到更好的编码。有解决办法吗?

谢谢。

您只是缺少格式
正确的方法是使用 CryptoJS.enc.Utf8

所以,请尝试:

CryptoJS.AES.decrypt(c, key).toString(CryptoJS.enc.Utf8);

您正在尝试将您的数据解密为 Latin1 字符串,即使您的输入字符串不是 Latin1 格式。 CryptoJS 内部使用的编码与您用于写入输入文件的编码不同。

加密(字符串-> 字节数组转换)和解密(字节数组-> 字符串转换)都需要指定相同的编码。

https://code.google.com/p/crypto-js/#The_Hasher_Input

The hash algorithms accept either strings or instances of CryptoJS.lib.WordArray [...] an array of 32-bit words. When you pass a string, it's automatically converted to a WordArray encoded as UTF-8.

因此,当您传递一个字符串(并且不使用 CryptoJS.enc.* 生成 WordArray)时,它会自动将字符串 (message) 转换为 utf8 WordArray.

请在此处查看往返示例 encrypt/decrypt: https://code.google.com/p/crypto-js/#The_Cipher_Output

这是一个与 CryptoJS 一起玩的 jsfiddle https://jsfiddle.net/8qbf4746/4/

var message = "café";
var key = "something";

var encrypted = CryptoJS.AES.encrypt(message, key);
//equivalent to CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(message), key);
var decrypted = CryptoJS.AES.decrypt(encrypted, key);

$('#1').text("Encrypted: "+encrypted);
$('#2').text("Decrypted: "+decrypted.toString(CryptoJS.enc.Utf8));

为了强调我的观点,使用 Latin1 编码也是一样的: https://jsfiddle.net/3a8tf48f/2/

var message = "café";
var key = "something";

var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Latin1.parse(message), key);
var decrypted = CryptoJS.AES.decrypt(encrypted, key);

$('#1').text("Encrypted: " + encrypted);
$('#2').text("Decrypted: " + decrypted.toString(CryptoJS.enc.Latin1));

附带说明一下,如果 API 只接受 WordArray 并且不重载 toString 方法(这只是 CryptoJS.enc 的一个方便接口),它可能会更好.*.stringify)。字符串转换魔法有点误导。