JAVA 微信小程序 解密 用户信息 encryptedData,linux 系统架构与目录解析
@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 para
meters = 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;
}
/**
微信 数据解密<br/>
对称解密使用的算法为 AES-128-CBC,数据采用 PKCS#7 填充<br/>
对称解密的目标密文:encrypted=Base64_Decode(encryptData)<br/>
对称解密秘钥:key = Base64_Decode(session_key),aeskey 是 16 字节<br/>
对称解密算法初始向量:iv = Base64_Decode(iv),同样是 16 字节<br/>
@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;
}
/**
初始化密钥
*/
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<String> 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);
}
//使用 finally 块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
评论