开发微信小程序的时候,第三方应用服务器需要解密微信服务器给的加密数据。当时小程序官方没有给出Java实现。网上的解决方案基本都差不多,但是示例代码不够清晰,逻辑混乱,这里整理一下。
1. Maven引入三方包
Java SE自带的加解密工具包不支持AES/CBC/PKCS7Padding。
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.55</version>
</dependency>
2. 测试方法
①进行加解密之前注意导入支持AES/CBC/PKCS7Padding的Provider。
②Base64只是一种编码解码工具,数据编码后,便于网络上传输。跟加解密没关系。
public static void main(String[] args) throws Exception {
//原始数据
String data = "i am data";
//密钥
String sessionKey = "i am strong key ";
//向量
String iv = "i am iv i am iv ";
//用Base64编码
Base64.Encoder encoder = Base64.getEncoder();
String baseData = encoder.encodeToString(data.getBytes());
String baseSessionKey = encoder.encodeToString(sessionKey.getBytes());
String baseIv = encoder.encodeToString(iv.getBytes());
//导入支持AES/CBC/PKCS7Padding的Provider
Security.addProvider(new BouncyCastleProvider());
//获取加密数据
String encryptedData = encrypt(baseData,baseSessionKey,baseIv);
//通过加密数据获得原始数据
String dataReborn = decrypt(encryptedData,baseSessionKey,baseIv);
//打印解密出来的原始数据
System.out.println(dataReborn);
}
3. 加密方法
public static String encrypt(String data,String sessionKey,String iv) throws Exception {
//加密之前,先从Base64格式还原到原始格式
Decoder decoder = Base64.getDecoder();
byte[] dataByte = decoder.decode(data);
byte[] keyByte = decoder.decode(sessionKey);
byte[] ivByte = decoder.decode(iv);
String encryptedData = null;
//指定算法,模式,填充方式,创建一个Cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
//生成Key对象
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
//把向量初始化到算法参数
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(ivByte));
//指定用途,密钥,参数 初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, params);
//指定加密
byte[] result = cipher.doFinal(dataByte);
//对结果进行Base64编码,否则会得到一串乱码,不便于后续操作
Base64.Encoder encoder = Base64.getEncoder();
encryptedData = encoder.encodeToString(result);
return encryptedData;
}
4. 解密方法
public static String decrypt(String encryptedData,String sessionKey,String iv) throws Exception {
//解密之前先把Base64格式的数据转成原始格式
Decoder decoder = Base64.getDecoder();
byte[] dataByte = decoder.decode(encryptedData);
byte[] keyByte = decoder.decode(sessionKey);
byte[] ivByte = decoder.decode(iv);
String data = null;
//指定算法,模式,填充方法 创建一个Cipher实例
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
//生成Key对象
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
//把向量初始化到算法参数
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(ivByte));
//指定用途,密钥,参数 初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);
//执行解密
byte[] result = cipher.doFinal(dataByte);
//解密后转成字符串
data = new String(result);
return data;
}
5. 结果
i am data