RSA加密代码在IDE正常运行,打包JAR后报InvalidKeySpecException错误
嘿,这种情况我之前踩过坑!大概率是你读取公钥的方式在JAR环境下不兼容导致的——毕竟IDE里是直接读取文件系统的文件,而JAR包内的资源是打包在归档里的,两者的读取逻辑有差异。
看你贴的代码,问题很可能出在keyfis.available()这一步。这个方法在读取JAR内的资源时,返回的往往不是公钥文件的实际大小,导致你只读取了部分公钥字节,后续生成PublicKey实例时自然就抛出无效密钥规范的异常了。
给你几个具体的修复方案:
1. 替换不靠谱的字节读取逻辑
把依赖available()的读取方式换成循环读取,确保完整获取所有公钥字节。你可以自己实现循环,或者用工具类简化:
private static PublicKey readPubKey() throws Exception { Config conf = new Config(); InputStream keyfis = conf.getFileInputStream(publicKeyPath); // 用ByteArrayOutputStream循环读取,避免依赖available() ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int readLen; while ((readLen = keyfis.read(buffer)) != -1) { baos.write(buffer, 0, readLen); } byte[] encKey = baos.toByteArray(); // 别忘了关闭流 keyfis.close(); baos.close(); // 后续生成PublicKey的代码保持不变即可 }
2. 确保JAR内资源路径正确
另外要确认:你的公钥文件是否被正确打包进JAR,且publicKeyPath的路径和JAR内的实际路径匹配。如果之前是用文件系统路径读取(比如/Users/xxx/public.key),打包成JAR后肯定找不到,这时候要改成类路径相对路径,并用类加载器读取:
// 改用类加载器读取JAR内的资源,更可靠 InputStream keyfis = YourCurrentClass.class.getClassLoader().getResourceAsStream(publicKeyPath); if (keyfis == null) { throw new FileNotFoundException("公钥文件未找到,类路径:" + publicKeyPath); }
这里的YourCurrentClass要换成你当前这个方法所在的类名,路径比如如果公钥放在resources/keys/public.key,那publicKeyPath就写keys/public.key。
3. 验证JAR内的公钥完整性
最后可以手动解压JAR包,检查里面的公钥文件内容和你IDE里的原文件是否一致——有些打包工具可能会自动过滤或修改文本文件,导致公钥内容损坏。如果是这种情况,要调整打包配置,确保公钥文件被原样打包。
本质上就是JAR环境下资源读取的特殊性,别用普通文件的逻辑来处理JAR内的资源,换成流式读取或者类加载器的方式,问题基本就能解决啦。
内容的提问来源于stack exchange,提问作者ask

