核心要点
- DES 算法:这是一种对称加密算法,加密和解密使用相同的密钥。
- 工作模式:DES 通常与某种“工作模式”一起使用,最常见的是 ECB (Electronic Codebook) 和 CBC (Cipher Block Chaining)。强烈推荐使用 CBC 模式,因为它比 ECB 更安全,本示例将重点展示 CBC 模式。
- 填充方式:DES 要求数据长度是 8 字节的整数倍,如果原始数据不是,就需要进行填充,最常用的填充方式是 PKCS5Padding 或 PKCS7Padding(两者在 DES 中效果相同)。
- IV (Initialization Vector - 初始化向量):在使用 CBC 模式时,需要一个初始化向量,IV 不需要保密,但它必须是随机的,并且与密钥一同使用,以确保即使对相同的数据加密多次,结果也不同。
- 编码格式:加密后的结果是二进制数据(字节数组),不能直接作为文本传输,必须将其转换为一种文本编码格式,最常用的是 Base64,前端和后端都需要使用相同的 Base64 编码/解码库。
第一步:前端 JavaScript 加密
我们将使用 crypto-js 这个流行的库,因为它提供了与 Java 标准库兼容的默认选项。

引入 Crypto-JS
在你的 HTML 文件中,通过 CDN 引入:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">JS DES 加密示例</title>
<!-- 引入 crypto-js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>
<body>
<h1>前端 DES 加密</h1>
<script>
// --- 你的配置 ---
const secretKey = "12345678"; // DES 密钥,必须是8字节
const iv = "87654321"; // 初始化向量,必须是8字节
const plaintext = "这是一段需要加密的敏感信息,Hello, World!";
// --- 加密过程 ---
console.log("原始明文:", plaintext);
// 1. 创建加密器配置对象
// Crypto-js 的 DES 默认使用 ECB 模式和 PKCS7 填充。
// 为了匹配 Java 的 CBC 模式,我们需要明确指定。
const key = CryptoJS.enc.Utf8.parse(secretKey);
const iv_wordArray = CryptoJS.enc.Utf8.parse(iv);
// 2. 执行加密
const encrypted = CryptoJS.DES.encrypt(plaintext, key, {
iv: iv_wordArray,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 3. 将结果转换为 Base64 字符串
const encryptedBase64 = encrypted.toString();
console.log("加密后的 Base64:", encryptedBase64);
// --- 解密过程 (用于验证) ---
const decrypted = CryptoJS.DES.decrypt(encryptedBase64, key, {
iv: iv_wordArray,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
const originalText = decrypted.toString(CryptoJS.enc.Utf8);
console.log("解密后的明文:", originalText);
</script>
</body>
</html>
代码解释:
secretKey和iv:必须都是 8个字符,在真实项目中,密钥应该通过安全的方式传递,而不是硬编码。CryptoJS.enc.Utf8.parse():将字符串(UTF-8 编码)转换为CryptoJS库内部使用的 WordArray 对象。CryptoJS.DES.encrypt():核心加密函数。- 第一个参数:要加密的明文。
- 第二个参数:密钥 WordArray。
- 第三个参数:配置对象,关键点:
iv: 初始化向量。mode: 设置为CryptoJS.mode.CBC。padding: 设置为CryptoJS.pad.Pkcs7。
encrypted.toString():将加密结果(一个 CipherParams 对象)转换为 Base64 字符串,方便网络传输。
第二步:后端 Java 解密
我们将使用 Java 标准库 javax.crypto 来实现解密,这与 crypto-js 的默认设置完美兼容。
Java 解密代码
创建一个 Java 类,DesDecryptor.java。

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class DesDecryptor {
// --- 你的配置 (必须与 JS 端完全一致) ---
private static final String SECRET_KEY = "12345678"; // DES 密钥,必须是8字节
private static final String INIT_VECTOR = "87654321"; // 初始化向量,必须是8字节
public static void main(String[] args) {
// 从前端获取到的加密后的 Base64 字符串
// 你可以把 JS 控制台打印的值复制到这里
String encryptedBase64FromJs = "Q1x8mJ3z4yK5uP6v+8wA7bC9dD0eF1gH2iJ3kL4mN5oP6qR7sT8uV9wX0yZ1aB2cD3eF4gH5iJ6kL7mN8oP9qR0sT1uV2wX3yZ4aB5cD6eF7gH8iJ9kL0mN1oP2qR3sT4uV5wX6yZ7aB8cD9eF0gH1iJ2kL3mN4oP5qR6sT7uV8wX9yZ0aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4cD5eF6gH7iJ8kL9mN0oP1qR2sT3uV4wX5yZ6aB7cD8eF9gH0iJ1kL2mN3oP4qR5sT6uV7wX8yZ9aB0cD1eF2gH3iJ4kL5mN6oP7qR8sT9uV0wX1yZ2aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX4yZ5aB6cD7eF8gH9iJ0kL1mN2oP3qR4sT5uV6wX7yZ8aB9cD0eF1gH2iJ3kL4mN5oP6qR7sT8uV9wX0yZ1";
try {
String decryptedText = decrypt(encryptedBase64FromJs);
System.out.println("解密成功!");
System.out.println("解密后的明文: " + decryptedText);
} catch (Exception e) {
System.err.println("解密失败: " + e.getMessage());
e.printStackTrace();
}
}
public static String decrypt(String encryptedBase64) throws Exception {
// 1. 创建密钥规范和 IV 规范
// SecretKeySpec 用于指定密钥
IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes(StandardCharsets.UTF_8));
SecretKeySpec skeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "DES");
// 2. 创建 Cipher 实例
// "DES/CBC/PKCS5Padding" 是关键,必须与 JS 端的配置完全对应
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
// 3. 初始化 Cipher 为解密模式
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
// 4. 解码 Base64 字符串为字节数组
byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64);
// 5. 执行解密
byte[] originalBytes = cipher.doFinal(encryptedBytes);
// 6. 将解密后的字节数组转换为 UTF-8 字符串
return new String(originalBytes, StandardCharsets.UTF_8);
}
}
代码解释:
- 配置:
SECRET_KEY和INIT_VECTOR必须和 JavaScript 中的完全一样。 new IvParameterSpec(...)和new SecretKeySpec(...):将字符串转换为 Java 加密库所需的规范对象。Cipher.getInstance("DES/CBC/PKCS5Padding"):这是最关键的一步。DES: 指定算法。CBC: 指定工作模式,必须与 JS 端的CryptoJS.mode.CBC对应。PKCS5Padding: 指定填充方式,必须与 JS 端的CryptoJS.pad.Pkcs7对应。
cipher.init(Cipher.DECRYPT_MODE, ...):初始化Cipher对象,设置为解密模式。Base64.getDecoder().decode(...):将前端传来的 Base64 字符串解码回原始的字节数组。cipher.doFinal(...):执行实际的解密操作。new String(..., StandardCharsets.UTF_8):将解密后的字节数组转换回可读的字符串。
运行与验证
- 运行前端:将 HTML 文件在浏览器中打开,打开开发者工具的控制台,你会看到类似下面的输出:
原始明文: 这是一段需要加密的敏感信息,Hello, World! 加密后的 Base64: Q1x8mJ3z4yK5uP6v+8wA7bC9dD0eF1gH2iJ3kL4mN5oP6qR7sT8uV9wX0yZ1aB2cD3eF4gH5iJ6kL7mN8oP9qR0sT1uV2wX3yZ4aB5cD6eF7gH8iJ9kL0mN1oP2qR3sT4uV5wX6yZ7aB8cD9eF0gH1iJ2kL3mN4oP5qR6sT7uV8wX9yZ0aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4cD5eF6gH7iJ8kL9mN0oP1qR2sT3uV4wX5yZ6aB7cD8eF9gH0iJ1kL2mN3oP4qR5sT6uV7wX8yZ9aB0cD1eF2gH3iJ4kL5mN6oP7qR8sT9uV0wX1yZ2aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX4yZ5aB6cD7eF8gH9iJ0kL1mN2oP3qR4sT5uV6wX7yZ8aB9cD0eF1gH2iJ3kL4mN5oP6qR7sT8uV9wX0yZ1 解密后的明文: 这是一段需要加密的敏感信息,Hello, World! - 复制 Base64:复制
加密后的 Base64字符串。 - 运行后端:将复制的 Base64 字符串粘贴到 Java 代码的
encryptedBase64FromJs变量中,然后运行main方法。 - 检查结果:控制台应该会输出:
解密成功! 解密后的明文: 这是一段需要加密的敏感信息,Hello, World!
如果前后端输出的明文完全一致,那么恭喜你,你已经成功实现了 JS DES 加密和 Java 解密!
安全性提醒
- DES 已不安全:DES 算法的密钥长度只有 56 位,在现代计算能力下非常容易被暴力破解。在生产环境中,强烈建议使用更安全的算法,如 AES (Advanced Encryption Standard)。
- 密钥管理:示例中的密钥是硬编码的,这是非常危险的做法,在实际应用中,密钥应该通过安全的渠道(如密钥管理服务 KMS)进行分发和管理,并且不应该在代码或前端中暴露。

