A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

【转载】        https://blog.csdn.net/l1028386804/article/details/79450115

一、概述

微信推出了小程序,很多公司的客户端应用不仅具有了APP、H5、还接入了小程序开发。但是,小程序中竟然没有提供Java版本的加密数据解密算法。这着实让广大的Java开发人员蛋疼。

微信小程序提供的加密数据解密算法链接为:https://mp.weixin.qq.com/debug/wxadoc/dev/api/signature.html

我们下载的算法示例如下:


木有Java!! 木有Java!! 木有Java!!

那么如何解决这个问题,我们一起来实现Java版本的微信小程序加密数据解密算法。

二、实现Java版本的微信小程序加密数据解密算法
1、创建项目

这里,我们创建一个Maven工程,具体创建步骤略。

2、配置pom.xml

我们在pom.xml中加入如下配置。



  • <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.4</version>



  • </dependency>







  • <dependency>



  •     <groupId>net.sf.json-lib</groupId>



  •     <artifactId>json-lib</artifactId>



  •     <version>2.2.3</version>



  •     <classifier>jdk15</classifier>



  • </dependency>


3、实现AES类


  • package com.chwl.medical.crypto.wx;







  • import java.security.AlgorithmParameters;



  • import java.security.InvalidAlgorithmParameterException;



  • import java.security.InvalidKeyException;



  • import java.security.Key;



  • import java.security.NoSuchAlgorithmException;



  • import java.security.NoSuchProviderException;



  • import java.security.Security;







  • 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 org.bouncycastle.jce.provider.BouncyCastleProvider;







  • /**



  • * AES加密



  • * @author liuyazhuang



  • *



  • */



  • public class AES {







  •         public static boolean initialized = false;







  •         /**



  •          * AES解密



  •          *



  •          * @param content



  •          *            密文



  •          * @return



  •          * @throws InvalidAlgorithmParameterException



  •          * @throws NoSuchProviderException



  •          */



  •         public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {



  •                 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;



  •         }



  • }


4、实现WxPKCS7Encoder类


  • package com.chwl.medical.crypto.wx;







  • import java.nio.charset.Charset;



  • import java.util.Arrays;











  • /**



  • * 微信小程序加解密



  • * @author liuyazhuang



  • *



  • */



  • public class WxPKCS7Encoder {



  •         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;



  •         }



  • }


5、实现WXCore类

这个类主要是对具体算法的封装,统一对外提供方法。



  • package com.chwl.medical.crypto.wx;







  • import org.apache.commons.codec.binary.Base64;







  • import net.sf.json.JSONObject;











  • /**



  • * 封装对外访问方法



  • * @author liuyazhuang



  • *



  • */



  • public class WXCore {







  •         private static final String WATERMARK = "watermark";



  •         private static final String APPID = "appid";



  •         /**



  •          * 解密数据



  •          * @return



  •          * @throws Exception



  •          */



  •         public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){



  •                 String result = "";



  •                 try {



  •                         AES aes = new AES();  



  •                     byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));  



  •                     if(null != resultByte && resultByte.length > 0){  



  •                         result = new String(WxPKCS7Encoder.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;



  •         }











  •         public static void main(String[] args) 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==";



  •        System.out.println(decrypt(appId, encryptedData, sessionKey, iv));



  •     }



  • }


三、测试1、运行Java版微信小程序加密数据解密算法

这里我们就直接运行WXcore类的main方法,这里的测试数据都是从Python版微信小程序加密数据解密算法的示例程序中提出来的。我们的运行结果如下:

{"openId":"oGZUI0egBJY1zhBYw2KhdUfwVJJE","nickName":"Band","gender":1,"language":"zh_CN","city":"Guangzhou","province":"Guangdong","country":"CN","avatarUrl":"http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0","unionId":"ocMvos6NjeKLIBqg5Mr9QjxrP1FA","watermark":{"timestamp":1477314187,"appid":"wx4f4bc4dec97d474b"}}2、运行Python版微信小程序加密数据解密算法

这里我们在python环境中直接运行微信官方提供的Python版小程序加密数据解密算法,结果如下:

{u'province': u'Guangdong', u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE', u'language': u'zh_CN', u'city': u'Guangzhou', u'gender': 1, u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0', u'watermark': {u'timestamp': 1477314187, u'appid': u'wx4f4bc4dec97d474b'}, u'country': u'CN', u'nickName': u'Band', u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA'}通过对比以上结果可知,我们自行使用Java实现的Java版微信小程序加密数据解密算法与微信官方提供的Python版小程序加密数据解密算法结果一致。


3 个回复

倒序浏览
奈斯,加油加油
回复 使用道具 举报
奈斯,加油加油
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马