目录
一、AES算法描述:
二、不同工作模式的算法实现
ECB模式
2.1、加密 encrypt(key,input) 传入明文
2.2、解密decrypt(key,input) 传入密文
2.3、main主函数调用
结果展示
CBC模式
3.1、加密 encrypt(key,input) 传入明文
3.2、合并数组: join(byte1,byte2)
3.3、解密decrypt(key,input) 传入密文
3.4、main主函数调用
结果展示
一、AES算法描述:
它是对称加密算法的一种:通过调用两种算法方法
encrypt(key,messsage)------进行加密
decrypt(key,message) ------进行解密
AES的明文分组长度为128位(16字节),
密钥:长度可以为128位(16字节)、192位(24字节)、256位(32字节)
注意点:密钥必须是相应的字节数【多了少了都会报错】
根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种。
工作模式:ECB/CBC
填充模式:NOPadding/PKCS5Padding
二、不同工作模式的算法实现
ECB模式
简述:是最简单的AES加密模式,它需要一个固定长度的密钥
特点:固定的明文会生成固定的密文
代码:完成加密和解密操作
加密和解密操作类似,
2.1、加密 encrypt(key,input) 传入明文
第一步:创建Cipher对象,需要传入参数,格式为:【算法名/工作模式/填充模式】
第二步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】
第三步:初始化秘钥 init()方法 设置秘钥模式为:【ENCRYPT_MODE】
第四步:根据原始字节内容(字节),进行加密:执行doFinal()方法
第五步:返回结果【得到密文】
public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKey keyspec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keyspec);
return cipher.doFinal(input);
}
2.2、解密decrypt(key,input) 传入密文
第一步:创建Cipher对象,需要传入参数,格式为:【算法名/工作模式/填充模式】
第二步:根据key的字节内容,“恢复”秘钥对象 即:SecreKey实例
第三步:初始化秘钥 init()方法 设置秘钥模式为:【DECRYPT_MODE】
第四步:根据原始字节内容(字节),进行解密 :执行doFinal()方法
第五步:返回结果【得到明文】
public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKey keySpec = new SecretKeySpec(key,"AES");
cipher.init(Cipher.DECRYPT_MODE,keySpec);
return cipher.doFinal(input);
}
2.3、main主函数调用
注意:密钥是16个字符,32个字节,多了少了都会报错
public static void main(String[] args) throws GeneralSecurityException {
// 原文:
String message = "天生我材必有用飞流直下三千尺";
System.out.println("Message(原始信息): " + message);
// 128位密钥 = 16 bytes Key:
byte[] key = "1234567890abcdef".getBytes();
// 加密:
byte[] data = message.getBytes();
byte[] encrypted = encrypt(key, data);
System.out.println("Encrypted(加密内容): " +
Base64.getEncoder().encodeToString(encrypted));
// 解密:
byte[] decrypted = decrypt(key, encrypted);
System.out.println("Decrypted(解密内容): " + new String(decrypted));
}
结果展示
CBC模式
相比较ECB模式的一对一进行加密,CBC模式传入了一个随机数作为IV参数,使得同一份明文,产生不同的明文,安全性提高。
3.1、加密 encrypt(key,input) 传入明文
第一步:创建Cipher对象,需要传入参数,格式为:【AES/CBC/填充模式】
第二步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】
第三步:生成一个16 字节的随机数
1.使用SecureRandom的getInstanceStrong()方法产生随机数sr
2.将1产生的sr调用generateSeed(16)生成16个字节的随机数
3.将随机数封装成IvParameterSpec对象Iv
第四步:初始化秘钥 init(操作模式、秘钥、IV参数)方法
设置秘钥模式为:【ENCRYPT_MODE】
第五步:根据原始字节内容(字节),进行加密:执行doFinal()方法
第六步:返回结果【得到密文】其中IV不要要保密,一起返回
调用join(iv,data)方法
代码:
public static byte[] encrypt(byte[] key, byte[] input) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKey keySpet = new SecretKeySpec(key, "AES");
SecureRandom sr = SecureRandom.getInstanceStrong();
byte[] iv = sr.generateSeed(16);
System.out.println(Arrays.toString(iv));
System.out.println(iv.length);
IvParameterSpec ivps = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpet,ivps);
byte[] data = cipher.doFinal(input);
return join(iv,data);
}
3.2、合并数组: join(byte1,byte2)
由于秘钥是固定长度的,而密文是不定长的。
所以先存储秘钥,解密时,只需要从数组的第16个位置截取即可获取密文
public static byte[] join(byte[] bs1, byte[] bs2) {
byte[] r = new byte[bs1.length+bs2.length];
System.arraycopy(bs1, 0, r, 0, bs1.length);
System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
return r;
}
3.3、解密decrypt(key,input) 传入密文
第一步:把input分割成IV和密文
从第16位开始截取
第二步:创建Cipher对象,需要传入参数,格式为:【AES/CBC/填充模式】
第三步:根据key的字节内容,“恢复”秘钥对象即:SecreKey实例 【第二个参数:传入算法名称 】
第四步:将传入的key封装成IvParameterSpec对象Iv
第四步:初始化秘钥 init(操作模式、秘钥、IV参数)方法
设置秘钥模为:【DECRYPT_MODE】
第五步:根据原始字节内容(字节),进行加密:执行doFinal()方法
第六步:返回结果【得到明文】
代码:
public static byte[] decrypt(byte[] key, byte[] input) throws GeneralSecurityException {
// 把input分割成IV和密文:
byte[] iv = new byte[16];
byte[] data = new byte[input.length-16];
System.arraycopy(input, 0, iv, 0, 16);
System.arraycopy(input, 16, data, 0, data.length);
System.out.println(Arrays.toString(iv));
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivps = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec,ivps);
return cipher.doFinal(data);
}
3.4、main主函数调用
注意:秘钥的位数是32个字节【256位】
public static void main(String[] args) throws Exception {
// 原文:
String message = "止于智者";
System.out.println("Message(原始信息): " + message);
// 256位密钥 = 32 bytes Key:
byte[] key = "1234567890qwertyuiopasdfgasdfghj".getBytes();
// 加密:
byte[] data = message.getBytes();
byte[] encrypted = encrypt(key, data);
System.out.println("Encrypted(加密内容): " +
Base64.getEncoder().encodeToString(encrypted));
// 解密:
byte[] decrypted = decrypt(key, encrypted);
System.out.println("Decrypted(解密内容): " + new String(decrypted));
}