AES加解密
密钥是AES
算法实现加密和解密的根本。对称加密算法之所以对称,是因为这类算法对明文的加密和解密需要使用同一个密钥。
AES
支持三种长度的密钥: 128位,192位,256位
平时大家所说的AES128
,AES192
,AES256
,实际上就是指AES
算法对不同长度密钥的使用。
三种密钥的区别:
从安全性来看,AES256
安全性最高。从性能看,AES128
性能最高。本质原因是它们的加密处理轮数不同。
AES原理:AES是对数据按128位,也就是16个字节进行分组进行加密的,每次对一组数据加密需要运行多轮,而输入密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节,如果用户输入的密钥长度不是这几种长度,也会补成这几种长度。
无论输入密钥是多少字节,加密还是以16字节的数据一组来进行的,密钥长度的不同仅仅影响加密运行的轮数。
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;
public class TestController {
public static void main(String[] args) {
try {
//根据指定字符串生成秘钥
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128,new SecureRandom("ceshi".getBytes()));
SecretKey sk = kg.generateKey();
String keyStr = Base64.getEncoder().encodeToString(sk.getEncoded());
byte[] iv = Base64.getDecoder().decode(keyStr);
byte[] key = Base64.getDecoder().decode(keyStr);
String content = "测试";
String encrypted = Base64.getEncoder().encodeToString(encrypt(iv, key, content.getBytes()));
System.out.println("加密后: " + encrypted);
String raw = new String(decrypt(iv, key, Base64.getDecoder().decode(encrypted)));
System.out.println("解密后: " + raw);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static byte[] encrypt(byte[] iv, byte[] key, byte[] raw) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"
IvParameterSpec ips = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ips);
return cipher.doFinal(raw);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] decrypt(byte[] iv, byte[] key, byte[] encryptContent) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ips);
return cipher.doFinal(encryptContent);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
填充模式:
PKCS1Padding:PKCS#1(v1.5)中规定当RSA的密钥长度是1024b,如果使用PKCS1Padding填充,则原文数据最多117B。如果原文不满足长度要求,则在加密前需要进行填充。
PKCS5Padding:PKCS#5填充是将数据填充到8的倍数,填充后数据长度的计算公式是 定于元数据长度为x, 填充后的长度是 x + (8 - (x % 8)), 填充的数据是 8 - (x % 8),块大小固定为8字节
PKCS7Padding:假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小;PKCS5只填充到8字节,而PKCS7可以在1-255之间任意填充。
ZeroPadding:数据长度不对齐时使用0填充,否则不填充。
NoPadding:待补充