什么是对称加密算法?
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。(简单理解加密解密使用的是同一把密钥)
填充概念
AES,DES 都是分组加密,对明文进行加密处理时并不是把整个明文直接一股脑加密得到密文,而是分为分为多少个字节为一组,对每一组明文进行单独加密,最后拼合加密结果
按块处理的数据, 数据长度不符合块处理需求时, 按照一定的方法填充满块长的规则,这里主要介绍以下两种:
NoPadding
- 不填充.
- 在DES加密算法下, 要求原文长度必须是8byte的整数倍
- 在AES加密算法下, 要求原文长度必须是16byte的整数倍
PKCS5Padding
数据块的大小为8位, 不够就补足
默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding
工作模式概念
常用工作模式有 ECB、CBC
ECB
CBC
工具类
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class ADESUtil {
private static final String AES_ALGORITHM = "AES";
private static final String DES_ALGORITHM = "DES";
//转换规则 默认情况下, 加密模式和填充模式为 : ECB/PKCS5Padding
private static final String AES_ECB_PADDING="AES/ECB/PKCS5Padding";
private static final String DES_ECB_PADDING="DES/ECB/PKCS5Padding";
private static final String AES_CBC_PADDING="AES/CBC/PKCS5Padding";
private static final String DES_CBC_PADDING="DES/CBC/PKCS5Padding";
public static SecretKey getSecretKey(String key,String algorithmType){
try {
//获取key的构造器
KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithmType);
//密钥加强
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
//构造器初始化 keysize 初始大小为128 一次加64
keyGenerator.init(256,secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("算法类型有误,获取密钥失败!");
}
}
/**
* AES加密/ECB工作模式
* @param key 密钥 初始长度为24 且必须为8的整数倍
* @param data 待加密数据
* @return
* @throws Exception
*/
public static String encryptAesByEcb(String key,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(AES_ECB_PADDING);
//初始化
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
//加密
byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(bytes);
}
/**
* AES加密/CBC工作模式
* @param key 密钥 初始长度为24 且必须为8的整数倍
* @param data 待加密数据
* @param keyIv 初始化向量,keyIv长度必须等于16
* @return
* @throws Exception
*/
public static String encryptAesByCbc(String key,String keyIv,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(AES_CBC_PADDING);
//创建向量参数对象
IvParameterSpec iv = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
//初始化
cipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);
//加密
byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(bytes);
}
/**
* AES解密/ECB工作模式
* @param key 密钥 初始长度为24 且必须为8的整数倍
* @param data 待解密数据
* @return
* @throws Exception
*/
public static String decryptAesByEcb(String key,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(AES_ECB_PADDING);
//初始化
cipher.init(Cipher.DECRYPT_MODE,secretKey);
//加密
byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(data));
return new String(bytes);
}
/**
* AES 解密/CBC工作模式
* @param key 密钥 初始长度为24 且必须为8的整数倍
* @param data 待加密数据
* @param keyIv 初始化向量,keyIv长度必须等于16
* @return
* @throws Exception
*/
public static String decryptAesByCbc(String key,String keyIv,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(AES_CBC_PADDING);
//创建向量参数对象
IvParameterSpec iv = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
//初始化
cipher.init(Cipher.DECRYPT_MODE,secretKey,iv);
//加密
byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(data));
return new String(bytes);
}
/**
* DES加密/ECB工作模式
* @param key 密钥 长度必须为 8 个字节
* @param data 待加密数据
* @return
* @throws Exception
*/
public static String encryptDesByEcb(String key,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(DES_ECB_PADDING);
//初始化
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
//加密
byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(bytes);
}
/**
* DES加密/CBC工作模式
* @param key 密钥 长度必须为 8 个字节
* @param data 待加密数据
* @param keyIv 初始化向量,keyIv长度必须等于8
* @return
* @throws Exception
*/
public static String encryptDesByCbc(String key,String keyIv,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(DES_CBC_PADDING);
//创建向量参数对象
IvParameterSpec iv = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
//初始化
cipher.init(Cipher.ENCRYPT_MODE,secretKey,iv);
//加密
byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(bytes);
}
/**
* DES解密/ECB工作模式
* @param key 密钥 长度必须为 8 个字节
* @param data 待解密数据
* @return
* @throws Exception
*/
public static String decryptDesByEcb(String key,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(DES_ECB_PADDING);
//初始化
cipher.init(Cipher.DECRYPT_MODE,secretKey);
//加密
byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(data));
return new String(bytes);
}
/**
* DES 解密/CBC工作模式
* @param key 密钥 长度必须为 8 个字节
* @param data 待加密数据
* @param keyIv 初始化向量,keyIv长度必须等于8
* @return
* @throws Exception
*/
public static String decryptDesByCbc(String key,String keyIv,String data) throws Exception{
//获取密钥
Key secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), DES_ALGORITHM);
//根据转化规则获取密码对象
Cipher cipher = Cipher.getInstance(DES_CBC_PADDING);
//创建向量参数对象
IvParameterSpec iv = new IvParameterSpec(keyIv.getBytes(StandardCharsets.UTF_8));
//初始化
cipher.init(Cipher.DECRYPT_MODE,secretKey,iv);
//加密
byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(data));
return new String(bytes);
}
}