java.security.InvalidKeyException: IOException : Short read of DER length

在乐优商城项目中,遇到生成RSA密钥对时的错误。测试方法`testRsa()`尝试生成公钥和私钥,但因`@Before`注解的方法`testGetRsa()`在公钥和私钥未生成前尝试读取,导致异常。解决方案是注释掉`testGetRsa()`或调整执行顺序。
@Test
public void testRsa() throws Exception {
    RsaUtils.generateKey(publicKeyPath, privateKeyPath, "234");
}
也是乐优商城生成公钥和私钥报这个错,需要先将下面这个方法或者@Before注释掉,因为这个时候公钥和私钥还没有生成所以读取不到任何内容

@Before
public void testGetRsa() throws Exception {
    privateKey = RsaUtils.getPrivateKey(privateKeyPath);
    publicKey = RsaUtils.getPublicKey(publicKeyPath);
}
### 原因分析与解决方法 `java.security.InvalidKeyException: IOException: Detect premature EOF` 通常发生在密钥格式不完整或不符合标准时。该异常表明在解析 Base64 编码的密钥内容时,输入流提前结束,导致无法正确读取完整的 ASN.1 结构[^2]。 此类问题常见于以下几种情况: - 密钥内容被截断或包含非法字符。 - 使用了错误的编码方式(如未正确使用 Base64 解码)。 - 密钥格式不符合 X.509 或 PKCS#8 标准(例如 RSA 公钥应为 X.509 格式,私钥应为 PKCS#8 格式)。 - 文件读取过程中发生中断或读取不全。 #### 正确处理 RSA 公钥的方式 在 Java 中加载 RSA 公钥时,应确保使用 `X509EncodedKeySpec` 并通过 `KeyFactory` 正确生成公钥对象。以下是一个推荐的实现示例: ```java import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import java.util.Base64; public class RSAEncryption { public static PublicKey getPublicKey(String publicKeyStr) throws Exception { byte[] decodedKey = Base64.getDecoder().decode(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey); return KeyFactory.getInstance("RSA").generatePublic(keySpec); // 确保使用正确的密钥格式 [^2] } public static String encrypt(String data, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes("UTF-8"))); // 使用标准加密模式 [^2] } } ``` #### 密钥格式检查与转换 若从外部获取的密钥不是标准格式,需进行转换。例如,若提供的 RSA 私钥为 PKCS#1 格式而非 PKCS#8 格式,可使用 OpenSSL 进行转换: ```bash # 将 PKCS#1 私钥转换为 PKCS#8 格式 openssl pkcs8 -topk8 -inform PEM -outform PEM -in private_key.pem -out private_key_pkcs8.pem ``` 此操作可确保 Java 的 `PKCS8EncodedKeySpec` 能够正确解析并生成私钥对象[^3]。 #### 文件读取完整性 若密钥是从文件中读取的,需确保整个文件内容被正确加载。可以使用如下代码片段确保读取完整内容: ```java import java.nio.file.Files; import java.nio.file.Paths; public class KeyLoader { public static String readKeyFromFile(String filePath) throws Exception { return new String(Files.readAllBytes(Paths.get(filePath))).replaceAll("\\s", ""); // 去除空格和换行符 [^2] } } ``` ### 总结 要避免 `InvalidKeyException: Detect premature EOF`,必须确保以下几点: - 使用标准格式的密钥(如 RSA 公钥为 X.509,私钥为 PKCS#8)。 - 使用正确的 Base64 解码器对密钥内容进行解码。 - 确保密钥内容完整无损,未被截断或包含非法字符。 - 若密钥来自文件,确保读取全部内容,避免遗漏。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值