ECDSA密钥认证应用报java.security.InvalidKeyException求排查
问题分析与解决
异常信息
java.security.InvalidKeyException: IOException : algid parse error, not a sequence
核心错误点
你的代码存在三个关键错误,导致无法正确读取EC私钥:
- 结束标记替换错误:私钥结束标记是
-----END EC PRIVATE KEY-----,但代码里替换的是-----END PRIVATE KEY-----,残留的无效内容会导致Base64解码后格式错误。 - KeyFactory算法错误:你使用的是ECDSA密钥,但代码中
KeyFactory.getInstance("RSA")指定了RSA算法,应该改为"EC"。 - 密钥格式不匹配:OpenSSL生成的
BEGIN EC PRIVATE KEY是SEC1格式私钥,而PKCS8EncodedKeySpec仅支持PKCS8格式,两者不兼容。
修复方案
方案1:修改代码直接解析SEC1格式私钥
更新密钥处理类(建议重命名为ECKeyService更贴合功能):
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.security.PrivateKey; import java.security.Security; public class ECKeyService { static { // 添加BouncyCastle安全提供者 Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); } public static PrivateKey getPrivateKey(String fileName) throws IOException { try (BufferedReader reader = new BufferedReader(new FileReader(fileName)); PEMParser pemParser = new PEMParser(reader)) { Object object = pemParser.readObject(); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); return converter.getPrivateKey((PrivateKeyInfo) object); } } }
需添加BouncyCastle依赖(Maven示例):
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency>
方案2:将SEC1格式密钥转为PKCS8格式
用OpenSSL命令转换密钥:
openssl pkcs8 -topk8 -inform PEM -in private_key.pem -out private_key_pkcs8.pem -nocrypt
转换后的密钥以-----BEGIN PRIVATE KEY-----开头,修改原代码的错误点即可:
private static PrivateKey getPrivateKeyFromString(String key) throws NoSuchAlgorithmException, InvalidKeySpecException { String privateKeyPem = key; // 修正结束标记替换 privateKeyPem = privateKeyPem.replace("-----BEGIN PRIVATE KEY-----", ""); privateKeyPem = privateKeyPem.replace("-----END PRIVATE KEY-----", ""); privateKeyPem = privateKeyPem.replace("\n", ""); byte[] encoded = Base64.decodeBase64(privateKeyPem); // 改为EC算法 KeyFactory kf = KeyFactory.getInstance("EC"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); return kf.generatePrivate(keySpec); }
额外注意事项
JWTService中使用SignatureAlgorithm.ES256是正确的,对应secp256k1曲线,但解析公钥时也需使用EC算法而非RSA。- 建议将
RSAService重命名为ECKeyService,避免算法类型混淆。
内容的提问来源于stack exchange,提问作者Cross
相关产品推荐
相关产品推荐

