JAVA解密微信小程序用户信息encryptedData方案
首先我相信当各位大佬看到这个文章的时候,应该看过很多关于java解密微信小程序用户信息的方案了。
但是总会遇到一些问题,比如代码复制过来,导入正确的包也会遇到的问题拉~,这里我就发布一个自己遇到的问题,希望能帮助后面的人,这个坑很大哦~
废话不多说,贴代码
这个AES解密工具包,放在Util包下
import java.security.AlgorithmParameters;
import java.security.Key;
import java.util.Arrays;
import java.util.Base64;
import java.util.Base64.Decoder;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public final class AES {
public static final String KEY_ALGORITHM = "AES";
public static final String CIPHER_ALGORITHM = "AES/CBC/NoPadding";
// 生成密钥
public static byte[] generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
keyGenerator.init(128);
SecretKey key = keyGenerator.generateKey();
return key.getEncoded();
}
// 生成iv
public static AlgorithmParameters generateIV() throws Exception {
// iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
return generateIV(iv);
}
// 生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_ALGORITHM);
params.init(new IvParameterSpec(iv));
return params;
}
// 转化成JAVA的密钥格式
public static Key convertToKey(byte[] keyBytes) throws Exception {
SecretKey secretKey = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
return secretKey;
}
// 加密
public static byte[] encrypt(byte[] data, byte[] keyBytes, AlgorithmParameters iv) throws Exception {
// 转化为密钥
Key key = convertToKey(keyBytes);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
return cipher.doFinal(data);
}
// 解密
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception {
Key key = convertToKey(keyBytes);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(encryptedData);
}
}
调用方式
Decoder decoder = Base64.getDecoder();
try {
byte[] result = AES.decrypt(decoder.decode(encryptedData), decoder.decode(session_key),
AES.generateIV(decoder.decode(iv)));
String s=StringUtils.toString(result,"UTF-8");
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
那么当你走到这一步的时候,你很可能遇到的问题:
java.lang.IllegalArgumentException: Illegal base64 character 20
没错就是这个异常,问题的原因是因为 encryptedData 密文在进行http传输的时候按照W3C的规范给你把其中的+号变成了空格,
例如这个密文
TuuTLtXibxWa1L8uTBQciO4hah/LwFh95Ip8I/tNo1FbDlEbIk0USXr4d3mm91XaVZ7+CynILJcCih5bbSEcFJKQiua2yn48Fdu4WiXRKwU0RD49aldpZ9SGSU+AtzAsD3KbyUiStdfwaWhkeX37qnQeXucV0/irhZBkwFqg5EXHDvq+cOldXl6pVJt2oO3/4c0kBECfGavQ717QXKJLqnEaoDfh8Qfce678CeDwa6wYnR46Xu6fnBx5t0K53f5qKL9hZZtHlr28aFZ6kYVq06mEP+97E4HxDBZjU9ZuDZjKyIpcajA2GUKCgzqqwMQG7iYfl6br7Q2cjh6UFGs5p08Ofr/p9TPNPXJm0ErAfVghu5UuyVxGRerW2O9aEQjKdlUGztlGqMZVriky6TjpzVz/Uy7m4++B7Pd4cvWkYaZGDWb+MdwMP+KYXLGVwrQyhPuAcppQqZ9G92qeMZl4uMfFLwFO3B/+7ShE0Ulpies=
然后通过DEBUG查看后台接收到的密文
TuuTLtXibxWa1L8uTBQciO4hah/LwFh95Ip8I/tNo1FbDlEbIk0USXr4d3mm91XaVZ7 CynILJcCih5bbSEcFJKQiua2yn48Fdu4WiXRKwU0RD49aldpZ9SGSU AtzAsD3KbyUiStdfwaWhkeX37qnQeXucV0/irhZBkwFqg5EXHDvq cOldXl6pVJt2oO3/4c0kBECfGavQ717QXKJLqnEaoDfh8Qfce678CeDwa6wYnR46Xu6fnBx5t0K53f5qKL9hZZtHlr28aFZ6kYVq06mEP 97E4HxDBZjU9ZuDZjKyIpcajA2GUKCgzqqwMQG7iYfl6br7Q2cjh6UFGs5p08Ofr/p9TPNPXJm0ErAfVghu5UuyVxGRerW2O9aEQjKdlUGztlGqMZVriky6TjpzVz/Uy7m4 B7Pd4cvWkYaZGDWb MdwMP KYXLGVwrQyhPuAcppQqZ9G92qeMZl4uMfFLwFO3B/ 7ShE0Ulpies=
两个仔细对比一下,然后你感到惊喜了吗?特瞄的居然是把+号改成了空格。
所以各位在前台传输数据的时候一定要注意,可以把+号改成 %2B 这样后台在接收密文的时候,按照规范来讲%2B会自动变成+号了。