【发布时间】:2017-01-16 14:20:43
【问题描述】:
我需要使用 JavaScript 实现 AES 加密。使用 AES/CBC/NoPadding 模式并创建了一种完成 16 个长度块的方法。我已经使用 Java 解决了它。它看起来像:
public static String encrypt(byte[] key, byte[] initVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(completeBlocks(value));
return Base64.encodeBase64String(encrypted);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Error: " + ex);
}
return null;
}
/**
* Completes 16 lenght blocks
*
* @param message
*
*
*/
static byte[] completeBlocks(String message) {
try {
int bytesLenght = message.getBytes("UTF-8").length;
if (bytesLenght % 16 != 0) {
byte[] newArray = new byte[bytesLenght + (16 - (bytesLenght % 16))];
System.arraycopy(message.getBytes(), 0, newArray, 0, bytesLenght);
return newArray;
}
return message.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
System.out.println("" + ex);
}
return null;
}
public static void main(String[] args) {
String key = "253D3FB468A0E24677C28A624BE0F939";
String strToEncrypt = "My Secret text";
final byte[] initVector = new byte[16];
String resultado = encrypt(new BigInteger(key, 16).toByteArray(), initVector, strToEncrypt.trim());
System.out.println("ENCRYPTED:");
System.out.println(resultado);
}
使用输入 key = 253D3FB468A0E24677C28A624BE0F939、strToEncrypt = "My Secret text" 和 ceros IV。它抛出
7StScX3LnPUly/VNzBes0w==
我知道这是所需的输出。这是正确的! 我尝试使用 JavaScript 复制它。我使用了 CryptoJs 库。但我无法产生相同的 Java 输出。我试过了:
var text = "My Secret text";
var key = CryptoJS.enc.Base64.parse("253D3FB468A0E24677C28A624BE0F939");
var iv = CryptoJS.enc.Base64.parse(" ");
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log(encrypted.toString());
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
使用相同的输入,我得到De+CvPVIyiBX2//EE6gXTg== 作为输出。我究竟做错了什么?如何获得相同的 Java 输出?非常感谢!!
【问题讨论】:
-
看来cryptojs不支持CBC模式。
-
另外,您的密钥以十六进制而不是 base64 的形式给出,并且为 base64 提供空格与零数组不同。
-
@TamasHegedus 我认为你是对的!!遗憾的是,不支持 CBC 模式。我找到了这个:github.com/ricmoo/aes-js。看起来它支持CBC模式。我要试试!!非常感谢!
-
Sergio,事实证明它确实支持 CBC。它在 github.com/sytelus/CryptoJS/blob/… 中实现,而不是在 mode-cbc.js 中作为其他一些模式。
-
@TamasHegedus 我正在检查它!你看起来很棒!我要试试!谢谢
标签: javascript java encryption aes