目录

AES算法(九)Java 实战

目录

本篇将对之前所述的 AES 算法基于 Java 语言做实战讲解,由于 ECB 工作模式相对其他工作模式安全性低(不推荐使用),本文将不对其进行展示,如在工作中确实需要使用,请自行实现。

由于篇幅限制,所有的演示代码将只展示关键步骤,如果想要直接上手使用,请移步:https://github.com/aurthurxlc/java-utils

再多解释一下数据填充模式(M),并不是说只有 ECB、CBC 工作模式才可以用数据填充,其实所有的工作模式都可以进行数据填充再加密,只需要和解密方约定好就可以,但是 ECB、CBC 这两种工作模式却必须填充,否则是无法进行数据加密的。

加密的核心代码很简单,因为 Java 的 JDK 已经封装的很好了,直接调用即可。

/**
 * AES 加密解密主类
 */
public class AESCrypto {
    private final AESMode mode;
    private final SecretKey key;

    /**
     * 构造方法
     */
    public AESCrypto(AESMode mode, SecretKey key) {
        this.mode = mode;
        this.key = key;
    }

    /**
     * 加密
     */
    public byte[] encryptWithIV(byte[] plainText, IvParameterSpec iv)
            throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException {

        Cipher cipher = Cipher.getInstance(mode.getMode());
        cipher.init(Cipher.ENCRYPT_MODE, key, iv);
        return cipher.doFinal(plainText);
    }

    /**
     * 解密
     */
    public byte[] decryptWithIV(byte[] cipherText, IvParameterSpec iv)
            throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException {

        Cipher cipher = Cipher.getInstance(mode.getMode());
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(cipherText);
    }
}

需要注意的是,encryptWithIV 方法返回值是 Byte Array 形式的值,你可以根据需要转成 Hex 或者 Base64 形式进行存储,具体可以参考 ByteUtil 类。

AESMode 是我配置的一个常用的工作模式枚举类,具体可见 AESMode 类,可以根据需要自行扩充,标准 JDK 支持的模式请查看:https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#cipherTable

使用我们的加密解密代码示例:

public class AESCryptoTest {
    IvParameterSpec iv;
    SecretKey key;
    String pText;

    @Before
    public void init() throws NoSuchAlgorithmException {
        // 准备参数
        iv = AESTool.generateIV();
        key = AESTool.generateKey(128);
        pText = "AES 算法基于 Java 实战演示";

        System.out.println("key: " + BytesUtil.bytesToHex(key.getEncoded()));
        System.out.println("iv: " + BytesUtil.bytesToHex(iv.getIV()));
        System.out.println("pText: " + pText);
    }

    @Test
    public void test() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {

        // 加密
        AESCrypto aes = new AESCrypto(AESMode.CBC_PKCS5Padding, key);
        byte[] cBytes = aes.encryptWithIV(BytesUtil.stringToBytes(pText), iv);
        System.out.println("加密后 cText: " + BytesUtil.bytesToHex(cBytes));

        // 解密
        byte[] pBytes = aes.decryptWithIV(cBytes, iv);
        System.out.println("解密后 pText: " + BytesUtil.bytesToString(pBytes));

    }
}

输出结果如下:

key: e43ee68382dc550fbd1d329486febdd4
iv: ddffc44a93503156abb36e9bbca876f8
pText: AES 算法基于 Java 实战演示
加密后 cText: e8aa678c21aa028988cd74ee2835344519014a4e9365cb8dda7cf24bfe95dfdf0e047cf979587b02500ccad15415b1c3
解密后 pText: AES 算法基于 Java 实战演示