文章目录
对称加密在Java中的使用
在之前的文章中,我们已经将要介绍了对称加密(后期链接到前面的文章),现在我们将了解Java对于对称加密的支持。
DES
我们先介绍Java中DES的使用
DESCoder 工具类
import java.security.GeneralSecurityException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* DES 安全编码组件
*
* @author shaozuo
*
* @version 2018年7月2日
*/
public final class DESCoder {
public static final String DES = "DES";
private DESCoder() {
}
/**
* 使用Java 提供的DES 实现<br>
*
* @return 密钥 按照一定编码格式编码的密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey() throws GeneralSecurityException {
return initKey(56);
}
/**
* 生成密钥 使用默认的Provider<br>
* java只支持56位 <br>
*
* @return 密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey(int keySize) throws GeneralSecurityException {
// 实例化密钥生成器
KeyGenerator kg = KeyGenerator.getInstance(DES);
// 初始化
kg.init(keySize);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制表示形式
return secretKey.getEncoded();
}
/**
* 生成密钥 <br>
* java只支持56位 <br>
* Bouncy Castle 支持64 位
*
* @return 密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey(int keySize, String providerName) throws GeneralSecurityException {
// 实例化密钥生成器
KeyGenerator kg = KeyGenerator.getInstance(DES, providerName);
// 初始化
kg.init(keySize);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制表示形式
return secretKey.getEncoded();
}
}
测试代码
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.security.GeneralSecurityException;
import java.security.InvalidParameterException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* DES 测试
*
* @author shaozuo
*
*/
public class DESTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
/**
* Java 本身自带的DES算法实现<br>
* 密钥长度只能是56位,否则会抛出异常
*
* @throws GeneralSecurityException
*/
@Test
public void testJdkKeySize() throws GeneralSecurityException {
// 支持56位密钥
DESCoder.initKey(56);
thrown.expect(InvalidParameterException.class);
thrown.expectMessage("Wrong keysize: must be equal to 56");
// 不支持64位DES密码
DESCoder.initKey(64);
}
/**
* BouncyCastle 支持64位DES密钥<br>
*
* @throws GeneralSecurityException
*/
@Test
public void testBcKeySize() throws GeneralSecurityException {
Security.addProvider(new BouncyCastleProvider());
DESCoder.initKey(64, BouncyCastleProvider.PROVIDER_NAME);
}
/**
* DES 加密解密测试
*
* @throws Exception
*/
@Test
public void testEncyptDecypt() throws Exception {
String raw = "待加密数据";
byte[] rawData = raw.getBytes();
byte[] keyData = DESCoder.initKey();
DESKeySpec desKeySpec = new DESKeySpec(keyData);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(DESCoder.DES);
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance(DESCoder.DES);
// 加密数据
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptData = cipher.doFinal(rawData);
// 解密数据
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptData = cipher.doFinal(encryptData);
assertArrayEquals(rawData, decryptData);
assertEquals(raw, new String(decryptData));
}
}
AES
接下来我们用代码来使用AES加密算法
工具类
import java.security.GeneralSecurityException;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* AES 安全编码组件
*
* @author shaozuo
*
* @version 2018年7月2日
*/
public final class AESCoder {
public static final String ALGORITHM_NAME = "AES";
private AESCoder() {
}
/**
* 使用Java 提供的AES 实现<br>
*
* @return 密钥 按照一定编码格式编码的密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey() throws GeneralSecurityException {
return initKey(128);
}
/**
* 生成密钥 使用默认的Provider<br>
* Java 支持128、192、256位(需要获取无限制文件) <br>
*
* @return 密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey(int keySize) throws GeneralSecurityException {
// 实例化密钥生成器
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME);
// 初始化
kg.init(keySize);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制表示形式
return secretKey.getEncoded();
}
/**
* 生成密钥 <br>
* Java 支持128、192、256位 <br>
* Bouncy Castle 支持64 位
*
* @return 密钥
* @throws GeneralSecurityException
*/
public static byte[] initKey(int keySize, String providerName) throws GeneralSecurityException {
// 实例化密钥生成器
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, providerName);
// 初始化
kg.init(keySize);
// 生成秘密密钥
SecretKey secretKey = kg.generateKey();
// 获得密钥的二进制表示形式
return secretKey.getEncoded();
}
}
测试
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.security.GeneralSecurityException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;
public class AESTest {
@Test
public void test() throws GeneralSecurityException {
Security.addProvider(new BouncyCastleProvider());
String raw = "待加密数据";
byte[] rawData = raw.getBytes();
byte[] keyData = AESCoder.initKey(256, BouncyCastleProvider.PROVIDER_NAME);
SecretKeySpec keySpec = new SecretKeySpec(keyData, AESCoder.ALGORITHM_NAME);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(keySpec.getAlgorithm());
SecretKey secretKey = keyFactory.generateSecret(keySpec);
// 加密解密算法/工作模式/填充方式
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 加密数据
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptData = cipher.doFinal(rawData);
System.out.println(Base64.encodeBase64String(encryptData));
// 解密数据
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptData = cipher.doFinal(encryptData);
System.out.println(Base64.encodeBase64String(decryptData));
assertArrayEquals(rawData, decryptData);
assertEquals(raw, new String(decryptData));
}
}
参考文章
关于本章内容,参考了一下书籍和文章
- Java加密与解密的艺术 链接