Java实现AES加密解密

AES加密属于对称加密算法,可以使用相同的密码反向解密出来。另外,AES加密属于典型的块加密算法,其中常用的块加密的工作模式包含:

  • ECB模式:又称电码本(ECB,Electronic Codebook Book)模式。这是最简单的块密码加密模式,加密前根据加密块大小(如AES为128位)分成若干块,之后将每块使用相同的密钥单独加密,解密同理。
  • CBC模式:又称密码分组链接(CBC,Cipher-block chaining)模式。在这种加密模式中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量IV。

使用Java实现的完整示例代码如下:

package cn.zifangsky.utils;
 
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.MessageFormat;
 
/**
 * AES加解密
 *
 * @author zifangsky
 * @date 2018/8/14
 * @since 1.0.0
 */
public class AesUtils {
    /**
     * AES加解密
     */
    private static final String ALGORITHM = "AES";
    /**
     * 默认的初始化向量值
     */
    private static final String IV_DEFAULT = "g8v20drvOmIx2PuR";
    /**
     * 默认加密的KEY
     */
    private static final String KEY_DEFAULT = "8G5M4Ff9hel8fUA9";
    /**
     * 工作模式:CBC
     */
    private static final String TRANSFORM_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
 
    /**
     * 工作模式:ECB
     */
    private static final String TRANSFORM_ECB_PKCS5 = "AES/ECB/PKCS5Padding";
 
    /**
     * 基于CBC工作模式的AES加密
     * @author zifangsky
     * @date 2018/8/14 11:42
     * @since 1.0.0
     * @param value 待加密字符串
     * @param key 秘钥,如果不填则使用默认值
     * @param iv 初始化向量值,如果不填则使用默认值
     * @return java.lang.String
     */
    public static String encryptCbcMode(final String value, String key, String iv){
        if(StringUtils.isNoneBlank(value)){
            //如果key或iv为空,则使用默认值
            if(key == null || key.length() != 16){
                key = KEY_DEFAULT;
            }
            if(iv == null || iv.length() != 16){
                iv = IV_DEFAULT;
            }
 
            //密码
//            final SecretKeySpec keySpec = new SecretKeySpec(getUTF8Bytes(key),"AES");
            final SecretKeySpec keySpec = getSecretKey(key);
 
            //初始化向量器
            final IvParameterSpec ivParameterSpec = new IvParameterSpec(getUTF8Bytes(iv));
 
            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_CBC_PKCS5);
 
                //加密模式
                encipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
                //使用AES加密
                byte[] encrypted = encipher.doFinal(getUTF8Bytes(value));
                //然后转成BASE64返回
                return Base64.encodeBase64String(encrypted);
            } catch (Exception e) {
                System.out.println(MessageFormat.format("基于CBC工作模式的AES加密失败,VALUE:{0},KEY:{1}",value,key));
                e.printStackTrace();
            }
        }
 
        return null;
    }
 
    /**
     * 基于CBC工作模式的AES解密
     * @author zifangsky
     * @date 2018/8/14 11:42
     * @since 1.0.0
     * @param encryptedStr AES加密之后的字符串
     * @param key 秘钥,如果不填则使用默认值
     * @param iv 初始化向量值,如果不填则使用默认值
     * @return java.lang.String
     */
    public static String decryptCbcMode(final String encryptedStr, String key, String iv){
        if(StringUtils.isNoneBlank(encryptedStr)){
            //如果key或iv为空,则使用默认值
            if(key == null || key.length() != 16){
                key = KEY_DEFAULT;
            }
            if(iv == null || iv.length() != 16){
                iv = IV_DEFAULT;
            }
 
            //密码
//            final SecretKeySpec keySpec = new SecretKeySpec(getUTF8Bytes(key),"AES");
            final SecretKeySpec keySpec = getSecretKey(key);
//            初始化向量器
            final IvParameterSpec ivParameterSpec = new IvParameterSpec(getUTF8Bytes(iv));
 
            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_CBC_PKCS5);
 
                //加密模式
                encipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
                //先用BASE64解密
                byte[] encryptedBytes = Base64.decodeBase64(encryptedStr);
                //然后再AES解密
                byte[] originalBytes = encipher.doFinal(encryptedBytes);
                //返回字符串
                return new String(originalBytes);
            } catch (Exception e) {
                System.out.println(MessageFormat.format("基于CBC工作模式的AES解密失败,encryptedStr:{0},KEY:{1}",encryptedStr,key));
                e.printStackTrace();
            }
        }
 
        return null;
    }
 
 
    /**
     * 基于ECB工作模式的AES加密
     * @author zifangsky
     * @date 2018/8/14 11:42
     * @since 1.0.0
     * @param value 待加密字符串
     * @param key 秘钥,如果不填则使用默认值
     * @return java.lang.String
     */
    public static String encryptEcbMode(final String value, String key){
        if(StringUtils.isNoneBlank(value)){
            //如果key为空,则使用默认值
            if(key == null || key.length() != 16){
                key = KEY_DEFAULT;
            }
 
            //密码
            final SecretKeySpec keySpec = getSecretKey(key);
 
            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_ECB_PKCS5);
 
                //加密模式
                encipher.init(Cipher.ENCRYPT_MODE, keySpec);
                //使用AES加密
                byte[] encrypted = encipher.doFinal(getUTF8Bytes(value));
                //然后转成BASE64返回
                return Base64.encodeBase64String(encrypted);
            } catch (Exception e) {
                System.out.println(MessageFormat.format("基于ECB工作模式的AES加密失败,VALUE:{0},KEY:{1}",value,key));
                e.printStackTrace();
            }
        }
 
        return null;
    }
 
    /**
     * 基于ECB工作模式的AES解密
     * @author zifangsky
     * @date 2018/8/14 11:42
     * @since 1.0.0
     * @param encryptedStr AES加密之后的字符串
     * @param key 秘钥,如果不填则使用默认值
     * @return java.lang.String
     */
    public static String decryptEcbMode(final String encryptedStr, String key){
        if(StringUtils.isNoneBlank(encryptedStr)){
            //如果key为空,则使用默认值
            if(key == null || key.length() != 16){
                key = KEY_DEFAULT;
            }
 
            //密码
            final SecretKeySpec keySpec = getSecretKey(key);
 
            try {
                Cipher encipher = Cipher.getInstance(TRANSFORM_ECB_PKCS5);
 
                //加密模式
                encipher.init(Cipher.DECRYPT_MODE, keySpec);
                //先用BASE64解密
                byte[] encryptedBytes = Base64.decodeBase64(encryptedStr);
                //然后再AES解密
                byte[] originalBytes = encipher.doFinal(encryptedBytes);
                //返回字符串
                return new String(originalBytes);
            } catch (Exception e) {
                System.out.println(MessageFormat.format("基于ECB工作模式的AES解密失败,encryptedStr:{0},KEY:{1}",encryptedStr,key));
                e.printStackTrace();
            }
        }
 
        return null;
    }
 
    /**
     * 将字符串转化为UTF8格式的byte数组
     *
     * @param input the input string
     * @return UTF8 bytes
     */
    private static byte[] getUTF8Bytes(String input) {
        return input.getBytes(StandardCharsets.UTF_8);
    }
 
    /**
     * 生成加密秘钥
     * @param KEY 明文秘钥
     * @return SecretKeySpec
     */
    private static SecretKeySpec getSecretKey(final String KEY) {
        //生成指定算法密钥
        KeyGenerator generator = null;
 
        try {
            generator = KeyGenerator.getInstance(ALGORITHM);
 
            //指定AES密钥长度(128、192、256)
            generator.init(256, new SecureRandom(getUTF8Bytes(KEY)));
 
            //生成一个密钥
            SecretKey secretKey = generator.generateKey();
            //转换为AES专用密钥
            return new SecretKeySpec(secretKey.getEncoded(), ALGORITHM);
        } catch (NoSuchAlgorithmException ex) {
            System.out.println(MessageFormat.format("生成加密秘钥失败,KEY:{0}",KEY));
            ex.printStackTrace();
        }
 
        return null;
    }
 
    public static void main(String[] args) {
        String encryptedStr = AesUtils.encryptCbcMode("hello world!", "4Ct7TyXZa19rgQKK", null);
        System.out.println(encryptedStr);
 
        String originalStr = AesUtils.decryptCbcMode(encryptedStr, "4Ct7TyXZa19rgQKK", null);
        System.out.println(originalStr);
 
        String encryptedStr2 = AesUtils.encryptEcbMode("{\"username\":\"Tom\",\"password\":\"123456\",\"mobile\":\"12306\",\"email\":\"admin@zifangsky.cn\"}", "4Ct7TyXZa19rgQKK");
        String originalStr2 = AesUtils.decryptEcbMode(encryptedStr2, "4Ct7TyXZa19rgQKK");
        System.out.println(originalStr2);
 
    }
 
}

示例输出如下:

MIxF9AlTl21FkwnASvYowg==
hello world!
{"username":"Tom","password":"123456","mobile":"12306","email":"admin@zifangsky.cn"}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值