游乐游手机版
首页/网络安全/文章详情

Java实现DES加密解密:修复代码缺陷与最佳实践

时间:2026-08-31 11:51
本文详细解析Java中使用DES算法加密字符数据的实现方法。重点修复了原代码中字节转字符串导致的乱码问题,通过引入Base64编码确保数据完整性。同时优化了资源关闭逻辑,防止内存泄漏,并提供完整的加密解密工具类代码及运行示例。

本文详细解析Java中使用DES算法加密字符数据的实现方法。重点修复了原代码中字节转字符串导致的乱码问题,通过引入Base64编码确保数据完整性。同时优化了资源关闭逻辑,防止内存泄漏,并提供完整的加密解密工具类代码及运行示例。

DES加密最终效果预览

在Java中实现DES加密后,原始明文字符串将被转换为不可读的密文字符串(通常经过Base64编码)。解密过程则能将密文还原为原始明文。下图展示了加密前后的数据形态对比,以及解密成功的控制台输出结果。

Java DES加密解密控制台输出截图,显示原始明文、Base64编码后的密文以及解密还原后的明文一致
图1:DES加密解密控制台输出示例,展示明文、密文(Base64)与解密结果的对应关系

操作前准备说明

在开始编写代码之前,请确保开发环境满足以下条件:

  • JDK版本:建议使用 JDK 8 或更高版本,以确保包含完整的 javax.crypto 包支持。
  • 依赖库:Java标准库已内置 javax.crypto.Cipherjavax.crypto.spec 相关类,无需额外引入第三方JAR包。
  • 编码工具:需使用 java.util.Base64 类(JDK 8+)或 org.apache.commons.codec.binary.Base64 来处理二进制数据到字符串的转换。
  • 密钥准备:DES算法要求密钥长度必须为8字节(64位,其中8位用于奇偶校验)。请确保密钥字符串长度符合此要求,否则需进行截断或填充处理。

DES加密解密核心实现步骤

第1步:定义密钥与初始化参数

DES加密需要明确的密钥(Key)和初始化向量(IV)。为了保证安全性,建议使用 SecureRandom 生成随机数,并固定密钥和IV字符串。

操作目的:确立加密所需的密钥材料,确保加密和解密使用相同的参数。

  1. 定义静态常量 PASSKEY 作为IV(初始化向量),长度需为8字节。
  2. 定义静态常量 DESKEY 作为主密钥,长度需为8字节。
  3. 使用 DESKeySpec 将密钥字符串转换为字节数组。
  4. 通过 SecretKeyFactory.getInstance("DES") 生成 SecretKey 对象。

第2步:配置Cipher实例与模式

操作目的:指定加密算法、工作模式和填充方式,并初始化为加密或解密模式。

  1. 创建 IvParameterSpec 对象,传入IV的字节数组。
  2. 使用 Cipher.getInstance("DES/CBC/PKCS5Padding") 获取Cipher实例。这里采用CBC模式(密码块链接)和PKCS5Padding填充,以增强安全性。
  3. 调用 cipher.init(mode, securekey, iv, sr),其中 modeCipher.ENCRYPT_MODECipher.DECRYPT_MODE

第3步:执行数据流加密与Base64编码

操作目的:将明文转换为密文,并安全地转换为字符串格式,避免乱码。

关键修复点:原代码直接使用 out.toString() 将字节数组转换为字符串,这会导致编码错误和乱码。正确做法是将加密后的字节数组进行 Base64编码

  1. 使用 CipherInputStream 包装输入流,自动执行加密操作。
  2. 使用 ByteArrayOutputStream 接收加密后的字节数据。
  3. 读取加密流中的数据块(Buffer),写入输出流。
  4. 加密完成后,使用 Base64.getEncoder().encodeToString(out.toByteArray()) 将字节数组转换为Base64字符串,作为最终密文返回。

第4步:执行数据流解密与还原

操作目的:将Base64密文解码为字节数组,并解密还原为原始明文。

  1. 使用 Base64.getDecoder().decode(src) 将密文字符串还原为字节数组。
  2. 使用 CipherInputStream 包装解密流,自动执行解密操作。
  3. 将解密后的字节数组转换为字符串(使用UTF-8编码)。
  4. 返回解密后的明文。

优化后的完整代码实现

以下是修复了资源泄漏、乱码问题并优化了结构后的完整工具类代码:

import javax.crypto.Cipher;import javax.crypto.CipherInputStream;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import javax.crypto.spec.IvParameterSpec;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.security.SecureRandom;import java.util.Base64;public class DesTool {    // 密钥:必须为8字节    private static final String DESKEY = "12345678";    // IV:必须为8字节    private static final String PASSKEY = "abcdefgh";    /**     * 加密或解密方法     * @param src 源数据(加密时为明文,解密时为Base64密文)     * @param mode 模式:Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE     * @return 加密后的Base64字符串,或解密后的明文     */    public static String encoderOrdecoder(String src, int mode) {        String result = "";        InputStream is = null;        CipherInputStream cis = null;        ByteArrayOutputStream out = null;        try {            // 1. 生成密钥            SecureRandom sr = new SecureRandom();            DESKeySpec dks = new DESKeySpec(DESKEY.getBytes("UTF-8"));            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");            SecretKey securekey = keyFactory.generateSecret(dks);            // 2. 生成IV            IvParameterSpec iv = new IvParameterSpec(PASSKEY.getBytes("UTF-8"));            // 3. 初始化Cipher            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");            cipher.init(mode, securekey, iv, sr);            // 4. 处理输入数据            byte[] inputBytes;            if (mode == Cipher.DECRYPT_MODE) {                // 解密时需先进行Base64解码                inputBytes = Base64.getDecoder().decode(src);            } else {                // 加密时直接使用明文                inputBytes = src.getBytes("UTF-8");            }            // 5. 执行加密/解密流操作            cis = new CipherInputStream(new java.io.ByteArrayInputStream(inputBytes), cipher);            out = new ByteArrayOutputStream();            byte[] buffer = new byte[1024];            int r;            while ((r = cis.read(buffer)) > 0) {                out.write(buffer, 0, r);            }            // 6. 结果处理            if (mode == Cipher.ENCRYPT_MODE) {                // 加密结果转为Base64字符串                result = Base64.getEncoder().encodeToString(out.toByteArray());            } else {                // 解密结果转为UTF-8字符串                result = new String(out.toByteArray(), "UTF-8");            }        } catch (Exception e) {            e.printStackTrace();        } finally {            // 7. 安全关闭资源            try {                if (cis != null) cis.close();                if (out != null) out.close();            } catch (Exception e1) {                // 忽略关闭异常            }        }        return result;    }    public static void main(String[] args) {        String originalText = "Hello, DES Encryption!";        System.out.println("原始明文: " + originalText);        // 加密        String encryptedText = encoderOrdecoder(originalText, Cipher.ENCRYPT_MODE);        System.out.println("加密后(Base64): " + encryptedText);        // 解密        String decryptedText = encoderOrdecoder(encryptedText, Cipher.DECRYPT_MODE);        System.out.println("解密后: " + decryptedText);        // 验证        System.out.println("解密是否成功: " + originalText.equals(decryptedText));    }}

图片验证与结果核对

运行上述代码后,控制台应输出类似图1所示的内容。请核对以下关键点:

  • 原始明文:显示您输入的字符串。
  • 加密后(Base64):显示一串由字母、数字和符号组成的长字符串,这是Base64编码后的密文。
  • 解密后:显示与原始明文完全一致的字符串。
  • 解密是否成功:输出 true,表示加密解密流程无误。

如果输出中出现乱码或异常,请检查密钥长度是否为8字节,以及是否使用了正确的Base64编码/解码方法。

问题与调整

问题1:解密时出现“Bad padding”异常

  • 表现:抛出 javax.crypto.BadPaddingException
  • 原因:密文在传输或存储过程中被修改,或者Base64解码失败(例如密文包含空格或换行符)。
  • 解决方法:确保密文在传输前已去除首尾空格,且Base64编码/解码过程一致。

问题2:密钥长度不匹配

  • 表现:抛出 java.security.InvalidKeyException: Key length not 8 bytes
  • 原因:DES算法严格要求密钥长度为8字节(64位)。
  • 解决方法:确保 DESKEY 字符串长度为8个字符。如果密钥更长,需截取前8字节;如果更短,需进行填充(不推荐,安全性降低)。

问题3:中文乱码

  • 表现:解密后的中文显示为问号或乱码。
  • 原因:编码格式不一致,加密时使用UTF-8,解密时使用了ISO-8859-1等默认编码。
  • 解决方法:在 getBytes("UTF-8")new String(..., "UTF-8") 中统一指定编码格式为 UTF-8

总结

本文通过修复原代码中的关键缺陷,提供了一个健壮、安全的Java DES加密解密工具类。核心改进包括:

  • 使用 Base64编码 解决二进制数据转字符串的乱码问题。
  • 优化 资源关闭逻辑,避免内存泄漏。
  • 明确指定 UTF-8编码,确保中文等多字节字符的正确处理。
  • 强调 密钥长度 必须为8字节,符合DES算法规范。

该实现适用于对安全性要求不高、数据量较小的内部系统加密场景。对于高安全性需求,建议升级至AES算法。

以上就是Java实现DES加密解密:修复代码缺陷与最佳实践的详细内容,更多关于Java加密技术的资料请关注本站其它相关文章!

来源:https://www.yisu.com/ask/3556.html
上一篇C语言实现简单数据加密:代码修正与原理详解 下一篇HTTPS解密发生在哪一层?深入解析OSI模型与TLS协议
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
DDoS攻击的三大主要形式:原理、特征与防御重点
网络安全 · 2026-08-31

DDoS攻击的三大主要形式:原理、特征与防御重点

DDoS攻击主要分为基于流量(Volume)、基于应用层(Application)和基于协议(Protocol)三种形式。流量型攻击通过海量数据淹没带宽;应用层攻击利用Web漏洞耗尽服务器资源;协议层攻击则利用TCP握手缺陷导致系统挂起。了解这些原理是制定针对性防御策略的基础。

如何有效预防和缓解DDoS攻击:5大核心策略详解
网络安全 · 2026-08-31

如何有效预防和缓解DDoS攻击:5大核心策略详解

面对DDoS攻击,单纯增加带宽已非长久之计。本文详解5大核心防护策略:优化网络硬件配置、建立DNS冗余机制、部署透明缓解技术、引入负载平衡器及专用Anti-DDoS模块。通过合理组合这些技术手段,可有效抵御SYN泛洪、Slowloris等常见攻击,保障业务连续性与网站可用性。

DDoS防护四大误区:CDN、防火墙与黑名单的局限性解析
网络安全 · 2026-08-31

DDoS防护四大误区:CDN、防火墙与黑名单的局限性解析

许多企业误以为CDN、防火墙或黑名单能完全抵御DDoS攻击。本文深入解析四大常见误区:CDN仅提供部分缓解、静态黑名单易失效、防火墙算力有限且可能成为目标、阈值警报仅具滞后性。了解这些局限性,有助于构建更立体的防御体系,避免在攻击发生时措手不及。

常见DDoS攻击类型详解:原理、特征与防御策略
网络安全 · 2026-08-31

常见DDoS攻击类型详解:原理、特征与防御策略

本文详细解析四种常见DDoS攻击类型:SYN Flood利用TCP三次握手缺陷耗尽资源;UDP Flood通过海量数据包造成带宽拥塞;ICMP Flood利用Ping请求消耗系统算力;应用层Flood针对Web脚本进行高频请求。了解其原理是制定有效防御策略的基础。

如何有效抵御DDOS攻击:4种核心防护方案解析
网络安全 · 2026-08-31

如何有效抵御DDOS攻击:4种核心防护方案解析

面对DDOS攻击,企业需构建多层防护体系。本文详解四大核心策略:利用反向路由器查询进行流量清洗,通过GCDN智能分配节点隐藏源站IP,部署负载均衡硬件分担压力,以及接入高防机房抵御数百G恶意流量。掌握这些技术,可最大程度保障业务连续性。