文章目录
- 前言
- 1、 核心原理
- 2、 特点
- 3、 常见的加密算法
- 4、 加密模式
- 5、 填充模式
- 6、DES加密实现
- 7、AES加密实现
前言
对称加密,加密和解密用的同一个秘钥,也叫单密钥加密。
1、 核心原理
流加密和块加密
- 流加密(序列密码):是对信息中的每一个元素(一个字母或者一个比特)作为基础的处理单元进行加密。
例如:1234678 先加密1再加密2再见3,以此类推。 - 块加密(分组密码):是先对信息进行分块,在对每一块分别加密。
例如:1234678 先分块 分为 1234 和 5678 再先加密1234 再加密5678。
2、 特点
- 加密速度快,可加密大文件。
- 密文可逆,一旦秘钥文件泄露,就会导致数据暴露。
- 加密后编码表找不到对应字符出现乱码。
- 一般结合Base64使用。
3、 常见的加密算法
DES加解密,key必须8个字节
AES加解密,key必须16个字节
4、 加密模式
加密模式:ECB、CBC
- ECB Electronic code book 电子密码本,需要加密的消息按照块密码的大小被分为数个块,并对每个块进行独立加密。
优点:可以并行处理数据
缺点:同样的原文生成同样的密文,不能很好的保护数据,
同时加密,原文是一样的,加密出来的密文也是一样的。 - CBC Cipher-block chaining 密码块连接,每个明文块先和前一个密文块进行异或后,在进行加密。这样每个密文块都依赖了他前面的所有明文块。
优点:同样的原文生成不一样的密文
缺点:串行处理数据,加密慢
CBC模式需要指定iv变量
5、 填充模式
当需要按照块处理的数据,数据长度不符合处理需求时,按照一定的方法填充满块长的规则
NoPadding和PKCS5Padding
- NoPadding
1、不填充
2、在DES加密算法下,要求原文长度必须是8Byte的整数倍。
3、在AES加密算法下,要求原文长度必须是16Byte的整数倍. - PKCS5Padding
数据块的大小为8位不够就补充,先分块,最后一个可能够8位,也不够8位,不够时就补全。
6、DES加密实现
package com.lh.basecryptology.desaes;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class DesDemo {
public static void main(String[] args) throws Exception {
// 原文
String text = "十里洋场,遍地黄金";
// 密钥 如果用Des加密密钥必须8位
String key = "12345678";
// 算法
// DES 默认是 DES/ECB/PKCS5Padding
String transformation = "DES";
// DES/ECB/PKCS5Padding URi9FEpJ67KLV+LYiQjmRZ+dulH/ltTO5ejvMir6dwo=
// String transformation = "DES/ECB/PKCS5Padding";
System.out.println("==========" + transformation);
// 加密类型 ECB/PKCS5Padding
String algorithm = "DES";
String encrypt = encryptECB(text, key, transformation, algorithm);
System.out.println("密文ECB:" + encrypt);
String decrypt = decryptECB(encrypt, key, transformation, algorithm);
System.out.println("原文ECB:" + decrypt);
// 加密类型 ECB/PKCS5Padding
transformation = "DES/ECB/NoPadding";
System.out.println("==========" + transformation);
String encryptNoPadding = encryptNoPadding(text, key, transformation, algorithm);
System.out.println("密文ECBNoPadding:" + encryptNoPadding);
String decryptNoPadding = decryptECB(encrypt, key, transformation, algorithm);
System.out.println("原文ECBNoPadding:" + decryptNoPadding);
// 加密模式为CBC时需要指定iv向量
transformation = "DES/CBC/PKCS5Padding";
System.out.println("==========" + transformation);
String encryptCBC = encryptCBC(text, key, "DES/CBC/PKCS5Padding", algorithm);
System.out.println("密文CBC:" + encryptCBC);
String decryptCBC = decryptCBC(encryptCBC, key, "DES/CBC/PKCS5Padding", algorithm);
System.out.println("原文CBC:" + decryptCBC);
}
/**
* 使用DES加密
*
* @param text 原文
* @param key 密钥
* @param transformation 加密算法
* @param algorithm 加密类型
* @throws Exception
*/
private static String encryptECB(String text, String key, String transformation, String algorithm) throws Exception {
//创建加密对象 transformation加密算法
Cipher cipher = Cipher.getInstance(transformation);
//创建加密规则 第一个参数key字节 第二个参数表示加密类型
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 进行加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
// 调用加密方法
// 参数是原文的字节数组
byte[] bytes = cipher.doFinal(text.getBytes());
/*for (byte aByte : bytes) {
System.out.println(aByte);
}
// 如果直接打印密文会出现乱码,是因为在编码表里面找不到对应的字符,ascii码只有正数
System.out.println(new String(bytes));*/
// 使用base64 转码
return Base64.encode(bytes);
}
/**
* 解密
*
* @param encrypt 密文
* @param key 秘钥
* @param transformation 加密算法
* @param algorithm 机密类型
* @return 解密后的内容
*/
private static String decryptECB(String encrypt, String key, String transformation, String algorithm) throws Exception {
byte[] decode = Base64.decode(encrypt);
Cipher cipher = Cipher.getInstance(transformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 进行加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
// 调用解密方法
byte[] bytes = cipher.doFinal(decode);
return new String(bytes);
}
/**
* 使用DES加密
*
* @param text 原文
* @param key 密钥
* @param transformation 加密算法
* @param algorithm 加密类型
* @throws Exception
*/
private static String encryptCBC(String text, String key, String transformation, String algorithm) throws Exception {
//创建加密对象 transformation加密算法
Cipher cipher = Cipher.getInstance(transformation);
//创建加密规则 第一个参数key字节 第二个参数表示加密类型
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 创建IV向量 在使用iv向量是 iv的字节也必须要8个字节
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
// 进行加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
// 调用加密方法
// 参数是原文的字节数组
byte[] bytes = cipher.doFinal(text.getBytes());
/*for (byte aByte : bytes) {
System.out.println(aByte);
}
// 如果直接打印密文会出现乱码,是因为在编码表里面找不到对应的字符,ascii码只有正数
System.out.println(new String(bytes));*/
// 使用base64 转码
return Base64.encode(bytes);
}
/**
* 解密
*
* @param encrypt 密文
* @param key 秘钥
* @param transformation 加密算法
* @param algorithm 机密类型
* @return 解密后的内容
*/
private static String decryptCBC(String encrypt, String key, String transformation, String algorithm) throws Exception {
byte[] decode = Base64.decode(encrypt);
Cipher cipher = Cipher.getInstance(transformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 创建IV向量
IvParameterSpec iv = new IvParameterSpec(key.getBytes());
// 进行加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
// 调用解密方法
byte[] bytes = cipher.doFinal(decode);
return new String(bytes);
}
/**
* 使用DES加密
*
* @param text 原文
* @param key 密钥
* @param transformation 加密算法
* @param algorithm 加密类型
* @throws Exception
*/
private static String encryptNoPadding(String text, String key, String transformation, String algorithm) throws Exception {
//创建加密对象 transformation加密算法
Cipher cipher = Cipher.getInstance(transformation);
//创建加密规则 第一个参数key字节 第二个参数表示加密类型
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 进行加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
// 调用加密方法
// 参数是原文的字节数组
return Base64.encode(cipher.doFinal(addZero(text.getBytes())));
}
/**
* NoPadding 补0
* 在DES加密算法下,要求原文长度必须是8Byte的整数倍。
* 在AES加密算法下,要求原文长度必须是16Byte的整数倍.
*
* @param data 数组
* @return 补0之后
*/
private static byte[] addZero(byte[] data) {
byte[] dataByte = data;
if (data.length % 8 != 0) {
byte[] temp = new byte[8 - data.length % 8];
dataByte = byteMerger(data, temp);
}
return dataByte;
}
/**
* java 合并两个byte数组
* System.arraycopy()方法
*
* @param bt1 数组1
* @param bt2 数组2
* @return 合并结果
*/
private static byte[] byteMerger(byte[] bt1, byte[] bt2) {
byte[] bt3 = new byte[bt1.length + bt2.length];
System.arraycopy(bt1, 0, bt3, 0, bt1.length);
System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
return bt3;
}
}
7、AES加密实现
package com.lh.basecryptology.desaes;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AesDemo {
public static void main(String[] args) throws Exception {
// 原文
String text = "十里洋场,遍地黄金";
// 密钥 如果用AES加密密钥必须16个字节
String key = "1234567812345678";
// 算法
String transformation = "AES";
// 加密类型
String algorithm = "AES";
String encrypt = encryptAES(text, key, transformation, algorithm);
System.out.println("密文:" + encrypt);
String decrypt = decryptAES(encrypt, key, transformation, algorithm);
System.out.println("原文:" + decrypt);
}
/**
* 解密
*
* @param encrypt 密文
* @param key 秘钥
* @param transformation 加密算法
* @param algorithm 机密类型
* @return 解密后的内容
*/
private static String decryptAES(String encrypt, String key, String transformation, String algorithm) throws Exception {
byte[] decode = Base64.decode(encrypt);
Cipher cipher = Cipher.getInstance(transformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 进行AES加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
// 调用解密方法
byte[] bytes = cipher.doFinal(decode);
return new String(bytes);
}
/**
* 使用AES加密
*
* @param text 原文
* @param key 密钥
* @param transformation 加密算法
* @param algorithm 加密类型
* @throws Exception
*/
private static String encryptAES(String text, String key, String transformation, String algorithm) throws Exception {
//创建加密对象 transformation加密算法
Cipher cipher = Cipher.getInstance(transformation);
//创建加密规则 第一个参数key字节 第二个参数表示加密类型
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
// 进行AES加密初始化 第一个参数表示模式 加密模式和解密模式 第二个参数表示加密规则
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
// 调用加密方法
// 参数是原文的字节数组
byte[] bytes = cipher.doFinal(text.getBytes());
/*for (byte aByte : bytes) {
System.out.println(aByte);
}
// 如果直接打印密文会出现乱码,是因为在编码表里面找不到对应的字符,ascii码只有正数
System.out.println(new String(bytes));*/
// 使用base64 转码
return Base64.encode(bytes);
}
}