JAVA AES CBC 加密 解密

Posted runliuv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA AES CBC 加密 解密相关的知识,希望对你有一定的参考价值。

AES 256 , KEY 的长度为 32字节(32*8=256bit).

AES 128 , KEY 的长度为 16字节(16*8=128bit)

 

CBC 模式需要IV, IV的值是固定写死,还是当参数传入,自己看情况。IV的长度没研究,这里用的是16字符。

java PKCS5Padding 对应 C#.NET 的 PKCS7 。

明文,KEY和IV 三者 string 转 byte[] 时要统一编码,如UTF-8。

加密后 cipher.doFinal() 得到密文byte[] ,是直接转string,还是转为base64编码的string ,要统一。

 

AesCbc:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;


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 java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;


/**
 *
 * @author jk
 */
public class AesCbc {
    private static final String IV_STRING = "abcdefghABCDEFGH";

    private static final String charset = "UTF-8";
    
    
    // AES 266 = KEY 长度是32个字符 = (32*8=266)
    public static String encrypt(String content, String key) {
        try {
            byte[] contentBytes = content.getBytes(charset);
            byte[] keyBytes = key.getBytes(charset);
            byte[] encryptedBytes = aesEncryptBytes(contentBytes, keyBytes);
            return Base64Utils.encode(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    
    public static byte[] aesEncryptBytes(byte[] contentBytes, byte[] keyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return cipherOperation(contentBytes, keyBytes, Cipher.ENCRYPT_MODE);
    }
    
    private static byte[] cipherOperation(byte[] contentBytes, byte[] keyBytes, int mode) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        //cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(java.util.Base64.Decoder.decode(IV.
        SecretKeySpec keySpec=new SecretKeySpec(keyBytes,"AES");
        Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] initParam=IV_STRING.getBytes(charset);
        IvParameterSpec ivParameterSpec=new IvParameterSpec(initParam);
//        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
//        byte[] initParam = IV_STRING.getBytes(charset);
//        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
//        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, keySpec, ivParameterSpec);
        return cipher.doFinal(contentBytes);
    }
    
    public static String decrypt(String content, String key) {
        try {
            byte[] encryptedBytes = Base64Utils.decode(content);
            byte[] keyBytes = key.getBytes(charset);
            byte[] decryptedBytes = aesDecryptBytes(encryptedBytes, keyBytes);
            return new String(decryptedBytes, charset);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    
    public static byte[] aesDecryptBytes(byte[] contentBytes, byte[] keyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
        return cipherOperation(contentBytes, keyBytes, Cipher.DECRYPT_MODE);
    }
}

Base64Utils:

package javaapplication1;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.codec.binary.Base64;

/**
 *  */
/**
 * <p>
 * BASE64编码解码工具包
 * </p>
 * <p>
 * 依赖javabase64-1.3.1.jar
 * </p>
 *
 * @author IceWee
 * @date 2012-5-19
 * @version 1.0
 */
public class Base64Utils {

    /**
     *      */
    /**
     * 文件读取缓冲区大小
     */
    private static final int CACHE_SIZE = 1024;

    public static final String _charset = "UTF-8";

    /**
     *      */
    /**
     * <p>
     * BASE64字符串解码为二进制数据
     * </p>
     *
     * @param base64
     * @return
     * @throws Exception
     */
    public static byte[] decode(String str) throws Exception {
        Base64 _base64 = new Base64();
        return _base64.decodeBase64(str.getBytes(_charset));
    }

    /**
     *      */
    /**
     * <p>
     * 二进制数据编码为BASE64字符串
     * </p>
     *
     * @param bytes
     * @return
     * @throws Exception
     */
    public static String encode(byte[] bytes) throws Exception {
        Base64 _base64 = new Base64();
        return new String(_base64.encodeBase64Chunked(bytes));
    }

    /**
     *      */
    /**
     * <p>
     * 将文件编码为BASE64字符串
     * </p>
     * <p>
     * 大文件慎用,可能会导致内存溢出
     * </p>
     *
     * @param filePath 文件绝对路径
     * @return
     * @throws Exception
     */
    public static String encodeFile(String filePath) throws Exception {
        byte[] bytes = fileToByte(filePath);
        return encode(bytes);
    }

    /**
     *      */
    /**
     * <p>
     * BASE64字符串转回文件
     * </p>
     *
     * @param filePath 文件绝对路径
     * @param base64 编码字符串
     * @throws Exception
     */
    public static void decodeToFile(String filePath, String base64) throws Exception {
        byte[] bytes = decode(base64);
        byteArrayToFile(bytes, filePath);
    }

    /**
     *      */
    /**
     * <p>
     * 文件转换为二进制数组
     * </p>
     *
     * @param filePath 文件路径
     * @return
     * @throws Exception
     */
    public static byte[] fileToByte(String filePath) throws Exception {
        byte[] data = new byte[0];
        File file = new File(filePath);
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
            data = out.toByteArray();
        }
        return data;
    }

    /**
     *      */
    /**
     * <p>
     * 二进制数据写文件
     * </p>
     *
     * @param bytes 二进制数据
     * @param filePath 文件生成目录
     */
    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
        InputStream in = new ByteArrayInputStream(bytes);
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        destFile.createNewFile();
        OutputStream out = new FileOutputStream(destFile);
        byte[] cache = new byte[CACHE_SIZE];
        int nRead = 0;
        while ((nRead = in.read(cache)) != -1) {
            out.write(cache, 0, nRead);
            out.flush();
        }
        out.close();
        in.close();
    }

}

base 64 编码引用了 org.apache.commons.codec.binary.Base64,可以从网上下载。

 

测试代码 main:

static void TestAesCbc() {
        String cc = "中华人民共和国~!@#¥%……&*()——+12345678ABC中华人民共和国~!@#¥%……&*()——+12345678ABC中华人民共和国~!@#¥%……&*()——+12345678ABC中华人民共和国~!@#¥%……&*()——+12345678ABC";
        System.out.println("明文:\r\n" + cc);

        System.out.println("AES 256 -------:\r\n");
        String aesKey = "12345678901234567890123456789012";
        String aa = AesCbc.encrypt(cc, aesKey);
        System.out.println("密文:\r\n" + aa);
        String dd = AesCbc.decrypt(aa, aesKey);
        System.out.println("解密后明文:\r\n" + dd);

        System.out.println("AES 128 -------:\r\n");
        String aesKey2 = "1234567890123456";
        aa = AesCbc.encrypt(cc, aesKey2);
        System.out.println("密文:\r\n" + aa);
        dd = AesCbc.decrypt(aa, aesKey2);
        System.out.println("解密后明文:\r\n" + dd);
    }

end

 

以上是关于JAVA AES CBC 加密 解密的主要内容,如果未能解决你的问题,请参考以下文章

nodejs和java交互 AES-128-CBC加密解密

AES-256-CBC用PHP加密并用Java解密

QT:AES-256-CBC 根据 PHP 代码在 C++ 中加密/解密

如何使用Javascript中的AES CBC零填充进行加密并使用Java进行解密

小程序:JS AES加密解密(ECB/CBC)

Java里的AES/CBC/PKCS7Padding加密解密