# AES Pkcs7加密/解密工具类,支持密钥偏移量

# Java代码

package com.guitu18.common.utils;

import cn.hutool.core.util.HexUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;

/**
 * AES Pkcs7加密/解密工具类,支持密钥偏移量
 * <p>
 * 介于java 不支持PKCS7Padding,只支持PKCS5Padding,但是PKCS7Padding和PKCS5Padding没有什么区别
 * 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
 * 代码参考:https://www.cnblogs.com/chen-lhx/p/6233954.html(有修改)
 *
 * @author zhangkuan
 * @date 2020/5/4
 */
public class AesPkcs7Util {

    /**
     * 算法名称
     */
    final String KEY_ALGORITHM = "AES";
    /**
     * 加解密算法/模式/填充方式
     */
    final String algorithmStr = "AES/CBC/PKCS7Padding";

    private static SecretKey key;
    private static AlgorithmParameterSpec iv;
    private Cipher cipher;


    public AesPkcs7Util(String keyStr, String ivStr) {
        // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
        byte[] keyBytes = keyStr.getBytes();
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + 1;
            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);
        iv = new IvParameterSpec(ivStr.getBytes());
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr, "BC");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | NoSuchProviderException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加密方法
     *
     * @param content 要加密的字符串
     */
    public byte[] encrypt(byte[] content) {
        byte[] encryptedText = null;
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, iv);
            encryptedText = cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedText;
    }

    /**
     * 解密方法
     *
     * @param encryptedData 要解密的字符串
     */
    public byte[] decrypt(byte[] encryptedData) {
        byte[] encryptedText = null;
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, iv);
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedText;
    }

    public static void main(String[] args) {
        AesPkcs7Util aes = new AesPkcs7Util("625202f9149guitu", "5efd3f60608guitu");
        String content = "encryptedData 要解密的字符串";
        byte[] enc = aes.encrypt(content.getBytes());
        String hexStr = HexUtil.encodeHexStr(enc);
        System.out.println("加密后的内容:" + hexStr);
        byte[] dec = aes.decrypt(HexUtil.decodeHex(hexStr));
        System.out.println("解密后的内容:" + new String(dec));
    }

}

# JavaScript代码

使用之前需要引入 crypto-js.js,源码地址:https://github.com/brix/crypto-js

    // 十六位十六进制数作为密钥
    const key = CryptoJS.enc.Utf8.parse("625202f9149guitu");
    //十六位十六进制数作为密钥偏移量
    const iv = CryptoJS.enc.Utf8.parse('5efd3f60608guitu');

    //解密方法
    function decrypt(word) {
        let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
        let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
        let decrypt = CryptoJS.AES.decrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });
        let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
        return decryptedStr.toString();
    }

    //加密方法
    function encrypt(word) {
        let srcs = CryptoJS.enc.Utf8.parse(word);
        let encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });
        return encrypted.ciphertext.toString();
    }

    // Test
    var encryptStr = encrypt('encryptedData 要解密的字符串');
    console.log(encryptStr);

    var decryptStr = decrypt(encryptStr);
    console.log(decryptStr);