序言
对称加密算法,加密与解密的密钥是一样的,密钥管理比较困难,容易泄露,一旦泄露就会很容易导致数据不安全。
相关概念
明文: 数据没有进行加密,原始数据信息。
密文: 加密过后得到的数据, 隐藏了原始数据的含义。
加密 : 将明文转为密文的过程。
解密 : 将密文转为明文的过程。
密钥: 是一种参数,是在加密或解密中输入的参数。
对称加密
定义: 指的是加密与解密使用相同的密钥。这种加密方式称为对称加密。
对称加密一般有: DES 、 3DES 、 AES 、 PBE
- DES(Data Encryption Standard): 数据加密标准,速度较快,适用于加密大量数据的场合。
- 3DES(Triple DES): 基于DES, 对一块数据用三个不同的密钥进行三次加密,强度更高。
- AES(Advanced Encryption Standard): 高级加密标准,是下一代的加密算法标准,速度快,安全级别高,支持128、192、256、512位密钥的加密。
- PBE(Password Based Encryption): 是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
对称加密特征:
- 加密方和解密方使用同一个密钥。
- 加密与解密的速度较快。
- 密钥传输过程不安全,且容易被破解,密钥管理也很麻烦。
代码实现:
DES算法
/**
* @program
* @Desc
* @Author 游戏人日常
* @CreateTime 2019/08/11--2:21
*/
public class DesTest {
//转化格式
public static final String TRAMSFORMATION = "DES/ECB/PKCS5Padding";
//算法 DES
public static final String ALGORITHM = "DES";
//待加密的源串
public static final String msg = "helloWorld";
//密钥
public static final String key = "123456789";
public static void main(String args[]) {
System.out.println("待加密数据: " + msg);
byte[] encryptStr = encrypt(msg, key);
System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
byte[] decryptStr = decrypt(encryptStr, key);
System.out.println("解密后的结果:" + new String(decryptStr));
}
/**
* 解密
* @param encryptionStr 加密的数据
* @param key 密钥
* @return
*/
private static byte[] decrypt(byte[] encryptionStr, String key) {
try {
//1.KEY转换
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
Key convertKey = factory.generateSecret(desKeySpec);
//2.解密 DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
cipher.init(Cipher.DECRYPT_MODE, convertKey );
byte[] result = cipher.doFinal(encryptionStr);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @param encryptionStr 待加密的串
* @param key 密钥
* @return
*/
public static byte[] encrypt(String encryptionStr, String key) {
try {
//1.KEY转换
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
Key convertKey = factory.generateSecret(desKeySpec);
//2.加密 DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
cipher.init(Cipher.ENCRYPT_MODE, convertKey );
byte[] result = cipher.doFinal(encryptionStr.getBytes());//输入要加密的内容
return result;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
输出结果
待加密数据: helloWorld
加密后以十六进制输出的结果: -60fd73ff69e3352e5e2e976c55e6ed92
解密后的结果:helloWorld
3DES算法
/**
* @program
* @Desc
* @Author 游戏人日常
* @CreateTime 2019/08/11--14:45
*/
public class DES3Test {
//转化格式
public static final String TRAMSFORMATION = "DESEde/ECB/PKCS5Padding";
//算法 DES
public static final String ALGORITHM = "DESEde";
//待加密的源串
public static final String msg = "helloWorld";
//密钥
public static final String key = "1234567812345678123456789";
public static void main(String[] args) {
System.out.println("待加密数据: " + msg);
byte[] encryptStr = encrypt(msg, key);
System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
byte[] decryptStr = decrypt(encryptStr, key);
System.out.println("解密后的结果:" + new String(decryptStr));
}
/**
* 解密
*
* @param encryptionStr 加密的数据
* @param key 密钥
* @return
*/
private static byte[] decrypt(byte[] encryptionStr, String key) {
try {
//1.生成KEY
DESedeKeySpec desKeySpec = new DESedeKeySpec(key.getBytes());//实例化DESKey秘钥的相关内容
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);//实例一个秘钥工厂,指定加密方式
Key convertKey = factory.generateSecret(desKeySpec);
//2.解密 DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
cipher.init(Cipher.DECRYPT_MODE, convertKey );
byte[] result = cipher.doFinal(encryptionStr);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] encrypt(String encryptionStr, String key) {
try {
//1.转换KEY
DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(key.getBytes());
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
Key convertKey = factory.generateSecret(deSedeKeySpec);
//2.加密
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, convertKey);
byte[] result = cipher.doFinal(encryptionStr.getBytes());
return result;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
输出结果
待加密数据: helloWorld
加密后以十六进制输出的结果: -60fd73ff69e3352e5e2e976c55e6ed92
解密后的结果:helloWorld
AES算法
/**
* @program
* @Desc
* @Author 游戏人日常
* @CreateTime 2019/08/11--15:16
*/
public class AESTest {
//转化格式
public static final String TRAMSFORMATION = "AES/ECB/PKCS5Padding";
//算法 DES
public static final String ALGORITHM = "AES";
//待加密的源串
public static final String msg = "helloWorld";
//密钥
public static final String key = "1234567812345678";
public static void main(String[] args) {
System.out.println("待加密数据: " + msg);
byte[] encryptStr = encrypt(msg, key);
System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
byte[] decryptStr = decrypt(encryptStr, key);
System.out.println("解密后的结果:" + new String(decryptStr));
}
/**
* 解密
*
* @param encryptionStr 加密的数据
* @param key 密钥
* @return
*/
private static byte[] decrypt(byte[] encryptionStr, String key) {
try {
//1.转换KEY
Key convertKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
//2.解密 DES/ECB/PKCS5Padding--->算法/工作方式/填充方式
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);//通过Cipher这个类进行加解密相关操作
cipher.init(Cipher.DECRYPT_MODE, convertKey);
byte[] result = cipher.doFinal(encryptionStr);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] encrypt(String encryptionStr, String key) {
try {
//1.转换KEY
Key convertKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
//2.加密
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, convertKey);
byte[] result = cipher.doFinal(encryptionStr.getBytes());
return result;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
输出结果
待加密数据: helloWorld
加密后以十六进制输出的结果: -680bb3194a04ff1ece4e28227012ad33
解密后的结果:helloWorld
PBE算法
/**
* @program
* @Desc
* @Author 游戏人日常
* @CreateTime 2019/08/11--15:55
*/
public class PBETest {
//转化格式
public static final String TRAMSFORMATION = "PBEWITHMD5andDES";
//待加密的源串
public static final String msg = "helloWorld";
//密钥
public static final String key = "123456789";
public static void main(String args[]) {
byte[] salt=initSalt();//初始化salt
System.out.println("待加密数据: " + msg);
byte[] encryptStr = encrypt(salt,msg,key);
System.out.println("加密后以十六进制输出的结果: " + new BigInteger(encryptStr).toString(16));//以十六进制输出
byte[] decryptStr = decrypt(salt,encryptStr, key);
System.out.println("解密后的结果:" + new String(decryptStr));
}
public static byte[] initSalt(){
SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(8);
return salt;
}
/**
* 解密
* @param salt
* @param encryptionStr 加密的数据
* @param key 这个是加密用的口令
* @return
*/
private static byte[] decrypt(byte[] salt, byte[] encryptionStr, String key) {
try {
//1.转换KEY
PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance(TRAMSFORMATION);
Key convertKey = factory.generateSecret(pbeKeySpec);
//2.解密
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);//100是你选择迭代的次数
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, convertKey, parameterSpec);
byte[] result = cipher.doFinal(encryptionStr);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 加密
* @param salt
* @param encryptionStr 待加密的串
* @param key 这个是加密用的口令
* @return
*/
public static byte[] encrypt(byte[] salt,String encryptionStr,String key) {
try {
//1.转换KEY
PBEKeySpec pbeKeySpec = new PBEKeySpec(key.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance(TRAMSFORMATION);
Key convertKey = factory.generateSecret(pbeKeySpec);
//2. 加密
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);//100是你选择迭代的次数
Cipher cipher = Cipher.getInstance(TRAMSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, convertKey, parameterSpec);
byte[] result = cipher.doFinal(encryptionStr.getBytes());
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
输出结果
待加密数据: helloWorld
加密后以十六进制输出的结果: 450056595e1fbcc4f35bf855bd18dee2
解密后的结果:helloWorld
总结
- 这些对称算法全是JDK自带的API实现,也可以用第三方(BouncyCastle)的实现。
- 不同的算法对key的长度有要求,通过查看jdk代码发现DES的key必须大于8,3DES大于24等等。 否则会抛异常:Wrong key size
- 这些对称算法的底层原理是怎么实现的本文没有叙述,具体怎么实现请查看其它的资料。
对称算法优缺点
优点
速度快,通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。
缺点
在数据传输前,发送和接收方必须确定好密钥,然后双方都能保存这个密钥,一旦泄露那么数据的传输这个过程就很不安全。