文章目录
- java数据安全 系列文章
- 一、maven依赖
- 二、对称加密算法
- 1、介绍
- 2、DES
- 1)、介绍
- 2)、应用场景
- 3)、DES示例
- 1、实现源码
- 2、testNG测试
- 4)、3DES示例
- 1、实现源码
- 2、testNG测试
- 3、AES
- 1)、介绍
- 2)、应用场景
- 3)、示例
- 1、实现源码
- 2、testNG测试
- 4、IDEA
- 1)、介绍
- 2)、应用场景
- 3)、示例
- 1、实现源码
- 2、testNG测试
- 5、PBE
- 1)、介绍
- 2)、应用场景
- 3)、示例
- 1、实现源码
- 2、testNG测试
本文简单的介绍了对称加密的5种(DES/3DES、AES、IDEA、PBE)常见算法的使用示例,并给出推荐的应用示例。
一、maven依赖
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
二、对称加密算法
1、介绍
对称加密就是加密与解密拥有相同的密钥,根据加密方式可分为密码和分组密码。
分组密码工作模式可分为ECB、CBC、CFB、OFB和CTR等,密钥长度决定了加密算法的安全性。
常见的加密算法有DES或3DES、AES和RC系列算法,除此之外,还有Blowfish、Twofish、Serpent、IDEA和PBE等。
2、DES
1)、介绍
DES(Data Encryption Standard)数据加密标准,其衍生算法有DESede(3DES),由于安全性的原因AES逐步替代DES。
2)、应用场景
应用于安全性要求不高的对称加密场景,基本上不用DES,3DES是其替代。
3)、DES示例
以下是jdk实现示例
1、实现源码
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
/**
* @author alan 2018年11月16日
*/
public class DESCoder {
/**
* 密钥算法 <br>
* Java 6 只支持56bit密钥 <br>
* Bouncy Castle 支持64bit密钥
*/
public static final String KEY_ALGORITHM = "DES";
/**
* 加密/解密算法 / 工作模式 / 填充方式
*/
public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5PADDING";
/**
* 转换密钥
*
* @param key
* 二进制密钥
* @return Key 密钥
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
// 实例化DES密钥材料
DESKeySpec dks = new DESKeySpec(key);
// 实例化秘密密钥工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
// 生成秘密密钥
SecretKey secretKey = keyFactory.generateSecret(dks);
return secretKey;
}
/**
* 解密
*
* @param data
* 待解密数据
* @param key
* 密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
// 实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* 待加密数据
* @param key
* 密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
// 实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 生成密钥 <br>
* Java 6 只支持56bit密钥 <br>
* Bouncy Castle 支持64bit密钥 <br>
*
* @return byte[] 二进制密钥
* @throws Exception
*/
public static byte[] initKey() throws Exception {
/*
* 实例化密钥生成器
*
* 若要使用64bit密钥注意替换 将下述代码中的KeyGenerator.getInstance(CIPHER_ALGORITHM);
* 替换为KeyGenerator.getInstance(CIPHER_ALGORITHM, "BC");
*/
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
/*
* 初始化密钥生成器 若要使用64bit密钥注意替换 将下述代码kg.init(56); 替换为kg.init(64);
*/
kg.init(56, new SecureRandom());
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制编码形式
return secretKey.getEncoded();
}
}
2、testNG测试
import static org.testng.Assert.assertEquals;
import org.apache.commons.codec.binary.Base64;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月16日
*/
public class DESCoderTest {
@Test
public final void test() throws Exception {
String inputStr = "DES";
byte[] inputData = inputStr.getBytes();
System.err.println("原文:\t" + inputStr);
// 初始化密钥
byte[] key = DESCoder.initKey();
System.err.println("密钥:\t" + Base64.encodeBase64String(key));
// 加密
inputData = DESCoder.encrypt(inputData, key);
System.err.println("加密后:\t" + Base64.encodeBase64String(inputData));
// 解密
byte[] outputData = DESCoder.decrypt(inputData, key);
String outputStr = new String(outputData);
System.err.println("解密后:\t" + outputStr);
// 校验
assertEquals(inputStr, outputStr);
}
}
4)、3DES示例
以下是jdk实现示例
1、实现源码
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
/**
* @author alan 2018年11月16日
*/
public class DESedeCoder {
public static final String KEY_ALGORITHM = "DESede";
/**
* 加密/解密算法 / 工作模式 / 填充方式 Java 6支持PKCS5PADDING填充方式 Bouncy
* Castle支持PKCS7Padding填充方式
*/
public static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
/**
* 转换密钥
*
* @param key
* 二进制密钥
* @return Key 密钥
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
// 实例化DES密钥材料
DESedeKeySpec dks = new DESedeKeySpec(key);
// 实例化秘密密钥工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
// 生成秘密密钥
SecretKey secretKey = keyFactory.generateSecret(dks);
return secretKey;
}
/**
* 解密
*
* @param data
* 待解密数据
* @param key
* 密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
/*
* 实例化 使用PKCS7Padding填充方式 Cipher.getInstance(CIPHER_ALGORITHM, "BC");
*/
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* 待加密数据
* @param key
* 密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
/*
* 实例化 使用PKCS7Padding填充方式 Cipher.getInstance(CIPHER_ALGORITHM, "BC");
*/
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 生成密钥 <br>
*
* @return byte[] 二进制密钥
* @throws Exception
*/
public static byte[] initKey() throws Exception {
// 实例化
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
/*
* DESede 要求密钥长度为 112位或168位
*/
kg.init(168);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制编码形式
return secretKey.getEncoded();
}
}
2、testNG测试
import static org.testng.Assert.assertEquals;
import org.apache.commons.codec.binary.Base64;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月16日
*/
public class DESedeCoderTest {
@Test
public final void test() throws Exception {
String inputStr = "DESede";
byte[] inputData = inputStr.getBytes();
System.err.println("原文:\t" + inputStr);
// 初始化密钥
byte[] key = DESedeCoder.initKey();
System.err.println("密钥:\t" + Base64.encodeBase64String(key));
// 加密
inputData = DESedeCoder.encrypt(inputData, key);
System.err.println("加密后:\t" + Base64.encodeBase64String(inputData));
// 解密
byte[] outputData = DESedeCoder.decrypt(inputData, key);
String outputStr = new String(outputData);
System.err.println("解密后:\t" + outputStr);
// 校验
assertEquals(inputStr, outputStr);
}
}
3、AES
1)、介绍
AES(Advanced Encryption Standard)高级数据加密标准,作为DES算法的替代。AES算法具有密钥建立时间短、灵敏性好、内存需求低等优点,应用比较广泛。
2)、应用场景
作为DES的替代,在对称加密中一般场合的首选。
3)、示例
以下是jdk实现示例
1、实现源码
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* @author alan 2018年11月16日
*/
public class AESCoder {
public static final String KEY_ALGORITHM = "AES";
/**
* 加密/解密算法 / 工作模式 / 填充方式 Java 6支持PKCS5Padding填充方式 Bouncy
* Castle支持PKCS7Padding填充方式
*/
public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 转换密钥
*
* @param key
* 二进制密钥
* @return Key 密钥
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
// 实例化AES密钥材料
SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
return secretKey;
}
/**
* 解密
*
* @param data
* 待解密数据
* @param key
* 密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
/*
* 实例化 使用PKCS7Padding填充方式,按如下方式实现 Cipher.getInstance(CIPHER_ALGORITHM, "BC");
*/
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* 待加密数据
* @param key
* 密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
// 还原密钥
Key k = toKey(key);
/*
* 实例化 使用PKCS7Padding填充方式,按如下方式实现 Cipher.getInstance(CIPHER_ALGORITHM, "BC");
*/
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 生成密钥 <br>
*
* @return byte[] 二进制密钥
* @throws Exception
*/
public static byte[] initKey() throws Exception {
// 实例化
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
/*
* AES 要求密钥长度为 128位、192位或 256位
*/
kg.init(256);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制编码形式
return secretKey.getEncoded();
}
}
2、testNG测试
import static org.testng.Assert.assertEquals;
import org.apache.commons.codec.binary.Base64;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月16日
*/
public class AESCoderTest {
@Test
public final void test() throws Exception {
String inputStr = "AES";
byte[] inputData = inputStr.getBytes();
System.err.println("原文:\t" + inputStr);
// 初始化密钥
byte[] key = AESCoder.initKey();
System.err.println("密钥:\t" + Base64.encodeBase64String(key));
// 加密
inputData = AESCoder.encrypt(inputData, key);
System.err.println("加密后:\t" + Base64.encodeBase64String(inputData));
// 解密
byte[] outputData = AESCoder.decrypt(inputData, key);
String outputStr = new String(outputData);
System.err.println("解密后:\t" + outputStr);
// 校验
assertEquals(inputStr, outputStr);
}
}
4、IDEA
1)、介绍
IDEA(International Data Encryption Algorithm)国际数据加密算法是一种对称分组密码,其密钥长度为128位,数据块大小为64位,目前常用的场景是邮件加密算法。
2)、应用场景
目前常用的场景是邮件加密算法
3)、示例
以下是bouncy castle实现示例
1、实现源码
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* @author alan 2018年11月16日
*/
public class IDEACoder {
public static final String KEY_ALGORITHM = "IDEA";
/**
* 加密/解密算法 / 工作模式 / 填充方式
*/
public static final String CIPHER_ALGORITHM = "IDEA/ECB/PKCS5Padding";
/**
* 转换密钥
*
* @param key
* 二进制密钥
* @return Key 密钥
* @throws Exception
*/
private static Key toKey(byte[] key) throws Exception {
// 生成秘密密钥
SecretKey secretKey = new SecretKeySpec(key, KEY_ALGORITHM);
return secretKey;
}
/**
* 解密
*
* @param data
* 待解密数据
* @param key
* 密钥
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 还原密钥
Key k = toKey(key);
// 实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 加密
*
* @param data
* 待加密数据
* @param key
* 密钥
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 还原密钥
Key k = toKey(key);
// 实例化
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,设置为加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
// 执行操作
return cipher.doFinal(data);
}
/**
* 生成密钥 <br>
*
* @return byte[] 二进制密钥
* @throws Exception
*/
public static byte[] initKey() throws Exception {
// 加入BouncyCastleProvider支持
Security.addProvider(new BouncyCastleProvider());
// 实例化
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
// 初始化
kg.init(128);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制编码形式
return secretKey.getEncoded();
}
}
2、testNG测试
import static org.testng.Assert.assertEquals;
import org.apache.commons.codec.binary.Base64;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月16日
*/
public class IDEACoderTest {
@Test
public final void test() throws Exception {
String inputStr = "IDEA";
byte[] inputData = inputStr.getBytes();
System.err.println("原文:\t" + inputStr);
// 初始化密钥
byte[] key = IDEACoder.initKey();
System.err.println("密钥:\t" + Base64.encodeBase64String(key));
// 加密
inputData = IDEACoder.encrypt(inputData, key);
System.err.println("加密后:\t" + Base64.encodeBase64String(inputData));
// 解密
byte[] outputData = IDEACoder.decrypt(inputData, key);
String outputStr = new String(outputData);
System.err.println("解密后:\t" + outputStr);
// 校验
assertEquals(inputStr, outputStr);
}
}
5、PBE
1)、介绍
PBE(Password Based Encryption)基于密码加密算法是一种基于密码的加密算法,其特点是密码(password)由用户自己保管,采用随机数(加盐)杂凑多重加密等方法保证数据的安全性。PBE没有密钥,其密码(password)代替了密钥,为了增加密码的安全性,采用了加盐的处理方式。PBE是对称加密算法的综合性算法,常见的算法有PBEWithMD5AndDES,该算法是使用了MD5和DES构建PBE算法。
2)、应用场景
PBE算法通常用于需要用户输入口令的场合,例如保护用户数据。
3)、示例
以下是jdk实现示例
1、实现源码
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
/**
* @author alan 2018年11月16日
*/
public class PBECoder {
/**
* Java 6 支持以下任意一种算法
*
* <pre>
* PBEWithMD5AndDES
* PBEWithMD5AndTripleDES
* PBEWithSHA1AndDESede
* PBEWithSHA1AndRC2_40
* </pre>
*/
public static final String ALGORITHM = "PBEWithMD5AndTripleDES";
/**
* 盐初始化<br>
* 盐长度必须为8字节
*
* @return byte[] 盐
* @throws Exception
*/
public static byte[] initSalt() throws Exception {
SecureRandom random = new SecureRandom();
return random.generateSeed(8);
}
/**
* 转换密钥
*
* @param password 密码
* @return Key 密钥
* @throws Exception
*/
private static Key toKey(String password) throws Exception {
// 密钥材料转换
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
// 实例化
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
// 生成密钥
SecretKey secretKey = keyFactory.generateSecret(keySpec);
return secretKey;
}
/**
* 加密
*
* @param data 数据
* @param password 密码
* @param salt 盐
* @return byte[] 加密数据
* @throws Exception
*/
public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception {
// 转换密钥
Key key = toKey(password);
// 实例化PBE参数材料
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
// 实例化
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化
cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
// 执行操作
return cipher.doFinal(data);
}
/**
* 解密
*
* @param data 数据
* @param password 密码
* @param salt 盐
* @return byte[] 解密数据
* @throws Exception
*/
public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception {
// 转换密钥
Key key = toKey(password);
// 实例化PBE参数材料
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
// 实例化
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 初始化
cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
// 执行操作
return cipher.doFinal(data);
}
}
2、testNG测试
import static org.testng.Assert.assertEquals;
import org.apache.commons.codec.binary.Base64;
import org.testng.annotations.Test;
/**
* @author alan 2018年11月16日
*/
public class PBECoderTest {
@Test
public void test() throws Exception {
String inputStr = "PBE";
System.err.println("原文:" + inputStr);
byte[] input = inputStr.getBytes();
String pwd = "alanchan";
System.err.println("密码:\t" + pwd);
// 初始化盐
byte[] salt = PBECoder.initSalt();
System.err.println("盐:\t" + Base64.encodeBase64String(salt));
// 加密
byte[] data = PBECoder.encrypt(input, pwd, salt);
System.err.println("加密后:\t" + Base64.encodeBase64String(data));
// 解密
byte[] output = PBECoder.decrypt(data, pwd, salt);
String outputStr = new String(output);
System.err.println("解密后:\t" + outputStr);
// 校验
assertEquals(inputStr, outputStr);
}
}
以上,简单的介绍了对称加密的5种常见算法的使用示例,并给出推荐的应用示例。