zoukankan      html  css  js  c++  java
  • 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中加入如下配置。

    <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));
        }
    }
  • 相关阅读:
    < java.util >-- Set接口
    Codeforces 627 A. XOR Equation (数学)
    Codeforces 161 B. Discounts (贪心)
    Codeforces 161 D. Distance in Tree (树dp)
    HDU 5534 Partial Tree (完全背包变形)
    HDU 5927 Auxiliary Set (dfs)
    Codeforces 27E. Number With The Given Amount Of Divisors (暴力)
    lght oj 1257
    Codeforces 219D. Choosing Capital for Treeland (树dp)
    Codeforces 479E. Riding in a Lift (dp + 前缀和优化)
  • 原文地址:https://www.cnblogs.com/chenziyu/p/10271564.html
Copyright © 2011-2022 走看看