https://smartprogram.baidu.com/docs/develop/api/open_log/#用户数据的签名验证和加解密/
百度小程序 对 用户数据的签名验证和解密
BaiduDecryptUtil.java
import java.nio.charset.Charset;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class BaiduDecryptUtil {
private static Charset CHARSET = Charset.forName("utf-8");
/**
* 对密文进行解密
*
* @param text 需要解密的密文
*
* @return 解密得到的明文
* @throws Exception 异常错误信息
* @author xjin21cen
*/
public String decrypt(String text, String sessionKey)
throws Exception{
byte [] aesKey = Base64.decodeBase64(sessionKey + "=");
byte[] original;
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
byte[] encrypted = Base64.decodeBase64(text);
original = cipher.doFinal(encrypted);
} catch (Exception e) {
throw new Exception(e);
}
String xmlContent;
String fromClientId;
try {
// 去除补位字符
byte[] bytes = PKCS7Encoder.decode(original);
// 分离16位随机字符串,网络字节序和ClientId
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
int xmlLength = recoverNetworkBytesOrder(networkOrder);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
fromClientId = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
} catch (Exception e) {
throw new Exception(e);
}
return xmlContent;
}
/**
* 还原4个字节的网络字节序
*
* @param orderBytes 字节码
*
* @return sourceNumber
*/
private int recoverNetworkBytesOrder(byte[] orderBytes) {
int sourceNumber = 0;
int length = 4;
int number = 8;
for (int i = 0; i < length; i++) {
sourceNumber <<= number;
sourceNumber |= orderBytes[i] & 0xff;
}
return sourceNumber;
}
/**
* 加密机密demo
* @param args
* @throws MobileException
*/
public static void main(String[] args) throws Exception{
String ecryptData= "OpCoJgs7RrVgaMNDixIvaCIyV2SFDBNLivgkVqtzq2GC10egsn+PKmQ/+5q+chT8xzldLUog2haTItyIkKyvzvmXonBQLIMeq54axAu9c3KG8IhpFD6+ymHocmx07ZKi7eED3t0KyIxJgRNSDkFk5RV1ZP2mSWa7ZgCXXcAbP0RsiUcvhcJfrSwlpsm0E1YJzKpYy429xrEEGvK+gfL+Cw==";
String sessionKey = "1df09d0a1677dd72b8325aec59576e0c";
BaiduDecryptUtil demo = new BaiduDecryptUtil();
String jsonStr= demo.decrypt(ecryptData, sessionKey);
System.out.println(jsonStr);
}
}
输出:
{"openid":"open_id","nickname":"baidu_user","headimgurl":"url of image","sex":1}
PKCS7Encoder.java
import java.nio.charset.Charset;
import java.util.Arrays;
public class PKCS7Encoder {
private static final Charset CHARSET = Charset.forName("utf-8");
private static final int BLOCK_SIZE = 32;
/**
* 获得对明文进行补位填充的字节.
*
* @param count 需要进行填充补位操作的明文字节个数
* @return 补齐用的字节数组
*/
public static byte[] encode(int count) {
// 计算需要填充的位数
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0) {
amountToPad = BLOCK_SIZE;
}
// 获得补位所用的字符
char padChr = chr(amountToPad);
String tmp = new String();
for (int index = 0; index < amountToPad; index++) {
tmp += padChr;
}
return tmp.getBytes(CHARSET);
}
/**
* 删除解密后明文的补位字符
*
* @param decrypted 解密后的明文
* @return 删除补位字符后的明文
*/
public static byte[] decode(byte[] decrypted) {
int pad = decrypted[decrypted.length - 1];
if (pad < 1 || pad > 32) {
pad = 0;
}
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
}
/**
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
*
* @param a 需要转化的数字
* @return 转化得到的字符
*/
public static char chr(int a) {
byte target = (byte) (a & 0xFF);
return (char) target;
}
}
异常
执行时,如果抛 java.security.InvalidKeyException: Illegal key size or default parameters
异常,解决办法请参考 https://blog.csdn.net/xiaojin21cen/article/details/85233645