我正在客户端使用CryptoJS AES算法对文本进行加密,并在Java的服务器端对其进行解密,但出现了异常.
JS代码:
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
console.info("encrypted " + encrypted);
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
var plainText = decrypted.toString(CryptoJS.enc.Utf8)
console.info("decrypted " + plainText);
js输出:
encrypted U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=
decrypted Message
Java代码:
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESJavaScript {
private SecretKeySpec key;
private Cipher cipher;
private int size = 128;
private static final Charset CHARSET = Charset.forName("UTF-8");
public AESJavaScript() throws NoSuchAlgorithmException,
NoSuchPaddingException, NoSuchProviderException {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(size); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
key = new SecretKeySpec(raw, "AES/CTR/NoPadding");
cipher = Cipher.getInstance("AES/CTR/NoPadding");
}
public void setKey(String keyText) {
byte[] bText = new byte[size];
bText = keyText.getBytes(CHARSET);
key = new SecretKeySpec(bText, "AES/CTR/NoPadding");
}
public String encrypt(String message) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(message.getBytes());
return byteArrayToHexString(encrypted);
}
public String decrypt(String hexCiphertext)
throws IllegalBlockSizeException, BadPaddingException,
InvalidKeyException {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexCiphertext));
return byteArrayToHexString(decrypted);
}
private static String byteArrayToHexString(byte[] raw) {
String hex = "0x";
String s = new String(raw);
for (int x = 0; x < s.length(); x++) {
char[] t = s.substring(x, x + 1).toCharArray();
hex += Integer.toHexString((int) t[0]).toUpperCase();
}
return hex;
}
private static byte[] hexStringToByteArray(String hex) {
Pattern replace = Pattern.compile("^0x");
String s = replace.matcher(hex).replaceAll("");
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte) v;
}
return b;
}
public static void main(String[] args) {
try {
AESJavaScript ajs = new AESJavaScript();
ajs.setKey("Secret Passphrase");
String hexCiphertext = "U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=";
String decrypted = ajs.decrypt(hexCiphertext);
System.out.println("decrypted > " + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
}
例外是:
java.security.InvalidKeyException: Invalid AES key length: 17 bytes
at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372)
at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010)
at javax.crypto.Cipher.implInit(Cipher.java:786)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1213)
at javax.crypto.Cipher.init(Cipher.java:1153)
at com.test.jenkins.jenkinsRestart.AESJavaScript.decrypt(AESJavaScript.java:49)
at com.test.jenkins.jenkinsRestart.AESJavaScript.main(AESJavaScript.java:82)
我在这里做错什么了吗,或者还有其他简单的方法可以进行这种加密和解密吗?
解决方法:
您的Java代码到处都是错误.这里有几个:
>最初的异常是由于“密码密码”字符串包含17个字节而引起的.您需要将其截断为16个字节(或将其填充以匹配24或32个字节).您需要匹配CryptoJS库的行为.
>您正在尝试对似乎是base64编码的数据进行十六进制解码.尝试使用DatatypeConverter.parseBase64Binary(hex);.
>您正在使用算法“ AES / CTR / NoPadding”创建密钥.这无效,只需使用“ AES”.
>您必须在解密中传递IV / nonce值:
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(...));
您使用的值将取决于CryptoJS在做什么.也许它使用全零?也许它会生成一个随机的密码,您需要将其与密文一起存储吗?
这应该足以让您入门.