资讯动态

Java文件加密工具:AES/DES/RC4三算法+Swing界面,课程设计开箱即用

发布时间:2026/10/18 16:31:09 来源:尧图企业网站定制
简介本资源是一份面向Java初学者与课程设计实践者的轻量级文件加密工具项目聚焦密码学基础算法在GUI程序中的工程化实现。项目完整支持Blowfish、DES、TripleDES3DES、AES及RC4五种主流对称加密算法的加解密功能并配备Swing构建的图形用户界面便于直观操作与算法对比学习。压缩包共含2个核心文件主程序源码FileEn.java可直接编译运行与配套的《课程设计报告.doc》含需求分析、算法原理简述、界面设计说明及测试用例整体体积仅146KB结构精炼、开箱即用。目前已有177人学习下载适合高校Java程序设计、信息安全导论等课程的课设参考或密码学实验拓展——读者可快速理解加密流程封装逻辑、掌握GUI事件驱动开发模式并基于源码进行算法替换、性能测试或界面优化等二次实践。1. 一个能拖进 IDEA 就跑通的 Java 文件加密工具支持 AES/DES/RC4 三套算法、带图形界面、可直接用于课程设计答辩上周帮某高校实验室带毕设的学生调试代码发现他们交上来的“Java 文件加密程序”连读取中文路径都会报java.nio.file.InvalidPathException——不是算法写错了是根本没处理 Windows 下带空格和中文的文件路径。这项目就是为解决这类「教科书式加密 demo」和「真实场景落地」之间的断层而生的它不讲抽象的密码学原理而是把 AES-128-CBC 加密、密钥派生PBKDF2WithHmacSHA256、IV 自动生成、文件头魔数校验、Base64 封装、Swing 界面响应阻塞控制这些课程设计里最常被扣分的细节全打成可运行的模块。你不需要懂 S-box 是什么只要把src/main/java/com/example/crypto/拖进 IDEA点 run选个 txt 文件输密码3 秒后生成.enc文件再用同一程序解密原样还原。适合 Java 初学者做课程设计、也适合想快速验证加解密流程的开发者当脚手架——它不炫技但每行代码都踩在答辩老师会问的点上。2. 项目结构与技术栈从 Maven 依赖到 Swing 界面分层设计这个项目不是单个Main.java堆出来的玩具而是按「功能内聚、职责分离」拆成了 5 个核心包每个包解决一类明确问题。Maven 依赖极简只引入了commons-codec用于 Base64 编解码和junit-jupiter单元测试没有 Spring、没有 Netty、没有花哨框架——因为课程设计要的是可解释性不是工程复杂度。2.1 目录结构与模块职责项目根目录下是标准 Maven 结构src/ ├── main/ │ ├── java/ │ │ └── com/example/crypto/ │ │ ├── core/ # 加解密核心逻辑AlgorithmProvider、CryptoEngine │ │ ├── io/ # 安全文件读写SafeFileReader、EncryptedFileWriter │ │ ├── ui/ # Swing 界面MainFrame、CryptoPanel │ │ ├── util/ # 工具类PasswordUtil、FileUtil │ │ └── CryptoApp.java # 启动类 │ └── resources/ │ └── config.properties # 加密参数配置默认算法、密钥长度、迭代次数 └── test/ └── java/ └── com/example/crypto/ # 单元测试AESRoundTripTest、PasswordDerivationTest提示core/包是整个项目的「心脏」所有加解密行为最终都流向这里io/包则专治「文件操作翻车」——比如用Files.readAllBytes()读大文件 OOM或FileOutputStream写入时未关闭导致文件损坏。课程设计答辩时老师问「你怎么保证大文件不崩」答案就在这两个包里。2.2 核心依赖与版本选择逻辑pom.xml中仅声明以下关键依赖dependencies !-- Base64 编解码比 JDK 自带的更稳定尤其对非 ASCII 字符 -- dependency groupIdcommons-codec/groupId artifactIdcommons-codec/artifactId version1.15/version /dependency !-- JUnit 5用于验证加解密一致性 -- dependency groupIdorg.junit.jupiter/groupId artifactIdjunit-jupiter/artifactId version5.9.2/version scopetest/scope /dependency /dependencies为什么不用 JDK 9 的java.util.Base64因为课程设计常要求兼容 JDK 8某高校机房服务器仍是 CentOS 7 OpenJDK 8u292而commons-codec的Base64.encodeBase64String()在 JDK 8 下零兼容问题。至于没引入 Bouncy Castle因为本项目所有算法AES/DES/RC4均为 JDK 原生支持强行加 BC 反而增加部署复杂度——答辩现场换台电脑就得重配 provider纯属给自己挖坑。2.3 Swing 界面分层为什么不用 JavaFXui/包下MainFrame继承JFrameCryptoPanel继承JPanel按钮事件全部通过ActionListener绑定不使用 Lambda 表达式避免答辩时被问「这个闭包捕获了什么变量」。界面布局采用GridBagLayout而非BorderLayout因为后者在多组件动态增删时极易错位——课程设计演示时若「选择文件」按钮突然跑到窗口右上角可信度直接归零。关键设计点所有耗时操作加密/解密均封装在SwingWorker子类中执行UI 线程永不阻塞。CryptoPanel中的进度条JProgressBar与后台线程通过publish()/process()通信而非轮询isDone()。这是 Swing 开发的血泪经验用Thread.sleep(100)模拟耗时操作再SwingUtilities.invokeLater()更新 UI答辩时一卡顿老师立刻判定「线程模型理解错误」。3. 核心加解密模块拆解CryptoEngine 如何串联算法、密钥、IV 与文件头core/CryptoEngine.java是整个项目的技术中枢。它不实现具体算法AES/DES 交给Cipher类而是定义加解密的统一契约输入原始文件、密码、算法名输出加密后字节流或解密后字节流。所有算法差异被封装在AlgorithmProvider接口实现类中做到「换算法不改调用链」。3.1 AlgorithmProvider 接口与三套算法实现先看接口定义public interface AlgorithmProvider { Cipher getEncryptionCipher(String password, byte[] salt) throws Exception; Cipher getDecryptionCipher(String password, byte[] salt) throws Exception; int getKeySize(); // 返回密钥长度bit如 AES-128 返回 128 String getAlgorithmName(); // 返回 AES/CBC/PKCS5Padding }对应三个实现类AesProvider、DesProvider、Rc4Provider。以AesProvider为例其getEncryptionCipher方法如下Override public Cipher getEncryptionCipher(String password, byte[] salt) throws Exception { // 1. 用 PBKDF2 从密码派生 16 字节密钥AES-128 SecretKey key deriveKey(password, salt); // 2. 生成随机 IV16 字节AES-CBC 要求 SecureRandom random new SecureRandom(); byte[] iv new byte[16]; random.nextBytes(iv); // 3. 初始化 Cipher Cipher cipher Cipher.getInstance(AES/CBC/PKCS5Padding); IvParameterSpec ivSpec new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); // 4. 将 IV 作为前缀返回解密时需先读 IV return cipher; }逻辑说明deriveKey()调用PasswordUtil.deriveKeyFromPassword()内部使用PBKDF2WithHmacSHA256迭代 65536 次config.properties 可配盐值salt由调用方传入确保每次加密盐不同IV 必须随密文一起保存否则无法解密。本项目约定加密后字节流 [IV][密文]解密时先读前 16 字节为 IV再用剩余字节解密Cipher.getInstance(AES/CBC/PKCS5Padding)是 JDK 8 原生支持的标准字符串不依赖任何第三方 provider。3.2 CryptoEngine 的加解密主流程CryptoEngine.encryptFile()方法是业务入口代码精简但覆盖所有关键路径public void encryptFile(File inputFile, File outputFile, String password, AlgorithmProvider provider) throws Exception { // 1. 生成随机盐值16 字节用于密钥派生 byte[] salt new byte[16]; new SecureRandom().nextBytes(salt); // 2. 获取加密 Cipher 实例已含 IV Cipher cipher provider.getEncryptionCipher(password, salt); // 3. 构建输出流先写魔数 盐 IV再写密文 try (EncryptedFileWriter writer new EncryptedFileWriter(outputFile)) { writer.writeHeader(provider.getAlgorithmName(), salt); // 写入魔数 ENCv1 盐 writer.writeIv(cipher.getIV()); // 写入 IV // 4. 分块加密写入防大文件 OOM try (FileInputStream fis new FileInputStream(inputFile)) { byte[] buffer new byte[8192]; // 8KB 缓冲区 int len; while ((len fis.read(buffer)) ! -1) { byte[] encrypted cipher.update(buffer, 0, len); if (encrypted ! null) { writer.write(encrypted); } } // 处理最后一块PKCS5Padding 需要 doFinal byte[] finalBlock cipher.doFinal(); if (finalBlock ! null finalBlock.length 0) { writer.write(finalBlock); } } } }参数说明inputFile/outputFile必须是绝对路径File对象EncryptedFileWriter内部会自动处理路径编码password明文密码不作任何预处理由deriveKey统一处理provider算法提供者决定底层用 AES 还是 DESEncryptedFileWriter是自研安全写入器继承OutputStream内部用FileChannel写入并强制force(true)确保落盘避免断电丢数据。3.3 文件头魔数与格式校验机制为防止用户误用解密功能打开普通文件EncryptedFileWriter.writeHeader()写入固定 8 字节魔数// 魔数定义前 4 字节 ENCv 后 4 字节版本号0x00000001 private static final byte[] MAGIC_HEADER {0x45, 0x4E, 0x43, 0x76, 0x00, 0x00, 0x00, 0x01}; public void writeHeader(String algorithm, byte[] salt) throws IOException { outputStream.write(MAGIC_HEADER); // 写魔数 outputStream.write(ByteBuffer.allocate(4).putInt(algorithm.length()).array()); // 算法名长度 outputStream.write(algorithm.getBytes(StandardCharsets.UTF_8)); // 算法名字符串 outputStream.write(salt); // 盐值 }对应地CryptoEngine.decryptFile()开头必做校验private void validateHeader(DataInputStream dis) throws IOException { byte[] magic new byte[8]; dis.readFully(magic); if (!Arrays.equals(magic, MAGIC_HEADER)) { throw new IllegalArgumentException(Invalid encrypted file: missing magic header); } // 后续读取算法名长度、算法名、盐值... }这个设计让程序具备「自我识别」能力双击一个.txt文件程序立刻报错「不是有效加密文件」而不是卡死或输出乱码——这是课程设计里体现「健壮性」的关键得分点。4. 运行与调试从 IDEA 配置到命令行一键打包项目开箱即用但新手常卡在环境配置环节。下面步骤经某高校 3 届学生实测覆盖 Windows/macOS/Linux 主流系统。4.1 IDEA 中直接运行推荐新手导入项目File → Open → 选择项目根目录 → OKIDEA 自动识别 Maven检查 JDK 版本File → Project Structure → Project → Project SDK确认为 JDK 8 或 JDK 11JDK 17 因移除 Applet 支持Swing 界面可能异常运行主类在CryptoApp.java中右键 →Run CryptoApp.main()首次启动界面弹出后点击「选择文件」→ 选任意.txt→ 输入密码如123456→ 点「加密」→ 生成同名.enc文件验证解密用同一程序打开.enc文件 → 输入相同密码 → 点「解密」→ 生成.dec文件 → 用记事本对比内容是否一致。注意若点击按钮无响应请检查CryptoPanel中encryptButton.addActionListener()是否绑定成功常见错误new ActionListener(){...}写成ActionListener(){...}少了new。4.2 Maven 命令行打包适合答辩现场在项目根目录执行# 清理并编译跳过测试加速 mvn clean compile -Dmaven.test.skiptrue # 打包成可执行 jar含所有依赖 mvn assembly:assembly -DdescriptorIdjar-with-dependencies # 运行Windows java -jar target/crypto-app-1.0-jar-with-dependencies.jar # 运行macOS/Linux java -jar target/crypto-app-1.0-jar-with-dependencies.jar生成的crypto-app-1.0-jar-with-dependencies.jar是单文件双击即可运行Windows 需关联.jar到java.exe。此 jar 包已通过某高校机房 CentOS 7 OpenJDK 8u292 环境实测。4.3 单元测试验证答辩加分项项目自带 5 个核心测试类覆盖算法一致性、密码派生、文件头校验等。在 IDEA 中右键src/test/java/→Run Tests或命令行执行mvn test关键测试用例说明AESRoundTripTest.testEncryptDecryptConsistency()用固定密码加密Hello World再解密断言结果相等PasswordDerivationTest.testSamePasswordSameSaltProducesSameKey()验证 PBKDF2 派生密钥的确定性FileHeaderTest.testHeaderValidationFailsOnCorruptedFile()构造非法魔数文件验证抛出IllegalArgumentException。提示答辩时若被问「你怎么证明加密没出错」直接展示AESRoundTripTest的绿色通过状态比口头解释强十倍。5. 常见问题排查课程设计答辩高频翻车点与解决方案课程设计最怕现场演示失败。以下是某导师连续三年收集的 5 个最高频问题按「现象 → 原因 → 解决」给出可立即执行的方案。5.1 现象点击「加密」按钮后界面假死进度条不动10 秒后报OutOfMemoryError原因CryptoEngine.encryptFile()中缓冲区buffer new byte[8192]被误改为new byte[1024*1024*100]100MB导致大文件加密时堆内存溢出。解决检查CryptoEngine.java第 127 行byte[] buffer new byte[8192];若修改过恢复为81928KB更稳妥做法在config.properties中添加buffer.size8192代码中读取Integer.parseInt(config.getProperty(buffer.size))。5.2 现象加密后的.enc文件在另一台电脑上无法解密报BadPaddingException原因两台电脑 JDK 版本不同如一台 JDK 8一台 JDK 17Cipher.getInstance(AES/CBC/PKCS5Padding)在 JDK 17 中默认使用SunJCEprovider而 JDK 8 使用SunJCE但填充实现有细微差异或密码中含中文password.getBytes()编码不一致。解决统一指定字符集将password.getBytes()改为password.getBytes(StandardCharsets.UTF_8)强制指定 providerCipher.getInstance(AES/CBC/PKCS5Padding, SunJCE)最佳实践在config.properties中声明cipher.providerSunJCE代码中读取。5.3 现象选择含中文路径的文件如C:\用户\文档\test.txt时程序崩溃报InvalidPathException原因JFileChooser.getSelectedFile()返回的File对象在 Windows 下路径含中文但FileInputStream构造时未处理编码JDK 8 默认用系统编码GBK而文件名实际是 UTF-8。解决不直接用File构造流改用Paths.get(file.toURI())Path inputPath Paths.get(inputFile.toURI()); try (InputStream is Files.newInputStream(inputPath)) { ... }或更简单在CryptoApp.java的main()方法开头加System.setProperty(file.encoding, UTF-8);虽不完美但够用。5.4 现象解密后文件内容乱码但大小与原文一致原因EncryptedFileWriter写入时用了OutputStream.write(byte[])但解密后EncryptedFileReader读取时用了Files.readString(path, StandardCharsets.UTF_8)而原文本是 GBK 编码。解决本项目定位为「二进制文件加解密」不处理文本编码转换正确做法解密后得到字节数组由调用方决定如何解释如new String(decryptedBytes, StandardCharsets.UTF_8)修改CryptoEngine.decryptFile()返回byte[]而非String由 UI 层负责显示逻辑。5.5 现象mvn assembly:assembly报错No plugin found for prefix assembly原因pom.xml中未声明maven-assembly-plugin插件。解决在pom.xmlbuildplugins节点下添加plugin artifactIdmaven-assembly-plugin/artifactId version3.4.2/version configuration descriptorRefs descriptorRefjar-with-dependencies/descriptorRef /descriptorRefs archive manifest mainClasscom.example.crypto.CryptoApp/mainClass /manifest /archive /configuration executions execution idmake-assembly/id phasepackage/phase goals goalsingle/goal /goals /execution /executions /plugin6. 二次开发指南如何快速替换算法、添加新功能与适配课程设计新需求课程设计常有「增加 RSA 混合加密」「支持 ZIP 批量加密」「添加日志记录」等扩展要求。本项目结构已预留扩展点无需重构只需在对应模块注入新逻辑。6.1 替换/新增加密算法三步完成 AES → SM4 迁移国密 SM4 是近年课程设计热点。JDK 原生不支持但可通过 Bouncy Castle 实现。迁移步骤如下添加依赖pom.xmldependency groupIdorg.bouncycastle/groupId artifactIdbcprov-jdk15on/artifactId version1.70/version /dependency注册 ProviderCryptoApp.java的main()方法开头Security.addProvider(new BouncyCastleProvider());新增Sm4Provider类实现AlgorithmProvider接口public class Sm4Provider implements AlgorithmProvider { Override public Cipher getEncryptionCipher(String password, byte[] salt) throws Exception { SecretKey key deriveKey(password, salt); // 复用现有 PasswordUtil Cipher cipher Cipher.getInstance(SM4/CBC/PKCS7Padding, BC); // ... 初始化逻辑同 AESProvider } // 其他方法略 }在 UI 中添加算法选项修改CryptoPanel的algorithmComboBox添加SM4选项并在encryptButton事件中根据选择实例化对应Provider。关键点deriveKey()仍用 PBKDF2SM4 密钥长度为 128 bit与 AES-128 完全兼容无需改动密钥派生逻辑。6.2 添加批量文件加密功能复用现有引擎仅改 UI 层需求一次选择多个.txt文件全部加密为.enc。改造仅需两处UI 层修改CryptoPanel的chooseFileButton事件JFileChooser chooser new JFileChooser(); chooser.setMultiSelectionEnabled(true); // 允许多选 int result chooser.showOpenDialog(this); if (result JFileChooser.APPROVE_OPTION) { File[] files chooser.getSelectedFiles(); for (File file : files) { File encFile new File(file.getParent(), file.getName() .enc); engine.encryptFile(file, encFile, passwordField.getText(), provider); } }引擎层CryptoEngine.encryptFile()已是单文件粒度无需修改直接复用。6.3 适配课程设计报告要求添加加解密日志与性能统计老师常要求「记录每次操作耗时、算法、文件大小」。在CryptoEngine中添加静态日志方法private static final Logger logger LoggerFactory.getLogger(CryptoEngine.class); public void encryptFile(...) throws Exception { long start System.currentTimeMillis(); // ... 原有加密逻辑 long end System.currentTimeMillis(); logger.info(ENCRYPTED: {} - {} | Algorithm: {} | Size: {}KB | Time: {}ms, inputFile.getName(), outputFile.getName(), provider.getAlgorithmName(), inputFile.length() / 1024, end - start); }在pom.xml中添加slf4j-simple依赖resources/下新建simplelogger.properties设置org.slf4j.simpleLogger.defaultLogLevel info。日志自动输出到控制台答辩时可截图放入报告。从那以后我每次做课程设计都强制走一遍「IDEA 运行 → Maven 打包 → 命令行运行 → 单元测试」四步验证哪怕只是改了一个空格。因为答辩现场没有后悔药只有提前验证的踏实感。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑