【发布时间】:2014-06-25 16:41:16
【问题描述】:
我在客户端使用 cryptojs aes 256 加密了消息。但无法在java端解密它。首先,我将密钥作为十六进制直接传递给服务器端,然后将其从十六进制转换为 java bytearray。它没有用。然后我将短语 salt, iv 作为十六进制传递给服务器。然后生成密钥。它仍然没有工作。总是抱怨密钥长度不对。
客户端:
var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);
var iv = CryptoJS.lib.WordArray.random(256/32);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);
var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 10 });
var key_hex=CryptoJS.enc.Hex.stringify(key);
var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });
var encryptedtxt = secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;
服务器端:
if (encrypted != null)
{
//Get the passphras, salt, IV and msg
String data[] = encrypted.split(":");
String passphrase = data[0];
String salt_hex = data[1];
String iv_hex = data[2];
String msg64 = data[3];
String jskey_hex = data[4];
byte[] jskey = hexStringToByteArray(jskey_hex);
byte[] iv = hexStringToByteArray(iv_hex);
byte[] salt = hexStringToByteArray(salt_hex);
BASE64Decoder decoder = new BASE64Decoder();
byte[] msg = decoder.decodeBuffer(msg64);
try {
//theClear = AES.decrypt(encrypted);
/* Decrypt the message, given derived key and initialization vector. */
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 10, 256/32);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
String plaintext = new String(cipher.doFinal(msg), "UTF-8");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
【问题讨论】:
-
如果“密钥长度不正确”,那么您的问题可能是前导零。
stringify()方法是否将[0x01, 0x02, 0x03]转换为"123"?您的解密代码可能假定为"010203"。"123"可能会给出一个两字节数组[0x12, 0x03],它与输入不匹配并且长度错误。这对加密密钥来说是致命的。 -
256/32 == 8,而 AES 支持的密钥大小为 16、24 或 32 字节。您必须修改 JS 和 Java 代码以使用至少 16 字节的密钥。 -
rossum - 十六进制字符串化密钥就像 010203。但我在 java 端进行十六进制解码到字节数组。我想知道JS上的单词数组如何与java上的字节数组匹配?
-
您的 IV 在 CryptoJS 中的大小也不正确。 AES 使用 128 位块,因此 IV 也应该是 128 位。
-
Owlstead - 你在 IV 上是绝对正确的。改变它。