专栏首页WindCoder进击微信小程序-Java版AES/CBC/PKCS7Padding加解密字符串

进击微信小程序-Java版AES/CBC/PKCS7Padding加解密字符串

前言

进击微信小程序,最初找到腾讯云给的解决方案,无奈后端是node.js,而且才一开始配上去还不能用,之后仔细看readme,摸到它开源的Wafer,本来以为找到终极解决方案了,仔细看后,发现提供的java方面仅有业务服务器端的代码(要不要如此“歧视”= =),会话服务器只有一个php版的,信道服务。。就更不用说了。于是乎只能自己啃了。

正庆幸之前看过一点php基础,等走到加密解密那,满心欢喜的下载完实例代码,吃惊的发现里面居然有没有java(此时内心可谓是一群动物在奔腾)。但是在崩溃也得向前啊,于是只能默默忍受着十万点真实伤害去搜索相关的解密方式。万幸的是,终于找到了个类似的,接着对照wafer的php版七改八改,还真完成了。

到目前为止实现了java版会话服务器端的移植,至于信道服务,由于暂时接到新需求,无法继续探索,只好暂时作罢,待过段时间继续来过。至于放出的嘛。。暂时就只有这个解密代码,完整的java会话还是过段时间有心情再放出吧,反正这个有了,小伙伴们估计很快也能完成自己的,而且。。毕竟公司都没来得及用上呢(不服?来咬我呀= =)。

这么萌你真的忍心么= =

主体

所需依赖

只需要一个jar包

maven可直接使用

  <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
    <dependency>
      <groupId>org.bouncycastle</groupId>
      <artifactId>bcprov-jdk15on</artifactId>
      <version>1.55</version>
    </dependency>

非maven,可直接下载

下载地址:http://www.bouncycastle.org/archive/139/bcprov-jdk16-139.jar

加解密类代码

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;

/**
 * Created by wind on 2016/12/24.
 */

/**
 *
 * @author ngh
 * AES128 算法
 *
 * CBC 模式
 *
 * PKCS7Padding 填充模式
 *
 * CBC模式需要添加一个参数iv--对称解密算法初始向量 iv
 *
 * 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别
 * 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
 */
public class Pkcs7Encoder {
    // 算法名称
    static  final String KEY_ALGORITHM = "AES";
    // 加解密算法/模式/填充方式
    static  final String algorithmStr = "AES/CBC/PKCS7Padding";
    private static Key key;
    private static Cipher cipher;
    boolean isInited = false;

    //默认对称解密算法初始向量 iv
    static byte[] iv = { 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x38 };

    public static void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr, "BC");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 加密方法
     *      --使用默认iv时
     * @param content
     *            要加密的字符串
     * @param keyBytes
     *            加密密钥
     * @return
     */
    public static byte[] encrypt(byte[] content, byte[] keyBytes) {
        byte[] encryptedText =  encryptOfDiyIV(content,keyBytes,iv);
        return encryptedText;
    }


    /**
     * 解密方法
     *      --使用默认iv时
     * @param encryptedData
     *            要解密的字符串
     * @param keyBytes
     *            解密密钥
     * @return
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
        byte[] encryptedText = decryptOfDiyIV(encryptedData,keyBytes,iv);
        return encryptedText;
    }
    /**
     * 加密方法
     *      ---自定义对称解密算法初始向量 iv
     * @param content
     *              要加密的字符串
     * @param keyBytes
     *              加密密钥
     * @param ivs
     *         自定义对称解密算法初始向量 iv
     * @return 加密的结果
     */
    public static byte[] encryptOfDiyIV(byte[] content, byte[] keyBytes, byte[] ivs) {
        byte[] encryptedText = null;
        init(keyBytes);
        System.out.println("IV:" + new String(ivs));
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivs));
            encryptedText = cipher.doFinal(content);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }
    /**
     * 解密方法
     *
     * @param encryptedData
     *            要解密的字符串
     * @param keyBytes
     *            解密密钥
     * @param ivs
     *         自定义对称解密算法初始向量 iv
     * @return
     */
    public static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes,byte[] ivs) {
        byte[] encryptedText = null;
        init(keyBytes);
        System.out.println("IV:" + new String(ivs));
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }
}

测试结果

测试类中的Base64解码是将java8的Base64加解码封装了一下,请根据实际情况自行完成解码工作(解码的jar与方法太多了,就不在这统一了)。

测试类

测试类

public class Test {

    public static void main(String[] args) { 
        String  encryptedData = "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew==";
        String iv="r7BXXKkLb8qrSNn05n0qiA==";
        String appid = "wx4f4bc4dec97d474b";
        String sessionKey = "tiihtNczf5v6AKRyjwEUhQ==";
        toStr(appid,sessionKey,encryptedData,iv);
    }

    private static void  toStr(String appid,String sessionKey,String  encryptedData ,String iv){
        byte[] sessionKeyBy = Base64Util.decode(sessionKey);
        byte[] encryptedDataBy = Base64Util.decode(encryptedData);
        byte[] ivBy = Base64Util.decode(iv);
        byte[] dec = Pkcs7Encoder.decryptOfDiyIV(encryptedDataBy, sessionKeyBy,ivBy);
        JSONObject h = new JSONObject(new String(dec));
        if(h.has("openId")){
            System.out.println("解密后的内容:" +h.toString() );
        }

    }

}

效果图

附录

参考资料

Java 使用AES/CBC/PKCS7Padding 加解密字符串

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • DateUtil-常用关于date的工具类备份

    汐楓
  • IDEA常用设置

    setting -> Editor ->code style ->line separator(for new files)

    汐楓
  • Elixir和OTP中面向过程的编程指南

    这篇文章感觉介绍语言是次,讲解各种各种分类以及面向过程的思想为主。本身我也没接触过Elixir,这次也权当开拓视野了。最后附加了一个英语单词的小解,当学习之余的...

    汐楓
  • 如何从零开始用PyTorch实现Chatbot?(附完整代码)

    作者 | 李理,环信人工智能研发中心vp,十多年自然语言处理和人工智能研发经验。主持研发过多款智能硬件的问答和对话系统,负责环信中文语义分析开放平台和环信智能机...

    AI科技大本营
  • 什么是 Multiagent Q Learning

    multiagent 是指同时有多个 agent 更新 value 和 Q 函数,主要的算法有:q learning, friend and foe q lea...

    杨熹
  • 七张图告诉你移动互联网时代的商业模式

    大数据文摘
  • 七张图告诉你移动互联网时代的商业模式

    导读:伴随着智能手机的普及和4G技术的推广,移动互联网时代已经不约而至。O2O,P2P等一系列新词不禁让人眼花缭乱,颇有“乱花渐入迷人眼”之感。在这些喧嚣背后,...

    华章科技
  • 027.Zabbix的定期备份

    Zabbix提供将所有配置导出为标准XML格式文件,也支持导入标准格式的XML配置文件。

    木二
  • Bytom交易说明(账户管理模式)

    Gitee地址:https://gitee.com/BytomBlockchain/bytom

    比原链Bytom
  • Bytom交易说明(账户管理模式)

    API接口 build-transaction,代码api/transact.go#L120

    比原链Bytom

扫码关注云+社区

领取腾讯云代金券