0%

DES对称加密

DES 对称加密算法详解

DES(Data Encryption Standard,数据加密标准)是一种经典的对称加密算法,尽管已逐渐被安全性更高的 AES 取代,但作为对称加密的重要里程碑,其设计思想对理解加密算法具有重要意义。

DES 的核心特性

  • 对称加密:加密和解密使用相同的密钥,密钥长度固定为56 位(实际存储为 64 位,含 8 位奇偶校验位)。
  • 分组加密:将明文按 64 位分组,逐组加密,最后一组不足 64 位时需填充。
  • 安全性:由于密钥长度较短(56 位),在现代计算能力下可被暴力破解,安全性已不足,但仍在部分 legacy 系统中使用。
  • 工作模式:支持 ECB、CBC、CFB 等多种分组加密模式(示例代码中未指定,默认使用 ECB 模式,安全性较低)。

DES 加密与解密流程解析

1. 加密过程(核心代码解析)

步骤 1:初始化随机数生成器
1
SecureRandom sr = new SecureRandom();

SecureRandom用于生成加密过程中所需的随机数,确保加密的随机性(尽管 DES 的安全性主要依赖密钥)。

步骤 2:处理密钥
1
2
3
DESKeySpec dks = new DESKeySpec(key); // 从密钥字节数组创建DES密钥规范
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); // 创建密钥工厂
SecretKey securekey = keyFactory.generateSecret(dks); // 生成符合DES标准的密钥
  • DESKeySpec:验证密钥合法性(必须为 8 字节,对应 56 位有效密钥)。
  • SecretKeyFactory:将原始密钥转换为 DES 算法可识别的SecretKey对象。
步骤 3:初始化加密器
1
2
Cipher cipher = Cipher.getInstance("DES"); // 创建DES密码器
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr); // 初始化为加密模式
  • Cipher.getInstance("DES"):默认使用DES/ECB/PKCS5Padding模式(ECB 模式不推荐,因相同明文分组会生成相同密文)。
  • init方法:传入加密模式、密钥和随机数生成器。
步骤 4:执行加密
1
return cipher.doFinal(src); // 对明文字节数组执行加密,返回密文字节数组

doFinal方法完成实际加密操作,返回加密后的字节数组。

2. 解密过程(核心代码解析)

解密流程与加密类似,仅初始化模式不同:

1
2
3
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, securekey, sr); // 初始化为解密模式
return cipher.doFinal(src); // 对密文字节数组执行解密,返回明文字节数组
  • 需使用与加密相同的密钥,否则无法正确解密。
  • 解密时的SecureRandom参数不影响结果(随机数仅在加密初始化时影响)。

DES 的局限性与替代方案

局限性

  • 密钥长度短:56 位密钥可被现代计算机暴力破解(2^56 种可能,约 7.2×10^16,通过分布式计算可在短时间内破解)。
  • ECB 模式不安全:默认的 ECB 模式不使用初始化向量(IV),相同明文分组加密后密文相同,易被攻击。
  • 分组大小固定:64 位分组在处理长数据时效率较低,且存在安全性隐患。

替代方案

  • 3DES:通过三次 DES 加密提升安全性(使用 3 个 56 位密钥,等效 112 位或 168 位密钥),但效率较低。
  • AES:目前的首选对称加密算法,支持 128/192/256 位密钥,安全性和效率均远超 DES。

完整示例:DES 加密解密工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;

public class DESUtils {
private static final String DES = "DES";

/**
* DES加密
* @param src 明文字节数组
* @param key 密钥(8字节)
* @return 加密后的Base64字符串
*/
public static String encrypt(byte[] src, byte[] key) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
byte[] encrypted = cipher.doFinal(src);
return Base64.getEncoder().encodeToString(encrypted); // 转为Base64便于传输
}

/**
* DES解密
* @param encryptedBase64 加密后的Base64字符串
* @param key 密钥(8字节)
* @return 明文
*/
public static String decrypt(String encryptedBase64, byte[] key) throws Exception {
byte[] src = Base64.getDecoder().decode(encryptedBase64); // 解码Base64
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
byte[] decrypted = cipher.doFinal(src);
return new String(decrypted); // 转为字符串
}

public static void main(String[] args) throws Exception {
String plaintext = "Hello, DES!";
byte[] key = "12345678".getBytes(); // 8字节密钥

// 加密
String encrypted = encrypt(plaintext.getBytes(), key);
System.out.println("加密后:" + encrypted);

// 解密
String decrypted = decrypt(encrypted, key);
System.out.println("解密后:" + decrypted);
}
}

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10