AES加密个人理解

这里实现的是AES加密算法的CBC模式的NoPadding加密

下图是官方文档中Cipher的provider。后面的padding为填充模式,即CBC为128位加密算法,加密内容的byte[]字节数组位数必须是16的倍数,否则会抛异常 Input length not multiple of 16 bytes

 

CBC加密提供了两种填充方式,NoPadding是默认不填充。因此不够16位的部分,下面用空格进行了填充凑位数。

另外CBC加密除了提供AES加密必须的密钥key以外,还要一个响亮iv,应该是增加加密复杂度的。

 以下源码是自己的CBC模式的实现,加密字段返回16进制字符串,解密时,同样通过AES/CBC/NoPadding方式,把16进制字符串转换为二进制byte[]字节数组后再解密,然后根据编码转为原字符串。

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Aes加密工具类--暂时只实现CBC NoPadding加密
 *
 * @author flysand
 **/
public class AesUtils {

    /**
     * 加密 加密方式AES/CBC/NoPadding 不足16位倍数,补空格
     *
     * @param sSrc           加密内容
     * @param encodingFormat 编码格式
     * @param sKey           密钥key
     * @param ivParameter    向量
     * @return
     * @throws Exception
     */
    public static String encrypt(String sSrc, String encodingFormat, String sKey, String ivParameter) throws Exception {
        byte[] sSrcArray = sSrc.getBytes(encodingFormat);
        int length = sSrcArray.length;
        byte[] lastArr;
        //不足16倍数位,补充空
        if (length % 16 != 0) {
            byte[] temp = new byte[16 - length % 16];
            //用空格补位
            byte[] fArr = " ".getBytes(encodingFormat);
            for (int i = 0; i < temp.length; i++) {
                temp[i] = fArr[0];
            }
            lastArr = new byte[length + temp.length];
            for (int i = 0; i < length; i++) {
                lastArr[i] = sSrcArray[i];
            }
            for (int i = 0; i < temp.length; i++) {
                lastArr[length + i] = temp[i];
            }
        } else {
            lastArr = sSrcArray;
        }
        //根据农银需求,采用AES/CBC/NoPadding加密方式
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        byte[] raw = sKey.getBytes(encodingFormat);
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(lastArr);
        //直接转为16进制传参
        return parseByte2HexStr(encrypted);
    }

    /**
     * 解密 根据加密方式AES/CBC/NoPadding解密
     *
     * @param sSrc           加密内容
     * @param encodingFormat 编码格式
     * @param sKey           密钥key
     * @param ivParameter    向量
     * @return
     * @throws Exception
     */
    public static String decrypt(String sSrc, String encodingFormat, String sKey, String ivParameter) throws Exception {
        try {
            byte[] raw = sKey.getBytes(encodingFormat);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes(encodingFormat));
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            //转为二进制字节数组
            byte[] encrypted = hex2byte(sSrc);
            byte[] original = cipher.doFinal(encrypted);
            String originalString = new String(original, encodingFormat);
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }


    /**
     * 将十六进制字符串转换成二进制字节数组
     *
     * @param strHex
     * @return
     */
    public static byte[] hex2byte(String strHex) {
        if (strHex == null) {
            return null;
        }
        int l = strHex.length();
        if (l % 2 == 1) {
            return null;
        }
        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; i++) {
            b[i] = (byte) Integer.parseInt(strHex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;

    }


    /**
     * 将二进制字节数组转换成16进制字符串
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }
}

 

posted @ 2017-12-05 09:17  飞沙流年  阅读(774)  评论(0编辑  收藏  举报