public static final String KEY_NAME = “AES”;
// 加解密算法/模式/填充方式
// ECB模式只用密钥即可对数据进行加密解密,CBC模式需要添加一个iv
public static final String CIPHER_ALGORITHM = “AES/CBC/PKCS7Padding”;
/**
-
微信小程序-个人信息解密
-
@param encryptedData
-
@param sessionKey
-
@param iv
-
@return
*/
public static String getUserInfo(String encryptedData, String sessionKey, String iv) {
String result = “”;
// 被加密的数据
byte[] dataByte = Base64.decodeBase64(encryptedData);
// 加密秘钥
byte[] keyByte = Base64.decodeBase64(sessionKey);
// 偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
int base = 16;
if (keyByte.length % base != 0) {
int groups = keyByte.length / base
- (keyByte.length % base != 0 ? 1 : 0);
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS7Padding”, “BC”);
SecretKeySpec spec = new SecretKeySpec(keyByte, “AES”);
AlgorithmParameters parameters = AlgorithmParameters
.getInstance(“AES”);
parameters.init(new IvParameterSpec(ivByte));
// 初始化
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
result = new String(resultByte, “UTF-8”);
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
return result;
}
/**
-
获取微信小程序 session_key 和 openid
-
@param code 调用微信登陆返回的Code
-
@return
*/
public JSONObject getSessionKeyAndOpenid(String code) {
//微信端登录code值
String wxCode = code;
//请求地址 https://api.weixin.qq.com/sns/jscode2session
String requestUrl = “https://api.weixin.qq.com/sns/jscode2session”;
Map<String, String> requestUrlParam = new HashMap<>();
//开发者设置中的appId
requestUrlParam.put(“appid”, appId);
//开发者设置中的appSecret
requestUrlParam.put(“secret”, appSecret);
//小程序调用wx.login返回的code
requestUrlParam.put(“js_code”, wxCode);
//默认参数 authorization_code
requestUrlParam.put(“grant_type”, “authorization_code”);
//发送post请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session 接口获取openid用户唯一标识
JSONObject jsonObject = JSON.parseObject(sendPost(requestUrl, requestUrlParam));
return jsonObject;
}
/**
-
微信 数据解密
-
对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
-
对称解密的目标密文:encrypted=Base64_Decode(encryptData)
-
对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节
-
对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节
-
@param encrypted 目标密文
-
@param session_key 会话ID
-
@param iv 加密算法的初始向量
*/
public static String wxDecrypt(String encrypted, String session_key, String iv) {
String json = null;
byte[] encrypted64 = org.apache.tomcat.util.codec.binary.Base64.decodeBase64(encrypted);
byte[] key64 = org.apache.tomcat.util.codec.binary.Base64.decodeBase64(session_key);
byte[] iv64 = org.apache.tomcat.util.codec.binary.Base64.decodeBase64(iv);
byte[] data;
try {
init();
json = new String(decrypt(encrypted64, key64, generateIV(iv64)));
} catch (Exception e) {
e.printStackTrace();
}
return json;
}
/
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
**
- 初始化密钥
*/
public static void init() throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyGenerator.getInstance(KEY_NAME).init(128);
}
/**
- 生成iv
*/
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
// iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
// Arrays.fill(iv, (byte) 0x00);
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
params.init(new IvParameterSpec(iv));
return params;
}
/**
- 生成解密
*/
public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)
throws Exception {
Key key = new SecretKeySpec(keyBytes, KEY_NAME);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return cipher.doFinal(encryptedData);
}
/**
-
向指定 URL 发送POST方法的请求
-
@param url 发送请求的 URL
-
@return 所代表远程资源的响应结果
*/
public String sendPost(String url, Map<String, ?> paramMap) {
PrintWriter out = null;
BufferedReader in = null;
String result = “”;
String param = “”;
Iterator it = paramMap.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
param += key + “=” + paramMap.get(key) + “&”;
}
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty(“accept”, “/”);
conn.setRequestProperty(“connection”, “Keep-Alive”);
conn.setRequestProperty(“Accept-Charset”, “utf-8”);
conn.setRequestProperty(“user-agent”, “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)”);
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), “UTF-8”));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}