Aes加解密

加解密概念

加密

通过一系列计算将明文转换成一个密文。

加密和解密的对象通常是字节数组(有的语言动态数组类比切片

加密后的数据,可能有很多是不可读字符。通常会将其转换为可见的字符串。

  • 直接将字节数组转为16进制的字符串(一个字节8位,4位表示一个16进制数据,因此转换后的数据是转换前字节数组的2倍长度,之所以采用16进制是因为其看起来更加紧凑)
  • 将字节数组进行Base64编码

AES加密

算法相关常量在类 Cipher的注释中有说明。

AES是一种对称加密算法。具体加密方式是以16字节一块 进行分块加密。

如果明文 长度不是16的倍数,那么则需要进行填充,这就引申出了填充模式。
其密钥长度要求为 128 位(16字节)、192(24字节) 位和 256(32字节) 位,三种,越长越安全,速度越慢

填充模式

常用填充模式:PKCS#5、PKCS#7 。在Java中已经将其行为统一了。

在模式的定义上:

  • PKCS#5用于8字节块为单位的加密场景
  • PKCS#7用于非8字节块 为单位的加密场景,在现代应用中更通用
    但是它们的实现方式都是类似的,剩余的字节数组长度距离加密块差几个字节,就填充几个字节,而且每一位值也是这个长度

比如剩下5字节,在AES中,是以16字节为单位 ,差11个字节。那么就会在这5个字节后面加11个项,而且每一项的值都是11

加密模式

AES中现在用得最多的就是CBC 模式.

这种方式在加密一个块时,需要使用上一个块加密后的数据与当前明文块 进行异或运算。也就是说每一个块的加密都不一样。
这就有一个点,第一个加密块前面没有数据块,所以我们需要指定一个初始向量(有的也称之为偏移量)(其长度就是一个数据块的长度)

示例

  • 加密(如果使用的是CBC模式,则需要指定初始向量(说白了就是手动创建加密块,因此也是长度为16的字节数组),
  1. 生成iv(如果是CBC模式,则需要。长度与加密块一致(16字节))
java 复制代码
// 如果是CBC模式 首先生成iv向量(本质就是一个长度为16的字节数组,随便怎么构建)
// 可以自行创建16字节的数组,但推荐生成随机iv
// 自行构建
String ivStr = "1111111111111111"
byte[] iv = ivStr.getBytes(StandardCharsets.UTF_8);

// 生成随机iv
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[16];
secureRandom.nextBytes(iv);

IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
  1. 生成密钥
    AES密钥支持16字节、24字节、32字节(越长越安全,运算速度越慢)
    与iv类似,可以自定义密钥串,然后构建密钥对象,也可以直接生成指定长度的随机密钥
java 复制代码
// 指定密钥串,构建密钥对象
String key = "0111111111111111";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");

// 生成指定长度的密钥
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
  1. 创建加密器,在java中通过聚合名称指定多项配置(AES/CBC/PKCS7Padding )它制定了加密算法、加密模式、填充模式
java 复制代码
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
  1. 初始化加密器。指定加密还是解密,密钥,初始向量
java 复制代码
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
  1. 执行加解密。参数和返回都是字节数组
java 复制代码
byte[] resByte = cipher.doFinal(s.getBytes(StandardCharsets.UTF_8));
  1. 以上加密结果可能会有一些不可读的字符,因此为了方便查看,存储,传输等,我们常常将字节数组转为16进制字符串 或者Base64 进行存储,传输。
    不仅是加密结果。随的的生成iv字节数组,随机生成密钥字节数组 等包含不可读字符的字节数组都可以采用这种方式进行分发,存储
  • Base64编解码
java 复制代码
// 字节数组编码为Base64字符串
String encodedKey = Base64.getEncoder().encodeToString(encoded);

// Base64字符串解码为字节数组
byte[] keyBytes = Base64.getDecoder().decode(encodedKey);
  • 16进制编解码
java 复制代码
// 字节数组编码为16进制字符串
public String byte2Hex(byte[] bytes) {
    int len = bytes.length;
    StringBuilder builder = new StringBuilder();
    for (int i = 0, j = 0; i < len; i++) {
        builder.append(Integer.toHexString((0xF0 & bytes[i]) >>> 4));
        builder.append(Integer.toHexString(0x0F & bytes[i]));
    }
    return builder.toString();
}

// 16进制字符串转字节数组
public byte[] hexToBytes(String s) {
    byte[] bytes = new byte[(s.length() + 1) >> 1];
    for (int i = 0, j = 0; i < bytes.length; i++) {
        int left = Character.digit(s.charAt(j++), 16) << 4;
        left = left | Character.digit(s.charAt(j++), 16);
        bytes[i] = (byte) (left & 0xff);
    }
    return bytes;
}
相关推荐
羊锦磊1 小时前
[ Mybatis 多表关联查询 ] resultMap
java·开发语言·数据库·mysql·mybatis
ZeroToOneDev4 小时前
Java(泛型和JUnit)
java·开发语言·笔记
迪尔~5 小时前
Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片
java·pdf·excel
现在,此刻6 小时前
leetcode 11. 盛最多水的容器 -java
java·算法·leetcode
DKPT6 小时前
Java设计模式之开闭原则介绍与说明
java·设计模式·开闭原则
hyy27952276847 小时前
企业级WEB应用服务器TOMCAT
java·前端·tomcat
布朗克1687 小时前
Spring Boot项目通过Feign调用三方接口的详细教程
java·spring boot·feign
Arva .7 小时前
Spring基于XML的自动装配
xml·java·spring
帅得不敢出门9 小时前
Android Framework定制长按电源键关机的窗口
android·java·framework
fatfishccc9 小时前
循序渐进学 Spring (上):从 IoC/DI 核心原理到 XML 配置实战
xml·java·数据库·spring·intellij-idea·ioc·di