Skip to content

Java加解密示例代码

java
package cn.hamm.airpower.crypto;

import cn.hamm.airpower.exception.ServiceException;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;

/**
 * <h1>AES 工具类</h1>
 *
 * @author Hamm.cn
 */
public class AesUtil {
    /**
     * 密钥长度
     */
    private static final int KEY_SIZE = 256;

    /**
     * AES
     */
    private static final String AES = "AES";

    /**
     * {@code AES/CBC/PKCS5Padding}
     */
    private static final String AES_CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";

    /**
     * 密钥
     */
    private byte[] key;

    /**
     * 偏移向量
     */
    private byte[] iv = "0000000000000000".getBytes(UTF_8);

    /**
     * 算法
     */
    private String algorithm = AES_CBC_PKCS5_PADDING;

    /**
     * 禁止外部实例化
     */
    private AesUtil() {

    }

    /**
     * 创建实例
     *
     * @return 新实例
     */
    @Contract(" -> new")
    public static @NotNull AesUtil create() {
        return new AesUtil();
    }

    /**
     * 获取随机密钥
     *
     * @return 随机密钥
     */
    @Contract(" -> new")
    public static @NotNull String getRandomKey() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(AES);
            keyGen.init(KEY_SIZE, new SecureRandom());
            SecretKey aesKey = keyGen.generateKey();
            byte[] keyBytes = aesKey.getEncoded();
            return Base64.getEncoder().encodeToString(keyBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 获取随机向量
     *
     * @return 随机向量
     */
    @Contract(" -> new")
    public static @NotNull String getRandomIv() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(AES);
            keyGen.init(KEY_SIZE / 2, new SecureRandom());
            SecretKey aesKey = keyGen.generateKey();
            byte[] keyBytes = aesKey.getEncoded();
            return Base64.getEncoder().encodeToString(keyBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new ServiceException(e);
        }
    }

    /**
     * 设置偏移向量
     *
     * @param iv 偏移向量
     * @return <b>AesUtil</b> 实例
     */
    @Contract("_ -> this")
    public final AesUtil setIv(String iv) {
        this.iv = Base64.getDecoder().decode(iv);
        return this;
    }

    /**
     * 设置算法
     *
     * @param algorithm 算法
     * @return <b>AesUtil</b> 实例
     */
    @Contract(value = "_ -> this", mutates = "this")
    public final AesUtil setAlgorithm(String algorithm) {
        this.algorithm = algorithm;
        return this;
    }

    /**
     * 设置密钥
     *
     * @param key 密钥
     * @return <b>AesUtil</b> 实例
     */
    @Contract("_ -> this")
    public final AesUtil setKey(String key) {
        this.key = Base64.getDecoder().decode(key);
        return this;
    }

    /**
     * 加密
     *
     * @param source 待加密的内容
     * @return 加密后的内容
     */
    public final String encrypt(String source) {
        try {
            return Base64.getEncoder().encodeToString(getCipher(ENCRYPT_MODE)
                    .doFinal(source.getBytes(UTF_8)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解密
     *
     * @param content 加密后的内容
     * @return 解密后的内容
     */
    @Contract("_ -> new")
    public final @NotNull String decrypt(String content) {
        try {
            return new String(getCipher(DECRYPT_MODE)
                    .doFinal(Base64.getDecoder().decode(content)), UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取 {@code Cipher}
     *
     * @param mode 模式
     * @return {@code Cipher}
     */
    private @NotNull Cipher getCipher(int mode) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(mode, secretKeySpec, ivParameterSpec);
            return cipher;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}