☰
Java RSA文件加密实战:修改两个默认参数避开常见坑
2026/10/19 5:10:53 网站建设 项目流程

简介:该压缩包为“基于JAVA的RSA文件加密软件的设计与实现”的完整源代码,面向Java或信息安全方向的学习者、毕业设计者及需要落地RSA加密工具的开发者。内容涵盖核心加密算法、文件加解密流程及交互界面,既包含C++底层算法模块(大数运算、RSA算法草稿与核心实现),也提供C#窗体界面与工程配置,可帮助理解RSA密钥生成、加解密过程及跨语言项目整合方法。整个包共56个文件,以cpp、h、cs、resx、ico为主要类型,配合sln、vcproj等工程文件,压缩后仅802KB,目录结构清晰,便于按模块阅读与复现。已有299人学习下载,适合作为课程设计、毕业设计或安全编程入门的参考资料,通过阅读源码即可掌握大整数运算、公私钥生成及文件流加密的关键实现思路。

1. 为什么拿到这份RSA文件加密源代码时,我建议你先改掉两个默认参数

从网盘里解压出这个「基于JAVA的RSA文件加密软件的设计与实现」源码包时,你大概率会和我当初一样:先在src里找到几个带main的类,随便点一个跑起来,用生成的公钥加密一个 txt,再拿私钥解密,看到控制台输出“解密成功”,就以为这套 Java 文件加密工具已经到手了。实际上只要换个场景——加密一张图片、把密文粘贴到 Windows 记事本再存盘、密钥文件里多了一行回车——这套源码立刻翻车。这份资源解决的事很具体:用 Java 实现一个可复用的 RSA 文件加密工具,覆盖密钥对生成、文件加解密、密钥文件读写与格式校验,适合做 java 安全方向的课程设计底稿,也适合准备 java 开发工程师面试时手撕 RSA 源码。但源码里有两个默认值我建议你到手就改:1024 位密钥长度,以及用String直接转字节数组的编码方式。原因在后面的章节里逐一展开。

2. RSA 加密选型之前:密钥长度、填充模式与文件编码的边界

2.1 为什么文件加密场景经常被 RSA 拦在第一步:非对称不是万能钥匙

RSA 的核心是“公钥加密、私钥解密”这一对密钥,公钥可以随便分发,私钥自己保管,这解决了对称加密里密钥配送的难题。你在 Java 基础阶段就接触过KeyPairGenerator,两行代码就能生成密钥对,但真正落地到文件加密,很多人会忽略一个事实:RSA 是数学运算密集型的算法,加密速度比 AES 慢两个数量级。同样的文件,AES 几毫秒跑完,RSA 可能要几十毫秒,文件一大差距直接拉满。

所以从业者常说的“RSA 不适用于大数据量加密”是真的。但这份源码的设计是“纯 RSA 加密文件”,那它适用的场景就非常明确:个人电脑上加密配置文件、密钥材料、几 KB 到几 MB 的小文件,或者作为教学项目展示非对称加密完整流程。如果是加密几百 MB 的视频,正规做法是混合加密——RSA 先加密一个随机生成的 AES 密钥,再用 AES 加密文件本体。这个思路你在很多开源工具里都能看到,但这份源码没有走混合路线,它坚持把 RSA 用到文件块上,那就必须在代码层面处理“分块”,这恰恰是整份源码里最值得看的工程点。

另一个被忽略的点是:RSA 加密得到的密文长度不是“正好等于明文长度”,而是等于密钥模长。1024 位密钥加密后每块密文固定 128 字节,2048 位则固定 256 字节。哪怕你加密一个“hello”,密文也是完整的一块 128/256 字节。这就直接带来两个后果:文件体积会膨胀,以及密文不能用肉眼去读、不能用普通字符串去存。

2.2 密钥长度与填充模式:1024 还是 2048,PKCS1Padding 还是 OAEP

这套源码里最常见的默认写法是KeyPairGenerator.getInstance("RSA")后initialize(1024),然后Cipher.getInstance("RSA/ECB/PKCS1Padding")。字面上看没问题,但 1024 位在今天已经不建议用于正式生产环境,它只能挡住最普通的攻击者,在安全要求高的场景下会被安全团队直接打回。改成 2048 位是成本最低的加固手段,代码只改一个数字,代价是加解密时间大约变成原来的 4 到 8 倍,但对小文件来说依然可以接受。

密钥长度模长/密文块单块最大明文(PKCS1Padding)安全等级
1024 位128 字节117 字节已不推荐教学演示可用
2048 位256 字节245 字节当前主流推荐
3072 位384 字节373 字节长期敏感数据可用

填充模式上,PKCS1Padding是历史最悠久、兼容性最好的选择,几乎所有 RSA 实现都支持。它用最少 11 字节的随机填充来构造符合 PKCS#1 v1.5 规范的密文块,所以单块最大明文是“模长 - 11”。而OAEP(RSA/ECB/OAEPWithSHA-256AndMGF1Padding)更安全,能防止 Bleichenbacher 攻击,代价是填充占用的字节数更多,并且和某些老系统互操作时对方不支持。我一般会给源码保留PKCS1Padding,因为它教学演示直观,但要清楚它的安全上限。如果你的项目要过等保或对接外部系统,再切 OAEP,同时要确认对端使用的哈希算法一致。

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 单块最大明文长度 = 密钥字节数 - 11 // 1024位密钥 -> 117字节;2048位密钥 -> 245字节

这段代码的意义在于把“模式选择”和“分块边界”绑定在一起。ECB在这里只是表示“每块独立加密”,不是对称加密里被诟病的那个 ECB 模式,RSA 的随机填充保证了同一明文在不同加密轮次产生不同密文,所以不存在 ECB 模式的图案泄露问题。参数说明:PKCS1Padding决定了填充开销是 11 字节,后续分块大小全部要按这个数值计算。

2.3 明文与密文的编码处理:Base64 存储与二进制流的取舍

源码里最常见的第二个坑是直接把密文字节数组拿去new String(...)再写文件。RSA 加密后的密文是随机字节,里面可能包含不可打印字符,也可能恰好不符合 UTF-8 的编码规则,强行转字符串会造成数据被替换或截断,解密时报BadPaddingException。正确做法只有两种:二进制流直接写.bin文件,或者用 Base64 编码成可打印文本。

Base64 的优点是可读、可复制、可以粘到 JSON 里,缺点是体积再膨胀约 33%。如果你要做的是一个带图形界面的文件加密小软件,给用户展示“加密后文本”,那 Base64 是必然选择。Java 8 以后用java.util.Base64即可,不必引入第三方包。

import java.util.Base64; // 加密后得到密文字节数组 byte[] cipherBytes = cipher.doFinal(plainBytes); // 用Base64转成可打印字符串,避免乱码 String base64Cipher = Base64.getEncoder().encodeToString(cipherBytes); // 解密前先还原字节数组 byte[] cipherData = Base64.getDecoder().decode(base64Cipher); byte[] plainBytes = cipher.doFinal(cipherData);

逻辑说明:encodeToString把二进制转成由 A-Z、a-z、0-9、+、/ 和 = 组成的字符串,这个过程是单射且无损的;decode再把字符串还原成完全一致的字节数组。参数说明:这里用的是Base64.getEncoder()基础模式,不会自动换行,适合文件整体存储;如果你要输出到控制台或日志,可以用getMimeEncoder()。反过来,如果你从外部拿到一段带换行的 Base64(比如 PEM 文件格式),要用Base64.getMimeDecoder(),它能自动忽略换行符。我在读源码时经常看到作者在这个环节偷懒,直接用字符串构造KeySpec,这是后面解密报错的重灾区。

3. 密钥对生成与密钥文件落盘:KeyPairGenerator、PKCS#8 与 Base64 的三个坑

3.1 生成密钥对的完整代码与参数解析

密钥对生成是整个 RSA 文件加密工具的地基。源码里通常有一句KeyPairGenerator.getInstance("RSA"),然后initialize(1024),这两行在 Java 基础教学里没问题,但在实际文件加密软件里,我建议显式指定算法提供方和状态,避免不同 JDK 版本行为不一致。

import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; // 使用SecureRandom提供高质量随机源 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); SecureRandom secureRandom = new SecureRandom(); keyGen.initialize(2048, secureRandom); KeyPair keyPair = keyGen.generateKeyPair(); // 导出密钥的字节数组,注意格式随算法而定 byte[] privateKeyBytes = keyPair.getPrivate().getEncoded(); byte[] publicKeyBytes = keyPair.getPublic().getEncoded();

逻辑说明:initialize(2048, secureRandom)的第二个参数很重要,SecureRandom是密码学安全的伪随机数生成器,它决定了 RSA 素数选择的随机性,直接关系到密钥强度。如果你省略这个参数,JDK 会自己选一个默认随机源,多数情况下没问题,但在某些嵌入式或特殊环境下会出现随机源熵不足的告警,所以我习惯显式传入。参数说明:2048 位密钥生成时间大约在 0.5 到 2 秒之间,取决于 CPU;如果你看到源码里先Thread.sleep再生成密钥,那不是必要的,直接生成即可。另一点要注意,getEncoded()返回的是“标准编码后的密钥字节”,私钥是 PKCS#8 格式,公钥是 X.509 格式,这两个格式是 Java 默认导出格式,并不互相兼容。

3.2 密钥存储格式对比:PKCS#8、X.509 与 PKCS#1 的区别

如果你把上一步得到的privateKeyBytes直接写文件,然后用文本编辑器打开,会看到一串不可读的二进制。为了让密钥文件可分发、可备份,通用做法是先 Base64 编码,再套上 PEM 头部文本。这里的格式坑在于:Java 私钥导出的是 PKCS#8,它的 PEM 头是BEGIN PRIVATE KEY;而 OpenSSL 默认生成的私钥是 PKCS#1,头是BEGIN RSA PRIVATE KEY。两者虽然都是 RSA 私钥,但内部编码结构不同,混用时必须转换。

格式Java 导出接口PEM 头部转换方式
PKCS#8 私钥PrivateKey.getEncoded()BEGIN PRIVATE KEYJava 原生支持
X.509 公钥PublicKey.getEncoded()BEGIN PUBLIC KEYJava 原生支持
PKCS#1 私钥OpenSSL 常用BEGIN RSA PRIVATE KEY需转换后再加载

源码里如果提供了“加载 OpenSSL 生成的密钥”的功能,那加载代码会复杂得多。最常见的做法是用 Bouncy Castle 的PEMParser,或者把 PKCS#1 的 DER 数据包装进 PKCS#8 的PrivateKeyInfo结构中。如果是纯粹的 Java 项目且密钥由本工具自己生成,那只需要处理 PKCS#8 和 X.509 两种格式,不要混用。很多学员问我为什么把私钥文件给别人之后对方报InvalidKeySpecException,十有八九是把 PEM Header 裁掉的方式不对,或者对方代码里用了X509EncodedKeySpec去加载私钥——类型没对上。

3.3 密钥文件的加载与校验:从 PEM 字符串到 KeySpec 的完整链路

密钥文件落盘后,解密软件启动时要做的第一件事就是把文件内容读回来并还原成PrivateKey对象。这一步源码里最容易出问题的地方是“去头尾”和“去换行”。

import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; public PrivateKey loadPrivateKey(String pemContent) throws Exception { // 去掉BEGIN/END标记行 String base64Part = pemContent .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s", ""); // 去掉所有空白字符 byte[] keyBytes = Base64.getDecoder().decode(base64Part); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory factory = KeyFactory.getInstance("RSA"); return factory.generatePrivate(spec); }

逻辑说明:这段代码先做“清洗”再把 Base64 解码成 DER 字节,最后用PKCS8EncodedKeySpec交给KeyFactory还原成私钥对象。replaceAll("\\s", "")这一步很关键,因为 PEM 文件在传输过程中可能被加上了换行甚至回车符,只要残留一个换行,Base64.getDecoder()就会因为遇到非合法字符而报错。参数说明:PKCS8EncodedKeySpec对应的是私钥的标准编码格式;如果是加载公钥,要换用X509EncodedKeySpec。我在读这份源码时发现作者把这两种 spec 写反过一次,导致公钥加密能跑、私钥解密永远失败,排查了一个小时才定位到是 KeySpec 类型错误。所以你在自己的实现里,记住一句口诀:私钥配PKCS8EncodedKeySpec,公钥配X509EncodedKeySpec。

4. 文件加密与解密实现:分块边界、Cipher 流与 close 顺序

4.1 一次 doFinal 的边界:117 字节背后的密码学算术

如果你看过 RSA 加密的简单示例,多半见过cipher.doFinal("hello".getBytes())把一段短字符串加密完。但文件加密软件不可能只加密 5 个字节,它要处理的内容可能是几百 KB。这时候如果沿用“一次 doFinal”的思路,文件稍大一点就会抛IllegalBlockSizeException: Data must not be longer than 245 bytes。原因在于PKCS1Padding模式下,一次doFinal只能处理一块明文,2048 位密钥对应上限 245 字节。

正确的做法是分块。读取明文中每 245 字节作为一个块,逐块加密,每个密文块是 256 字节,把所有密文块按顺序拼接写入文件。解密时反过来,每 256 字节解出一个最多 245 字节的明文块。

// 加密分块参数 private static final int KEY_BITS = 2048; // 每块最大明文长度 = 密钥字节数 - 11 private static final int MAX_PLAIN_BLOCK = (KEY_BITS / 8) - 11; // 密文块长度 = 密钥字节数 private static final int CIPHER_BLOCK = KEY_BITS / 8;

逻辑说明:KEY_BITS / 8得到密钥的字节长度,2048 位就是 256 字节。MAX_PLAIN_BLOCK是单次doFinal能处理的最大明文长度,填充模式决定必须减去 11 字节。CIPHER_BLOCK是任意明文块加密后的固定长度。这三个参数的推导过程,在很多 java 开发工程师面试题里会以“RSA 加密时为什么报 Data must not be longer than 117 bytes”的面目出现,核心就落在这条减法公式上。

4.2 加密流程:CipherOutputStream 与缓冲区的正确姿势

手写分块循环容易出错,比如最后一块的处理、EOF 判断、密文拼接顺序。更稳妥的落地方式是直接用CipherOutputStream,它内部会在关闭时自动完成所有块的操作。

import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.PublicKey; public void encryptFile(PublicKey publicKey, String sourcePath, String targetPath) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); try (FileInputStream in = new FileInputStream(sourcePath); FileOutputStream out = new FileOutputStream(targetPath); CipherOutputStream cos = new CipherOutputStream(out, cipher)) { byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) != -1) { cos.write(buffer, 0, len); } cos.flush(); // 注意:flush之后,close会触发最后一个完整块的加密 } }

逻辑说明:CipherOutputStream把write进来的数据缓存到内部缓冲区,当达到一个明文块大小(245 字节)时自动加密成 256 字节密文写出去。close()时会调用cipher.doFinal()处理最后可能不足一块的数据,并写入最终填充后的密文块。所以这里的关键点是关流顺序:先关CipherOutputStream或让它随 try-with-resources 正常关闭,再确认FileOutputStream关闭。参数说明:buffer用 1024 字节是通用选择,不是硬性要求;它只负责从源文件读入内容,内部块分割由Cipher控制,不影响加密结果。如果你想加快大文件处理,可以把 buffer 提到 8192,但不要超过几 MB,否则占内存没意义。

4.3 解密流程与 close 顺序的现场

解密是加密的逆过程,我用CipherInputStream来读取密文,同时把解密后的明文写到目标文件。这里必须保留一个认知:CipherInputStream读到 EOF 时,底层的Cipher会做doFinal校验 PKCS#1 填充。如果加密端在写完最后一个密文块后没有正确结束——比如加密端 close 前被强制中断——解密端就会在文件末尾报BadPaddingException。

import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.security.PrivateKey; public void decryptFile(PrivateKey privateKey, String sourcePath, String targetPath) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); try (FileInputStream in = new FileInputStream(sourcePath); CipherInputStream cis = new CipherInputStream(in, cipher); FileOutputStream out = new FileOutputStream(targetPath)) { byte[] buffer = new byte[1024]; int len; while ((len = cis.read(buffer)) != -1) { out.write(buffer, 0, len); } // cis在EOF时自动验证填充,若报错说明密文损坏或密钥不匹配 } }

逻辑说明:CipherInputStream在读取每个密文块时解密并返回明文,到达文件末尾时读取操作会触发内部doFinal,最终把最后一个明文块连同填充校验一起完成。这个机制导致了一个常见反例:有人为了“提前关闭输入流”而手动关掉FileInputStream,导致CipherInputStream还没读到 EOF 就被强制裁剪,解密结果少了一块,还不报错——这是最隐蔽的翻车方式。我的习惯是让 try-with-resources 按声明的逆序自动关闭,不手动干预流。参数说明:buffer大小同样建议 1024 到 8192 之间,密文读取按块发生,buffer 太小不会错,太大也不会让速度提升多少,因为瓶颈是 RSA 的模幂运算。

5. 避坑/常见问题排查:RSA 文件加密翻车的五个典型场景

5.1 现象:加密后的文件比源文件大出一大截,不是预期中的“差不多”

密文文件体积膨胀是 RSA 文件加密的必然结果,但膨胀幅度如果明显异常,就要看是不是数据本身被重复编码了。比如源码里先Base64.getEncoder().encodeToString(cipherBytes),又把得到的字符串按 UTF-8 转字节后写入文件,这等于双重体积放大。还有人在解密时再 Base64 解码一次,结果反而把二进制弄坏。解决:只做一次 Base64 编码,或者干脆用二进制流直接写.bin。我一般会在加密方法里用DataOutputStream写二进制密文,解密时用DataInputStream读回,减少编码层损耗。原因判断很简单:看文件打开后能否看到=结尾的字符串,如果是,说明密文被 Base64 文本化了。

5.2 现象:报IllegalBlockSizeException: Data must not be longer than 117 bytes或 245 字节

这个错几乎是 RSA 分块处理最常见的报错,原因是把整份文件内容一次性传给了doFinal()。doFinal只能处理一个明文块。解决:改用 4.2 节的CipherOutputStream,或者在自写循环里按MAX_PLAIN_BLOCK切块后再逐个加密。很多人以为把 buffer 调小就没事,比如buffer = new byte[64],以为小于 117 字节就不会爆——这个理解是错的。doFinal的入参是整个待加密数据,不是 read 的 buffer 大小,你需要的是循环调用update()或者依赖CipherOutputStream。我在源码里看到过手动update()实现分块的版本,代码能跑但很容易漏掉最后一块的doFinal(),所以能不用手写循环就不用。

5.3 现象:加载密钥文件时报InvalidKeySpecException: IOException: DerInputStream.getLength(): lengthTag=127之类的异常

密钥文件读取失败的根因通常不在KeyFactory,而在加载流程前段的 Base64 清洗不彻底。PEM 文件里有头尾标记、换行、回车,直接decode会让 DER 解析器读到非 Base64 字符或多余字节。解决:在decode前把字符串里的所有空白字符删除,同时确认头尾标记确实被去掉,并且没有引入多余的空格。我排查过一个案例:用户在 Windows 上用记事本编辑 PEM 文件,文件头部多了一个 UTF-8 BOM,导致decode出来的第一个字节是 0xEF,DER 解析直接失败。解决是用Notepad++另存为 UTF-8 无 BOM 格式,或者代码里判断并跳过 BOM。

5.4 现象:解密时报BadPaddingException: Decryption error

这个异常的含义是“最后一个密文块的填充校验失败”,可能原因有几种,按出现频率排序:私钥与公钥不匹配;密文文件在传输中被改过哪怕一个字节;解密时错误地用了 Base64 字符串去doFinal,而不是解码后的字节数组;加密端关闭流之前发生异常,导致最后一个块没有完整写入。解决步骤:先用原始加密环境的公钥和私钥做一次标准加解密回归,排除密钥不匹配;再检查密文文件大小,看是否是密文块长度(256 字节)的整数倍,如果不是,说明写入不完整;最后检查加密端close()是否被异常跳过。这个报错还有一个隐含提示——它不代表你的密钥被猜到了,而是完整性校验失败,所以别急着换密钥。

5.5 现象:大文件加密越来越慢,最后几乎卡死

RSA 加密耗时本来就是对称加密的几十倍,但如果你感觉“越来越慢”,通常不是算法问题,而是代码里有隐藏的全量复制或重复初始化。比如有人把Cipher放在循环里每次都init,每次init都要做密钥预处理,2048 位时尤其耗时。还有人在分块循环里对List<byte[]>做追加合并,每追加一次都复制全量数组,文件一大就把内存打满。解决:Cipher生成后复用,分块循环里直接写入FileOutputStream,不保留历史密文块。我在性能测试里用 2048 位密钥加密 1 MB 文件,合理实现的耗时大约在 3 到 8 秒之间,如果超过这个量级,优先检查是否是二次复制导致内存抖动。另外,SecureRandom实例可以复用,但没必要刻意优化,耗时的主体始终是 RSA 的模幂运算。

5.6 现象:解密后的文件末尾多了或少了数据,但整个过程没有报错

这类问题最具有迷惑性,号称“静默损坏”。根因几乎都是流的关闭顺序不对。比如加密端在CipherOutputStream还没关闭时先关了FileOutputStream,最后一个密文块没被doFinal写出;或者解密端手动中断读取,CipherInputStream没机会做最后的填充验证。解决:用 try-with-resources 保证流的关闭顺序按创建逆序执行,CipherOutputStream永远先于底层文件流关闭。给自己定一条死规矩:加密和解密方法里不手动调用close(),全部交给 try-with-resources。

6. 验证与进阶用法:签名验签和固化脚本把加密链路锁死

6.1 签名验签:私钥签名、公钥验签的追加实现

文件加密工具做到能加解密还不够,真正落地时对方怎么知道“这份文件确实来自我”?答案是用私钥对文件的摘要签名,接收方用公钥验签。Java 里做这件事非常顺,Signature类支持常用摘要算法。

import java.security.Signature; public byte[] signFile(byte[] fileData, PrivateKey privateKey) throws Exception { Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(fileData); return signature.sign(); } public boolean verifyFile(byte[] fileData, byte[] signedData, PublicKey publicKey) throws Exception { Signature signature = Signature.getInstance("SHA256withRSA"); signature.initVerify(publicKey); signature.update(fileData); return signature.verify(signedData); }

逻辑说明:signFile先对文件数据的 SHA-256 摘要做 RSA 运算,输出签名;verifyFile用公钥做逆运算并比对摘要。签名长度固定为密钥模长,2048 位对应 256 字节。参数说明:摘要算法选SHA256withRSA,比默认的 SHA1 更安全,和旧系统对接时再考虑降级。

6.2 一个验证脚本:把生成密钥对、加密、解密、验签串起来

我使用这份源码的习惯是,拿到手先写一个简单的主流程把整条链路跑一遍,确认无异常后再改业务代码。这个脚本对应四个步骤,核心价值是快速回归。

# 1. 生成密钥对,输出私钥/公钥 PEM 文件 java -cp lib/*.jar com.example.rsa.GenerateKeyPair 2048 keypair/ # 2. 用公钥加密 data.txt 得到 data.rsa java -cp lib/*.jar com.example.rsa.EncryptFile keypair/public.pem data.txt data.rsa # 3. 用私钥解密 data.rsa 还原出 recovered.txt java -cp lib/*.jar com.example.rsa.DecryptFile keypair/private.pem data.rsa recovered.txt # 4. 对原始文件签名并验签 java -cp lib/*.jar com.example.rsa.SignFile keypair/private.pem data.txt data.sig java -cp lib/*.jar com.example.rsa.VerifyFile keypair/public.pem data.txt data.sig

这套脚本跑通之后,才算把这份源代码真正“拿住”了。我在接手一套类似源码时曾经因为跳过第 4 步,直接在业务代码里加密文件,结果密钥文件被运维误改了一个字节,排查了半天才发现是密钥损坏而不是算法问题。从那以后,我每次拿到 RSA 相关源码都会强制先走一遍完整的生成、加密、解密、签名、验签流程,把容易翻车的点全暴露在小脚本里,再进业务改造。这个习惯帮我省下的调试时间,远比写脚本的时间多。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询