在Java开发中,DES加密解密是常见的对称加密应用,但处理不当时常出现乱码问题,影响数据传输和存储的准确性,乱码的产生通常涉及字符编码、密钥处理、数据填充等多个环节,本文将结合具体场景分析乱码原因,并提供系统的解决方案。

DES加密解密的基本流程与乱码根源
DES(Data Encryption Standard)是一种对称加密算法,其核心是通过密钥对64位数据块进行加密和解密,在Java中,通常使用javax.crypto.Cipher类实现加密解密流程:初始化Cipher对象、设置加密/解密模式、执行doFinal()方法处理数据,乱码问题的根源主要在于数据转换过程中的编码不一致、密钥处理不规范以及填充模式匹配错误,加密时将字符串转为字节数组使用了UTF-8编码,而解密时却用GBK解码,必然导致乱码;或未正确处理DES对8字节整数倍长度的要求,未填充或填充错误也会破坏数据结构。
字符编码问题:统一编码格式解决乱码
字符编码不一致是乱码最常见的原因,Java中字符串与字节数组的转换需明确指定编码格式,加密前需将明文字符串按特定编码(如UTF-8)转为字节数组,解密后必须用相同编码将字节数组转回字符串,若加密用UTF-8而解密用默认编码(可能因环境不同而变化),就会出现乱码。
解决方案:
- 加密前:使用
String.getBytes("UTF-8")将明文字符串转为字节数组; - 解密后:使用
new String(byte[], "UTF-8")将解密后的字节数组转回字符串。
示例代码:
// 加密
String plaintext = "Hello, DES加密";
byte[] plaintextBytes = plaintext.getBytes("UTF-8"); // 统一使用UTF-8编码
byte[] encryptedBytes = cipher.doFinal(plaintextBytes);
// 解密
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
String decryptedText = new String(decryptedBytes, "UTF-8"); // 必须与加密时编码一致
注意事项:需确保加密与解密两端使用完全相同的编码格式,推荐优先使用UTF-8,避免因环境差异导致编码解析错误。
密钥处理:规范密钥生成与存储
DES算法要求密钥长度为64位(8字节),但实际有效密钥为56位(每8位中的第1位用作奇偶校验),密钥处理不当是乱码的另一主因,常见问题包括密钥长度不足/超出、密钥字符串编码错误等。

解决方案:
- 密钥长度校准:若密钥为字符串,需确保其转换为字节数组后长度为8字节,不足时可通过补零(如
"123456"补为"123456\0\0")或截断(如"1234567890"截取前8字节)处理; - 密钥编码规范:生成
SecretKey对象时,密钥字节数组应使用固定编码(如UTF-8或ISO-8859-1)转换,避免隐式编码差异; - 密钥对象生成:使用
SecretKeySpec类将处理后的字节数组转换为密钥对象,确保算法名为”DES”。
示例代码:
String keyStr = "12345678"; // 密钥字符串需为8字节
byte[] keyBytes = keyStr.getBytes("UTF-8"); // 固定编码转字节数组
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "DES"); // 指定DES算法
注意事项:密钥应避免硬编码在代码中,建议通过配置文件或密钥管理服务存储,同时定期更换密钥以增强安全性。
数据填充:正确设置填充模式
DES算法要求数据长度为8字节的整数倍,若明文长度不足,需进行填充;解密后需移除填充数据,Java中Cipher的填充模式(Padding)需与加密解密逻辑匹配,常见填充模式包括PKCS5Padding和NoPadding。
解决方案:
- 优先使用PKCS5Padding:该模式会自动填充数据至8字节倍数(填充值填充字节数,如填充3字节则值为0x03),解密时自动移除填充,简化处理逻辑;
- 避免NoPadding的误用:若使用
NoPadding,需手动处理数据填充(如明文末尾补充0x00至8字节倍数),否则加密会抛出IllegalBlockSizeException,解密后也可能因填充缺失导致乱码。
示例代码(PKCS5Padding):

// 初始化Cipher时指定填充模式
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); // ECB模式+PKCS5填充
注意事项:加密与解密必须使用相同的填充模式和加密模式(如ECB、CBC),避免因模式不匹配导致数据解析错误。
完整代码示例与关键设置点
以下为完整的DES加密解密示例,涵盖编码统一、密钥处理、填充模式等关键设置:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class DESUtil {
private static final String ALGORITHM = "DES";
private static final String TRANSFORMATION = "DES/ECB/PKCS5Padding"; // 加密模式+填充
// 加密
public static String encrypt(String plaintext, String keyStr) throws Exception {
// 1. 密钥处理:8字节长度,UTF-8编码
byte[] keyBytes = keyStr.getBytes(StandardCharsets.UTF_8);
SecretKey secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
// 2. 初始化Cipher(加密模式)
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
// 3. 字符串转字节数组(UTF-8编码),加密
byte[] plaintextBytes = plaintext.getBytes(StandardCharsets.UTF_8);
byte[] encryptedBytes = cipher.doFinal(plaintextBytes);
// 4. Base64编码(避免二进制数据传输问题)
return java.util.Base64.getEncoder().encodeToString(encryptedBytes);
}
// 解密
public static String decrypt(String encryptedText, String keyStr) throws Exception {
// 1. 密钥处理(与加密一致)
byte[] keyBytes = keyStr.getBytes(StandardCharsets.UTF_8);
SecretKey secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
// 2. 初始化Cipher(解密模式)
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
// 3. Base64解码,解密
byte[] encryptedBytes = java.util.Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
// 4. 字节数组转字符串(UTF-8编码)
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
public static void main(String[] args) throws Exception {
String key = "12345678"; // 8字节密钥
String plaintext = "Java DES加密解密测试";
// 加密
String encryptedText = encrypt(plaintext, key);
System.out.println("加密结果: " + encryptedText);
// 解密
String decryptedText = decrypt(encryptedText, key);
System.out.println("解密结果: " + decryptedText); // 输出与明文一致
}
}
关键设置点:
- 编码统一:字符串与字节数组转换、密钥处理均使用
StandardCharsets.UTF_8; - 填充模式:
PKCS5Padding自动处理填充,无需手动干预; - 数据传输:加密后通过Base64编码,避免二进制数据在文本场景中损坏。
最佳实践与注意事项
为彻底避免DES加密解密后的乱码问题,需遵循以下最佳实践:
- 编码规范:全程使用UTF-8编码,避免依赖平台默认编码;
- 密钥管理:密钥长度严格保持8字节,通过安全渠道存储,避免硬编码;
- 填充与模式:优先使用
PKCS5Padding和ECB模式(若需更高安全性,可使用CBC模式并配置IV向量); - 异常处理:捕获
NoSuchAlgorithmException、InvalidKeyException等异常,避免程序因加密问题崩溃; - 测试验证:加密解密后务必验证数据完整性,确保明文与解密结果一致。
通过规范编码处理、密钥管理和填充模式设置,可有效解决DES加密解密后的乱码问题,保障数据的安全性和准确性。













