AES加密工具的实现及其基础原理

先贴代码:重要的参数都有注释,自己摸索的,有不对的地方大家指正

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 *
 * @ClassName:  DESUtil
 * @Description: 加解密工具类
 * @author: panpan
 * @date:   2019年1月29日 下午5:01:48
 *
 */
public class AESUtil {

    private static final String CHARSET_NAME = "UTF-8";

    public static String encode(String plainText, String key, String vi) {
        try {
            // 根据字符串key生成 Cipher 初始化使用的 secretKey
            SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES");
            // 获取Cipher实例,指定加密方法、加密模式、补位模式
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            // 加密器初始化,参数分别是: 加密器编码模式(加密或解密)、秘钥、加密向量
            cipher.init(Cipher.ENCRYPT_MODE, secretKey,
                    new IvParameterSpec(vi.getBytes()));
            // cipher 可以 add 但是最终需要使用 doFinal结束,返回byte[],这里通过base64编码成字符串
            return java.util.Base64.getEncoder().encodeToString(cipher.doFinal(plainText.getBytes(CHARSET_NAME)));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String decode(String encryptText, String key, String vi) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(CHARSET_NAME),"AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey,
                    new IvParameterSpec(vi.getBytes()));
            return new String(cipher.doFinal(java.util.Base64.getDecoder().decode(encryptText)), CHARSET_NAME);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String vi = "f4CAHEW85Daszbwi"; // 16字节加密向量
        String message = "Uibn1aICzX";  // 任意大小需要加密的文字
        String key = "JvOybH9j7Qs0wSxi"; // 128bit、16字节秘钥
        String encryptedCode = encode(message,key,vi);
        System.out.println(encryptedCode);
        String decryptedCode = decode(encryptedCode,key,vi);
        System.out.println(decryptedCode);
    }
}

  接着放参考资料:

  首先第一位的是 JAVA API:

http://www.matools.com/api/java8

   需要注意的是,获取Cipher实例时,可以选择很多加密模式,这是写这个工具类的核心。

   1、加密方法有: AES、DES、DESede、RSA

   2、加密模式有: CBC、ECB,这两种是JDK中提供的实例有的,如果你需要写其他的加密模式,如:CFB、OFB

   可以参考这篇文章的原理:

   https://blog.csdn.net/sunqiujing/article/details/75065218

   当然,想要demo的话,这里有一个CFB的例子:

    https://download.csdn.net/download/langeldep/9749421

   3、最后一个参数: Padding or not: 是否补位,这个初次接触加密的童鞋可能有点懵,说实话今早我刚刚看到这个的时候也有点懵逼,后来参考了   https://blog.csdn.net/sunqiujing/article/details/75065218 这篇文章讲述的原理,有点明白了,其实AES、DES在加密时,是以 8 bit 作为一个单元的,如果不满 8 bit,如果你选择了 PKCS5Padding,则会给你补位,CFB中那位老哥写的demo,使用的是 NoPadding,但是自己在代码了撸了补位的操作,具体为什么他不使用工具里自带的补位,没有细细研究。

   4、还有一点,括号中的数字,说的是你的 加密key需要的位数,也是 AES加密快的大小

                     

                                                                              引用一个图

 比如我使用 AES/CBC/PKCS5Padding,官方文档中说要 128 bit,即 key需要 128/8 = 16 字符的字符串,

 如果你的位数不满 16 位,就会报以下错误:

 java.lang.RuntimeException: java.security.InvalidKeyException: Invalid AES key length: 17 bytes

 

接下来的一个核心,是Cipher加密器的初始化:

cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(vi.getBytes()));

1、加密器模式: ENCRYPT_MODE是加密  DECRYPT_MODE是解密

2、 secretKey 是秘钥,当然你不能直接把直接放字符串秘钥,得使用JAVA提供的秘钥生成器,并制定加密方式,因为不同加密方式,使用的key构成是不一样的,并且秘钥的大小也不同,重点需要特别注意。

3、 加密向量,注意 上面代码里采用的 AES/CBC/PKCS5Padding 需要 16字节128bit的加密向量,否则则会报错:

java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long

       加密向量干啥用的嘞? 大家可以回想一下大学学得 线性代数,加密的每个明文模块、秘钥模块、密文模块其实都是一个矩阵,这里的加密向量其实和线代里的向量应该是一致的。

                                               再借用一张图

    大概原理差不多是:  明文矩阵 X 秘钥矩阵 X 基础向量 = 明文矩阵    

    这篇文章写得很详细,大家可以看一下

    https://blog.csdn.net/wufaliang003/article/details/79619027

 

    嗯嗯,总算对对称加密的几种方法有了个大概了解,做一篇文章,mark一下,也是分享经验,有不对的地方大家评论

       

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值