Java实现微信小程序加密数据解密算法
Posted kuku_zhongzi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java实现微信小程序加密数据解密算法相关的知识,希望对你有一定的参考价值。
Java实现微信小程序加密数据解密算法
一.概述
微信推出了小程序,很多公司的客户端应用不仅具有了APP、H5、还接入了小程序开发。但是,小程序中竟然没有提供Java版本的加密数据解密算法。
微信小程序提供的加密数据解密算法链接为
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
二.实现Java版本的微信小程序加密数据解密算法
- 1.配置pom.xml
我们在pom.xml中加入如下配置,其中bcprov-jdk15on是为了支持AES的BouncyCastleProvider,而commons-codec则是为了顺利的对session_key,iv,encryptData进行Base64的编解码
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.29</version>
</dependency>
- 2.封装WxDecryptUtil 解密工具类
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Arrays;
/**
* 封装工具类
* @author kuku_zhongzi
*/
public class WxDecryptUtil
public static boolean initialized = false;
private static final String WATERMARK = "watermark";
private static final String APPID = "appid";
/**
* 解密数据
*/
public static String decrypt(String appId, String encryptedData, String sessionKey, String iv)
String result = "";
try
byte[] resultByte = decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
if (null != resultByte && resultByte.length > 0)
result = new String(decode(resultByte));
JSONObject jsonObject = JSONObject.fromObject(result);
String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
if (!appId.equals(decryptAppid))
result = "";
catch (Exception e)
result = "";
e.printStackTrace();
return result;
/**
* @param content 密文
*/
public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte)
initialize();
try
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
byte[] result = cipher.doFinal(content);
return result;
catch (NoSuchAlgorithmException e)
e.printStackTrace();
catch (NoSuchPaddingException e)
e.printStackTrace();
catch (InvalidKeyException e)
e.printStackTrace();
catch (IllegalBlockSizeException e)
e.printStackTrace();
catch (BadPaddingException e)
e.printStackTrace();
catch (NoSuchProviderException e)
// TODO Auto-generated catch block
e.printStackTrace();
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
return null;
public static void initialize()
if (initialized)
return;
Security.addProvider(new BouncyCastleProvider());
initialized = true;
// 生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
/**
* 删除解密后明文的补位字符
*
* @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);
三.测试
以下数据都是测试数据 仅供学习参考
微信的js_code时效性只有一次,用过一次之后不能再用了,注意查看
js_code 用于获取openid、sessionKey、appId
@Test
public void test() throws Exception
String appId = "wx4f4bc4dec97d474b";
String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==";
String sessionKey = "tiihtNczf5v6AKRyjwEUhQ==";
String iv = "r7BXXKkLb8qrSNn05n0qiA==";
JSONObject jsonObject = JSON.parseObject(WxDecryptUtil.decrypt(appId, encryptedData, sessionKey, iv));
// jsonObject => "phoneNumber": "13580006666","purePhoneNumber": "13580006666","countryCode": "86","watermark":"appid":"APPID", "timestamp": 1618983
System.out.println("用户绑定的手机号(国外手机号会有区号):" + jsonObject.getString("phoneNumber")); // 13580006666
System.out.println("不带区号的手机号:" + jsonObject.getString("purePhoneNumber")); // 13580006666
System.out.println("区号:" + jsonObject.getString("countryCode")); // 86
亲测:运行结果和微信官网示例一致
附:
jar包下载地址:http://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16/1.46
以上是关于Java实现微信小程序加密数据解密算法的主要内容,如果未能解决你的问题,请参考以下文章
微信小程序session_key解析中反斜杠问题处理 Java解析