前后端配合使用AES/CBC/PKCS7Padding 实现加解密数据(crypto-js、bouncycastle-java)

5,794 阅读2分钟

安装

npm i crypto-js -S

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script type="text/javascript" src="node_modules/crypto-js/crypto-js.js"></script>
</head>
<body>
    <script type="text/javascript">
        // 偏移量
        let iv = "0000000000000000";
        // 加密内容
        let message = "abcd中文测试加标点符号!@#¥%……&*(+——)(*&~,。,;,,/;lkk;ki;'[p]./,'\\467646789";
        // 密钥,长度必须为16
        let secret_key = "1234567890123456";

        // utf-8 转换
        message = CryptoJS.enc.Utf8.parse(message);
        secret_key = CryptoJS.enc.Utf8.parse(secret_key);
        iv = CryptoJS.enc.Utf8.parse(iv);
       
        // Encrypt
        var ciphertext = CryptoJS.AES.encrypt(message, secret_key, { 
            iv: iv,
            mode: CryptoJS.mode.CBC, 
            padding: CryptoJS.pad.Pkcs7
        });
        console.log(ciphertext.toString());

        // Decrypt
        var bytes  = CryptoJS.AES.decrypt(ciphertext.toString(), secret_key,{
            iv: iv,
            mode: CryptoJS.mode.CBC, 
            padding: CryptoJS.pad.Pkcs7 
        });
        console.log(bytes.toString(CryptoJS.enc.Utf8));
    </script> 
    
</body>
</html>

java后端

package com.sgcc.atc.importUser.Utils.encrypted;

import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

 
public class AESpkcs7paddingUtil {
	
	/**
	 * 密钥算法
	 */
	private static final String KEY_ALGORITHM = "AES";
	
	/**
	 * 加密/解密算法 / 工作模式 / 填充方式
	 * Java 6支持PKCS5Padding填充方式
	 * Bouncy Castle支持PKCS7Padding填充方式
	 */
	private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
	
	/**
	 * 偏移量,只有CBC模式才需要
	 */
	private final static String ivParameter = "0000000000000000";
	
	/**
	 * AES要求密钥长度为128位或192位或256位,java默认限制AES密钥长度最多128位
	 */
	public static String sKey="" ;
	
	/**
	 * 编码格式
	 */
	public static final String ENCODING = "utf-8";
	
	
	static {
		//如果是PKCS7Padding填充方式,则必须加上下面这行
		Security.addProvider(new BouncyCastleProvider());
	}
	
	/**
	 * AES加密
	 * @param source	源字符串
	 * @param key	密钥
	 * @return	加密后的密文
	 * @throws Exception
	 */
	public static String encrypt(String source, String key) throws Exception {
		byte[] sourceBytes = source.getBytes(ENCODING);
		byte[] keyBytes = key.getBytes(ENCODING);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");  
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING));
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv);  
        byte[] decrypted = cipher.doFinal(sourceBytes);
        return Base64.encodeBase64String(decrypted);
	}
	
	/**
	 * AES解密
	 * @param encryptStr	加密后的密文
	 * @param key	密钥
	 * @return	源字符串
	 * @throws Exception
	 */
	public static String decrypt(String encryptStr, String key) throws Exception {
		byte[] sourceBytes = Base64.decodeBase64(encryptStr);
		byte[] keyBytes = key.getBytes(ENCODING);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, "BC");  
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(ENCODING));
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, KEY_ALGORITHM),iv);  
        byte[] decoded = cipher.doFinal(sourceBytes);  
        return new String(decoded, ENCODING);
	}
	
	
	public static void main(String[] args) throws Exception {
		String key = "1234567890123456";
		
		// 加密
		long lStart = System.currentTimeMillis();
		String enString = AESpkcs7paddingUtil.encrypt("abcd中文测试加标点符号!@#¥%……&*(+——)(*&~,。,;,,/;lkk;ki;'[p]./,'\\467646789",key);
		System.out.println("加密后的字串是:" + enString);

		long lUseTime = System.currentTimeMillis() - lStart;
		System.out.println("加密耗时:" + lUseTime + "毫秒");
		
		// 解密
		lStart = System.currentTimeMillis();
		String DeString = AESpkcs7paddingUtil.decrypt(enString,key);
		System.out.println("解密后的字串是:" + DeString);
		lUseTime = System.currentTimeMillis() - lStart;
		System.out.println("解密耗时:" + lUseTime + "毫秒");
	}
	
}

参考

Java 使用AES/CBC/PKCS7Padding 加解密字符串
npm
填充模式
对称加密的四种模式
demo