我需要使用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输出?非常感谢!!
假设您将修复诸如空IV之类的事情以及这是概念验证,您的代码将失败,因为:
在Java中不使用填充,您需要在JS中使用相同的填充
您在Java中手动填充空值,您需要在JS中执行相同的操作
你base64解码密钥但它不是base64(它是一个十六进制的字节串)
Java IV是一个空数组,但在JS中你使用空格(并错误地将其视为base64).
要在JS中复制输出:
CryptoJS.pad.NoPadding = {pad: function(){}, unpad: function(){}}; var text = "My Secret text\0\0"; var key = CryptoJS.enc.Hex.parse("253D3FB468A0E24677C28A624BE0F939"); var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000"); var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.NoPadding}); console.log(encrypted.toString());
对于:
7StScX3LnPUly/VNzBes0w ==