You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确读取PEM格式私钥?读取时触发InvalidKeySpecException报错

解决java.security.spec.InvalidKeySpecException读取RSA私钥生成JWT的问题

你在读取RSA私钥生成JWT时遇到以下错误:

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : null

代码中直接使用Base64解码私钥后通过PKCS8EncodedKeySpec解析,但报错依旧。

问题诊断

你的私钥是PKCS#1格式的,而PKCS8EncodedKeySpec仅支持解析PKCS#8格式的私钥编码,这是导致错误的核心原因。PKCS#1和PKCS#8是两种不同的RSA私钥编码标准,结构不兼容。

解决方案

提供两种可行的解决方式,按需选择:

方法1:将私钥转换为PKCS#8格式(推荐,无需修改代码)

使用OpenSSL命令将PKCS#1格式的私钥转换为PKCS#8格式:

openssl pkcs8 -topk8 -inform PEM -in your_private_key.pem -outform PEM -nocrypt -out private_key_pkcs8.pem

转换完成后,取出文件中-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----之间的Base64字符串,替换到代码的privateKeyPEMFormatted变量中即可。

方法2:在代码中直接解析PKCS#1格式私钥(需依赖BouncyCastle)

如果无法提前转换私钥,可以通过BouncyCastle库辅助解析PKCS#1私钥:

  1. 首先添加Maven依赖:
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
  1. 修改私钥解析代码:
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.Security;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.RSAPrivateKeySpec;
import java.util.Base64;

private PrivateKey getPrivateKey() throws Exception {
    // 注册BouncyCastle提供者
    Security.addProvider(new BouncyCastleProvider());
    
    String privateKeyPEM = "MIIBVgIBADANBgkqhkiG9w0BAQEFAASCATwwggE4AgEAAkEAzPUG7l/N0B5wr7TxF0+5Uxl5GZJ9N7ck+l5lUGM3yMR5YVqekZ6J0ON5nFfTmT3Tx5h+u5YKhzZ/bHYf8bFg9wIDAQABAkAAvNjEzfDbBVeBGWRCGhfM4kQFdyI9IoO2HJ6WgdSZK/LQvdSMbJf6e4O08Kj2FSq+O1WLPoT3sQ4lNaaRQ+2hAiEA+u5tQFcmFUVZsZb+uD/FXNdBlRXI/D7L4Ib4Nnb3OgECIQDYfhFPBeROr9tQRYNhuWmfGAtSjaKlG2cGQXYMlyiNVwIgCcLr5G6eGHiz7E9aPyRQo/1Wn+5x3w9Z0P1pX6QEzL8CIQCET+ZWAA8lfvTofU8QzXpJcN9L5xROOZ1TGyz+jmiOFQIhAK9F1mpOKkFdTLDXrdypo+5rAhnxqV2P9Hp+1vKQtZ9x";
    
    // 解码Base64私钥
    byte[] pkcs1Bytes = Base64.getDecoder().decode(privateKeyPEM);
    ASN1Sequence pkcs1Seq = ASN1Sequence.getInstance(pkcs1Bytes);
    
    // 提取PKCS#1结构中的私钥参数
    RSAPrivateKeySpec spec = new RSAPrivateKeySpec(
        ((ASN1Integer) pkcs1Seq.getObjectAt(1)).getPositiveValue(),
        ((ASN1Integer) pkcs1Seq.getObjectAt(3)).getPositiveValue()
    );
    
    // 使用BouncyCastle的KeyFactory生成私钥
    KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
    return kf.generatePrivate(spec);
}

验证

生成私钥后,可以用以下代码测试JWT签名:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

String jwt = Jwts.builder()
    .setSubject("test_user")
    .signWith(getPrivateKey(), SignatureAlgorithm.RS256)
    .compact();
System.out.println(jwt);

内容的提问来源于stack exchange,提问作者Yaron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 16:43:12