讲师中心 微信公众号
AI工具推荐 视频效率加速

Java初学者项目实战:构建一个基础的文件加密工具

老墨君_8378

老墨君_8378

发布时间:2026-01-07 15:38:02

|

689人浏览过

|

来源于php中文网

原创

Java中AES加密需用SecretKeySpec包装16/24/32字节密钥,推荐SHA-256哈希后截取;大文件须流式处理,IV必须精确读写前16字节;密码应通过System.console().readPassword()获取,避免硬编码。

java初学者项目实战:构建一个基础的文件加密工具

Java中用Cipher实现AES加密时,密钥长度必须是128/192/256位

很多初学者直接用 "mySecretKey" 这样的字符串当密钥,结果抛出 InvalidKeyException: Illegal key size。这不是代码写错了,而是JDK默认限制了AES密钥长度(尤其旧版JDK 8u161之前)。

  • 正确做法是用 SecretKeySpec 包装字节数组,且长度必须为16(128位)、24(192位)或32(256位)字节
  • 推荐用 MessageDigest 对原始口令做SHA-256哈希再取前16/32字节,比硬编码更安全
  • 如果坚持用短口令,必须补位(如PKCS5Padding方式),但别自己手写补位逻辑——容易出错
String password = "hello123";
byte[] key = MessageDigest.getInstance("SHA-256").digest(password.getBytes("UTF-8"));
key = Arrays.copyOf(key, 32); // 取前32字节作为AES-256密钥
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");

FileInputStream读取大文件时不能一次性load到内存

用 Files.readAllBytes() 加密一个200MB的PDF?程序直接OOM。真实工具必须流式处理,否则连“基础”都谈不上。

  • 用 CipherInputStream + FileInputStream 套接,边读边加密,内存占用恒定在几KB
  • 注意:Cipher 必须初始化为 Cipher.ENCRYPT_MODE,且使用带IV的模式(如 AES/CBC/PKCS5Padding)
  • IV必须随密文一起保存(通常写在加密文件开头),否则解密失败——这是新手最常漏的一步
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
try (FileInputStream fis = new FileInputStream(inputFile);
     CipherInputStream cis = new CipherInputStream(fis, cipher);
     FileOutputStream fos = new FileOutputStream(outputFile)) {
    // IV需单独写入输出流开头
    fos.write(cipher.getIV());
    byte[] buffer = new byte[8192];
    int len;
    while ((len = cis.read(buffer)) != -1) {
        fos.write(buffer, 0, len);
    }
}

解密时读不到IV或IV错位,导致javax.crypto.BadPaddingException

错误现象:加密成功,但解密时报 BadPaddingException: Given final block not properly padded。大概率不是密码错,而是IV没对齐。

Audio Upload Aioz Stream Free
Audio Upload Aioz Stream Free

基于 AIOZ Stream API 的免费音频上传技能,通过三步流程(Create → Upload Part → Complete)将本地音频文件上传至 AIOZ 流媒体平台。支持默认快速上传方式,使用默认编码配置,上传完成后返回 HLS 流媒体播放链接。使用 API Key (stream-publ...)进行认证。

下载
  • 加密时写入的IV是16字节(AES-CBC),解密时必须从文件头精确读出这16字节,再传给 cipher.init(...)
  • 别用 BufferedInputStream.mark()/reset() 想“回退读”,流位置容易失控;老实用 RandomAccessFile 或分两步读
  • 如果加密文件格式自定义,建议固定前16字节为IV,后面全是密文——简单、可靠、易调试
try (RandomAccessFile raf = new RandomAccessFile(inputFile, "r")) {
    byte[] iv = new byte[16];
    raf.read(iv); // 精确读16字节IV
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
    try (FileInputStream fis = new FileInputStream(inputFile);
         CipherInputStream cis = new CipherInputStream(fis, cipher);
         FileOutputStream fos = new FileOutputStream(outputFile)) {
        // 跳过IV字节再开始读密文
        fis.skip(16);
        // ... 后续流处理
    }
}

main方法里硬编码路径和密码,根本没法实际使用

写死 new File("test.txt") 和 "123456" 的代码,连命令行运行都困难。真正能用的工具至少要支持参数输入。

立即学习“Java免费学习笔记(深入)”;

  • 用 args 解析:约定 java FileCrypto -e input.txt output.enc password
  • 密码绝不明文打印,用 System.console().readPassword() 获取(注意IDE里 console() 返回null,得切到终端运行)
  • 加个简单校验:输入文件存在、输出路径可写、密码非空——省得报错后看不懂是哪步挂了

IV怎么存、密钥怎么派生、异常怎么分类捕获……这些细节堆起来才叫“工具”,不是demo。初学者最容易在流关闭顺序、IV一致性、字符集指定(比如用 StandardCharsets.UTF_8 替代 "UTF-8" 字符串)上栽跟头,而它们恰恰决定程序能不能稳定跑完一次真实文件。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1838

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2924

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6224

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

6129

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

7714

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

11634

2024.04.29

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

100

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn