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

RHEL8下生成JWT签名报错InvalidKeyException求助

解决JJWT签名ECDSA密钥时的InvalidKeyException问题

问题重现

签名JWT时抛出如下异常:

io.jsonwebtoken.security.InvalidKeyException: JWT standard signing algorithms require either 1) a SecretKey for HMAC-SHA algorithms or 2) a private RSAKey for RSA algorithms or 3) a private ECKey for Elliptic Curve algorithms. The specified key is of type sun.security.pkcs11.P11Key$P11PrivateKey

报错代码:

public static String createJwtToken(Key privKey, String iss, String[] roles) {
    long nowMs = System.currentTimeMillis();
    long ttl = 60*60*1000; // 1 hour
    Date now = new Date(nowMs);
    Date exp = new Date(nowMs+ttl);
    return "Bearer " + Jwts.builder()
            .setHeaderParam("typ", "JWT")
            .claim("roles", roles)
            .setIssuer(iss).setAudience("DRF")
            .setIssuedAt(now)
            .setExpiration(exp)
            .signWith(privKey)
            .compact();
}

私钥生成代码:

KeyFactory kf = KeyFactory.getInstance("EC");
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey = kf.generatePrivate(keySpec);

环境差异:RHEL7+Java8正常,升级到RHEL8(OpenJDK8/11)后触发错误。

问题原因

RHEL8的OpenJDK默认调高了PKCS11安全提供者的优先级,从PKCS8字节生成EC私钥时,会优先通过PKCS11提供者创建sun.security.pkcs11.P11Key$P11PrivateKey实例。而JJWT的密钥校验逻辑仅识别直接实现ECKey接口的密钥类型,导致校验失败。

解决方案

方案1:指定密钥工厂使用SunEC提供者

修改私钥生成代码,明确指定使用SunEC提供者生成EC密钥,绕过PKCS11:

// 指定SunEC提供者,避免PKCS11生成的密钥类型
KeyFactory kf = KeyFactory.getInstance("EC", "SunEC");
EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey privateKey = kf.generatePrivate(keySpec);

方案2:显式指定签名算法

在签名时明确指定ECDSA算法,让JJWT跳过密钥类型推断,直接使用指定算法处理:

// 替换signWith(privKey)为以下代码,根据密钥算法选择ES256/ES384/ES512
.signWith(privKey, SignatureAlgorithm.ES256)

方案3:调整JVM安全提供者顺序(不推荐)

修改JVM的安全配置文件,将SunEC提供者的顺序调整到PKCS11之前,或者禁用PKCS11提供者。例如创建自定义java.security文件,添加:

security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.ec.SunEC
security.provider.3=sun.security.pkcs11.SunPKCS11

然后启动JVM时指定该配置:

java -Djava.security.properties=/path/to/custom-java.security YourMainClass

注意:此方案可能影响其他依赖PKCS11的安全操作,需谨慎使用。

验证

应用上述任一方案后,重新测试JWT签名功能,确认异常不再抛出,签名成功。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 19:52:49