Java之——实现微信小程序加密数据解密算法

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/79450115

一、概述

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

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

最新地址为:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html

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

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

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

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

1、创建项目

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

2、配置pom.xml

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

1<dependency> 2 <groupId>org.bouncycastle</groupId> 3 <artifactId>bcprov-jdk16</artifactId> 4 <version>1.46</version> 5</dependency> 6 7 <dependency> 8 <groupId>commons-codec</groupId> 9 <artifactId>commons-codec</artifactId> 10 <version>1.4</version> 11</dependency> 12 13<dependency> 14 <groupId>net.sf.json-lib</groupId> 15 <artifactId>json-lib</artifactId> 16 <version>2.2.3</version> 17 <classifier>jdk15</classifier> 18</dependency>

3、实现AES类

1package com.chwl.medical.crypto.wx; 2 3import java.security.AlgorithmParameters; 4import java.security.InvalidAlgorithmParameterException; 5import java.security.InvalidKeyException; 6import java.security.Key; 7import java.security.NoSuchAlgorithmException; 8import java.security.NoSuchProviderException; 9import java.security.Security; 10 11import javax.crypto.BadPaddingException; 12import javax.crypto.Cipher; 13import javax.crypto.IllegalBlockSizeException; 14import javax.crypto.NoSuchPaddingException; 15import javax.crypto.spec.IvParameterSpec; 16import javax.crypto.spec.SecretKeySpec; 17import org.bouncycastle.jce.provider.BouncyCastleProvider; 18 19/** 20 * AES加密 21 * @author liuyazhuang 22 * 23 */ 24public class AES { 25 26 public static boolean initialized = false; 27 28 /** 29 * AES解密 30 * 31 * @param content 32 * 密文 33 * @return 34 * @throws InvalidAlgorithmParameterException 35 * @throws NoSuchProviderException 36 */ 37 public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { 38 initialize(); 39 try { 40 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); 41 Key sKeySpec = new SecretKeySpec(keyByte, "AES"); 42 cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化 43 byte[] result = cipher.doFinal(content); 44 return result; 45 } catch (NoSuchAlgorithmException e) { 46 e.printStackTrace(); 47 } catch (NoSuchPaddingException e) { 48 e.printStackTrace(); 49 } catch (InvalidKeyException e) { 50 e.printStackTrace(); 51 } catch (IllegalBlockSizeException e) { 52 e.printStackTrace(); 53 } catch (BadPaddingException e) { 54 e.printStackTrace(); 55 } catch (NoSuchProviderException e) { 56 // TODO Auto-generated catch block 57 e.printStackTrace(); 58 } catch (Exception e) { 59 // TODO Auto-generated catch block 60 e.printStackTrace(); 61 } 62 return null; 63 } 64 65 public static void initialize() { 66 if (initialized) 67 return; 68 Security.addProvider(new BouncyCastleProvider()); 69 initialized = true; 70 } 71 72 // 生成iv 73 public static AlgorithmParameters generateIV(byte[] iv) throws Exception { 74 AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); 75 params.init(new IvParameterSpec(iv)); 76 return params; 77 } 78}

4、实现WxPKCS7Encoder类

1package com.chwl.medical.crypto.wx; 2 3import java.nio.charset.Charset; 4import java.util.Arrays; 5 6 7/** 8 * 微信小程序加解密 9 * @author liuyazhuang 10 * 11 */ 12public class WxPKCS7Encoder { 13 private static final Charset CHARSET = Charset.forName("utf-8"); 14 private static final int BLOCK_SIZE = 32; 15 16 /** 17 * 获得对明文进行补位填充的字节. 18 * 19 * @param count 20 * 需要进行填充补位操作的明文字节个数 21 * @return 补齐用的字节数组 22 */ 23 public static byte[] encode(int count) { 24 // 计算需要填充的位数 25 int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE); 26 if (amountToPad == 0) { 27 amountToPad = BLOCK_SIZE; 28 } 29 // 获得补位所用的字符 30 char padChr = chr(amountToPad); 31 String tmp = new String(); 32 for (int index = 0; index < amountToPad; index++) { 33 tmp += padChr; 34 } 35 return tmp.getBytes(CHARSET); 36 } 37 38 /** 39 * 删除解密后明文的补位字符 40 * 41 * @param decrypted 42 * 解密后的明文 43 * @return 删除补位字符后的明文 44 */ 45 public static byte[] decode(byte[] decrypted) { 46 int pad = decrypted[decrypted.length - 1]; 47 if (pad < 1 || pad > 32) { 48 pad = 0; 49 } 50 return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); 51 } 52 53 /** 54 * 将数字转化成ASCII码对应的字符,用于对明文进行补码 55 * 56 * @param a 57 * 需要转化的数字 58 * @return 转化得到的字符 59 */ 60 public static char chr(int a) { 61 byte target = (byte) (a & 0xFF); 62 return (char) target; 63 } 64}

5、实现WXCore类

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

1package com.chwl.medical.crypto.wx; 2 3import org.apache.commons.codec.binary.Base64; 4 5import net.sf.json.JSONObject; 6 7 8/** 9 * 封装对外访问方法 10 * @author liuyazhuang 11 * 12 */ 13public class WXCore { 14 15 private static final String WATERMARK = "watermark"; 16 private static final String APPID = "appid"; 17 /** 18 * 解密数据 19 * @return 20 * @throws Exception 21 */ 22 public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){ 23 String result = ""; 24 try { 25 AES aes = new AES(); 26 byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv)); 27 if(null != resultByte && resultByte.length > 0){ 28 result = new String(WxPKCS7Encoder.decode(resultByte)); 29 JSONObject jsonObject = JSONObject.fromObject(result); 30 String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID); 31 if(!appId.equals(decryptAppid)){ 32 result = ""; 33 } 34 } 35 } catch (Exception e) { 36 result = ""; 37 e.printStackTrace(); 38 } 39 return result; 40 } 41 42 43 public static void main(String[] args) throws Exception{ 44 String appId = "wx4f4bc4dec97d474b"; 45 String encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew=="; 46 String sessionKey = "tiihtNczf5v6AKRyjwEUhQ=="; 47 String iv = "r7BXXKkLb8qrSNn05n0qiA=="; 48 System.out.println(decrypt(appId, encryptedData, sessionKey, iv)); 49 } 50}
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )