对称加密是使用相同的密码进行加密和解密, 对称加密实现简单,安全性相比非对称加密较弱, 常用的对称加密算法有 DES,AES以及PDE等,关于对称加密相关概念参考:
对称加密、非对称加密深度解析
本篇介绍Java的DES和AES的加密和解密, 关于PDE算法的加解密实现, 可以参考:
Java使用PBE算法进行对称加解密最简入门和示例
DES 加密和解密
在Java语言中, DES 算法使用一个密钥进行加密和解密,使用密码规范(DESKeySpec)和密钥工厂(SecretKeyFactory)生成密钥。通过Cipher类来进行加密和解密操作,使用“DES/ECB/PKCS5Padding”作为加密算法和填充模式。
DES加密示例代码:
/**
* DES 对称加密
*/
@Test
public void desEncrypt() throws Exception {
String plainText = "需要加密的内容";
String secretKey = "this is password";
DESKeySpec desKeySpec = new DESKeySpec(secretKey.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("DES加密后的内容=" + encryptedText);
}
DES 解密示例代码:
@Test
public void desDecrypt() throws Exception {
String encryptedText = "HAyFHQXRKmihGtxFsrZlAJwla4FE3aqS";
String secretKey = "this is password";
DESKeySpec desKeySpec = new DESKeySpec(secretKey.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
String plainText = new String(decryptedBytes, StandardCharsets.UTF_8);
System.out.println("DES解密的内容=" + plainText);
}
这里为什么是DES/ECB/PKCS5Padding , 而不直接是 DES呢?
DES/ECB/PKCS5Padding 是一种加密算法和模式的规范,常用于对数据进行加密和解密操作。
具体来说:
- DES(Data Encryption Standard)是一种对称加密算法,它使用相同的密钥(通常是 56 位长)进行加密和解密操作。
- ECB(Electronic Codebook)是一种加密模式,它将输入的数据分成块,每块独立进行加密运算。
- PKCS5Padding 是一种填充模式,它在数据块长度不足时,使用特定的填充方式进行填充,使每个数据块的长度达到指定长度。
DES/ECB/PKCS5Padding 相比其他加密算法和模式,具有以下优点和缺点:
优点:
-
运算速度相对较快,适合对大数据流进行加密和解密操作;
-
实现比较简单,可在多种编程语言和平台上进行实现;
-
加密后的数据大小不会增加。
缺点:
-
ECB 模式不具备随机性和反复率,相邻数据块可能会产生相同的密文,容易受到攻击;
-
密钥长度较短,安全性相对较低,易受到暴力破解和密码分析攻击;
使用相同密钥加密同一数据,密文总是相同,可容易地进行重放攻击和密码攻击。
因此,对于加密性能要求较高,安全要求相对较低的场景,可以选择使用 DES/ECB/PKCS5Padding 进行加密和解密操作。对于安全性要求较高的场景,应该考虑使用更加安全和可靠的加密算法和模式,比如 AES、RSA、CBC、GCM 等。
AES 加密和解密
AES 的加解密和DES很类似,直接看代码:
AES加密代码示例:
@Test
public void encryptAES() throws Exception {
String plainText = "需要加密的内容";
String secretKey = "this is password";
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("AES加密后的内容=" + encryptedText);
}
AES解密代码示例:
@Test
public void decryptAES() throws Exception {
String encryptedText = "oL2b5xULTtAmfi4ujnpw/jPamo0nTNCgRC9Bo+SBz7k=";
String secretKey = "this is password";
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
String plainText = new String(decryptedBytes, StandardCharsets.UTF_8);
System.out.println("AES解密的内容=" + plainText);
}
AES(Advanced Encryption Standard)使用相同的密钥进行加密和解密操作。这个示例中使用密钥字符串构建了一个 AES 密钥规范(SecretKeySpec),并通过 Cipher 类来进行加密和解密操作,使用 “AES/ECB/PKCS5Padding” 作为加密算法和填充模式。
需要注意的是,AES 是一个块密码算法,不同于 DES 等分块密码,它支持不同的密钥长度,如 AES-128、AES-192 和 AES-256。
在实际应用中,为了保证安全性,密钥应该足够长,同时需要确保密钥的安全生成、存储和传输。
Java 8 找不到 javax.crypto.spec.SecretKeySpec问题解决
在Java 11 和Java 17版本中,上面示例运行正常,但是在Java 8 中会提示找不到 javax.crypto.spec.SecretKeySpec,在及基于Eclipse 开发中, 虽然import 了SecretKeySpec , 但是会提示找不到这个类:
The import javax.crypto.spec.SecretKeySpec cannot be resolved
这里需要下载jce的扩展包,下载地址:
https://www.oracle.com/java/technologies/javase-jce8-downloads.html
下载后解压,
将 local_policy.jar 和US_export_policy.jar 放入JRE 的security目录中,比如C:\Program Files\Java\jdk1.8.0_361\jre\lib\security\policy\unlimited
, 覆盖该目录下的同名文件:
之后在 Eclipse 的项目中导入这两个文件。
在线代码
- https://github.com/osxm/java-ency/blob/master/src/main/java/com/osxm/je/topic/security/SymmetricEncy.java