gpt4 book ai didi

java - 将 JSON 与 AES 一起使用会引发 javax.crypto.IllegalBlockSizeException

转载 作者:太空宇宙 更新时间:2023-11-04 10:47:25 25 4
gpt4 key购买 nike

当我使用 AES/CBC/PKCS5Padding 加密普通的 String 时,没有问题。

当我使用包含典型 JSON 类型数据的 JSON String 时,它在执行解密时抛出异常:

完全异常:

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:936)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at io.crypto.Crypto.doFinal(Crypto.java:60)
at io.crypto.Crypto.decrypt(Crypto.java:50)
at io.Controller.main(Controller.java:38)

AES 代码:

public class Crypto {

private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'b', 'c', 'D', 'e', 'F'};
private static Cipher cipher;

public static void init() {

try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
NetworkModule.handleException(e);
}

}

public static String encrypt(String password, String message) throws Exception {

String salt = random(16);
String iv = random(16);
SecretKey key = generateKey(salt, password);
byte[] encrypted = doFinal(Cipher.ENCRYPT_MODE, key, iv, message.getBytes("UTF-8"));
String code = Base64.getEncoder().encodeToString(encrypted);
return salt + code.substring(0, code.length() - 2) + iv;

}

public static String decrypt(String password, String message) throws Exception {

String salt = message.substring(0, 32);
String iv = message.substring(message.length() - 32, message.length());
String base = message.substring(32, message.length() - 32) + "==";
SecretKey key = generateKey(salt, password);
byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, Base64.getDecoder().decode(base));
return new String(decrypted, "UTF-8");

}

private static byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) {

try {

cipher.init(encryptMode, key, new IvParameterSpec(hex(iv)));
return cipher.doFinal(bytes);

} catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
NetworkModule.handleException(e);
return null;
}

}

private static SecretKey generateKey(String salt, String passphrase) {

try {

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), 1000, 128);
SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
return key;

} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
NetworkModule.handleException(e);
return null;
}

}

private static String random(int length) {
byte[] salt = new byte[length];
new SecureRandom().nextBytes(salt);
return hex(salt);
}

private static String hex(byte[] data) {

int l = data.length;
char[] out = new char[l << 1];
int i = 0;

for (int var5 = 0; i < l; ++i) {
out[var5++] = HEX[(240 & data[i]) >>> 4];
out[var5++] = HEX[15 & data[i]];
}

return new String(out);

}

private static byte[] hex(String hex) {

char[] data = hex.toCharArray();
int len = data.length;

if ((len & 1) != 0) {
return null;
} else {

byte[] out = new byte[len >> 1];
int i = 0;

for (int j = 0; j < len; ++i) {

int f = Character.digit(data[j], 16) << 4;
++j;
f |= Character.digit(data[j], 16);
++j;
out[i] = (byte) (f & 255);

}

return out;

}

}

}

工作示例:

Crypto.init();
String password = "42cb54a0b6a89a53709301ee320f45de102dda05ccd1a49c3c62c19b7319ca73";
String message = "Hello World";
System.out.println(message);
String encrypt = Crypto.encrypt(password, message);
System.out.println(encrypt);
String decrypt = Crypto.decrypt(password, encrypt);
System.out.println(decrypt);

输出:

Hello World
3cc6b607175011Fc50bb498c8064863ebbAePnO7nmGSFLBr2KnfhQDAb84b338007b4e3e9bbFF3e35b0341A
Hello World

异常示例:

Crypto.init();
String password = "42cb54a0b6a89a53709301ee320f45de102dda05ccd1a49c3c62c19b7319ca73";
String message = new PacketBuilder("example").build();
System.out.println(message);
String encrypt = Crypto.encrypt(password, message);
System.out.println(encrypt);
String decrypt = Crypto.decrypt(password, encrypt);
System.out.println(decrypt);

输出:

{"packet":"EXAMPLE"}
6b1FbA86e4F17A21633AA12c352eAD63ebKIw+ljAx4XsqBgK5Q3KQ2Hd5w8nO4NP9sqxC+CLI0A4D2e4AbF47ecF6b6149A8F2445658F
Exception in thread "main" ... full stacktrace on the top of the post

最佳答案

好的,我已经找到问题了。

在检查变量时,我发现在加密方法中打印代码会产生一个以单个空格结尾的字符串。但是,您切断了子字符串中的两个字母,因此您需要做的第一件事就是在该方法中重写您的返回,如下所示

        return salt + code.replace("=","") + iv;

接下来,每当您要从基础解码时,您都会执行此操作

        String base = message.substring(32, message.length() - 32) + "==";

但这不是必需的,所以像这样改变它

        String base = message.substring(32, message.length() - 32);

更改这些后,您的方法应该可以工作。

关于java - 将 JSON 与 AES 一起使用会引发 javax.crypto.IllegalBlockSizeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48241140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com