关于数据AES加密的使用
- 1 AES概述
- 2 AES加密方式
- 1 填充
- 2 模式
- 3 常用案列
因博主最近接触到敏感数据保护,选择使用AES进行加密,记录一下.
1 AES概述
1 引入概述
密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。
DES使用的是56位密钥,AES可以使用128、192、和256位密钥
2 加密类型
AES机密属于对称加密,即通过相应的密钥,可以解析出明文.
3 使用场景
AES现在广泛用于金融财务,敏感数据保护等领域。
2 AES加密方式
AES加密中, 密钥的长度有三种: 128 192 256 .
1 填充
明文不是128位(16字节)的则需要填充,在明文某个地方补充到16个字节整数倍的长度,加解密时需要采用同样的填充方式,否则无法解密.
NoPadding
不进行填充,但是这里要求明文必须要是16个字节的整数倍,需要用户自己实现.
PKCS5Padding(默认)
在明文的末尾进行填充,填充的数据是当前和16个字节相差的数量.
注:使用PKCS5Padding填充时,最后一个字节肯定为填充数据和16字节的差值,所以在解密后可以准确删除填充的数据.
2 模式
ECB模式(默认) 电码本模式
根据密钥的位数,将数据分成不同的块进行加密,加密完成后,再将加密后的数据拼接起来.
CBC模式 密码分组链接模式
ECB模式的密文块都是相同,这是一个缺点.CBC的模式引入了一个初始向量概念,该向量必须是一个与密钥长度相等的数据,在第一次加密前,会使用初始化向量与第一块数据做异或运算,生成的新数据再进行加密,加密第二块之前,会拿第一块的密文数据与第二块明文进行异或运算后再进行加密,以此类推,解密时也是在解密后,进行异或运算,生成最终的明文.
3 常用案列
AES加密常用模板
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* @Description
* @date 2021/8/21
*/
public class AESTest {
/**
* key 密钥 可以用26个字母和数字组成 使用AES-128-CBC加密模式,key需要为16位
*/
private static final String key="1234567812345678";
/**
* iv 偏移量,长度16
*/
private static final String iv ="1234567887654321";
/**
* @Description AES算法加密明文
* @param data 明文
* @return 密文
*/
public static String encryptAES(String data) throws Exception {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
byte[] dataBytes = data.getBytes();
int plaintextLength = dataBytes.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
// CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
byte[] encrypted = cipher.doFinal(plaintext);
// BASE64做转码
return AESTest.encode(encrypted).trim();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* @Description AES算法解密密文
* @param data 密文
* @return 明文
*/
public static String decryptAES(String data) throws Exception {
try
{
// 先用base64解密
byte[] encrypted1 = AESTest.decode(data);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original);
return originalString.trim();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 编码
* @param byteArray
* @return
*/
public static String encode(byte[] byteArray) {
return new String(new Base64().encode(byteArray));
}
/**
* 解码
* @param base64EncodedString
* @return
*/
public static byte[] decode(String base64EncodedString) {
return new Base64().decode(base64EncodedString);
}
public static void main(String[] args) throws Exception {
// 明文
String password = "777788889999";
// 加密
String encodePassword = AESTest.encryptAES(password);
System.out.println(encodePassword);
// 解密
String decodePassword = AESTest.decryptAES(encodePassword);
System.out.println(decodePassword);
}
}