跳到主要内容
ecdsa.com
Java (JDK)Java

错误信息

java.security.InvalidKeyException: No installed provider supports this key: sun.security.rsa.RSAPublicKeyImpl

也可能输出为

  • java.security.InvalidKeyException: No installed provider supports this key: sun.security.ec.ECPublicKeyImpl
  • java.security.InvalidKeyException: No installed provider supports this key: sun.security.ec.ed.EdDSAPublicKeyImpl

冒号后面的文本是密钥的实现类(`sun.security.rsa.RSAPublicKeyImpl`、`sun.security.ec.ECPublicKeyImpl`、`sun.security.ec.ed.EdDSAPublicKeyImpl`、某个 Bouncy Castle 类……)。在当前的 JDK 上,`null` 密钥会更早失败,报错“Key must not be null”。

Java (JDK) — Signature.initVerify / initSign, Cipher.init

含义

JCA 逐一查找提供程序,看哪个提供程序对所请求算法的实现能接受这个密钥对象,结果一个也没有。在使用默认提供程序时,这几乎总是意味着密钥和算法属于不同的算法族——把 RSA 密钥交给了 `SHA256withECDSA`、把 EC 密钥交给了 `SHA256withRSA`、把 Ed25519 密钥交给了 ECDSA。消息末尾的类名会告诉你实际收到的是哪种密钥。

原因

修复方法

  1. 1.

    推导算法并对照密钥检查

    把允许的 JWS 算法显式映射到 JCA 名称,并拒绝密钥类型不符的组合,这样失败时报出的就是清晰的策略错误,而不是提供程序查找错误。

    java
    static Signature verifierFor(String jwsAlg, PublicKey key) throws GeneralSecurityException {
      String jca = switch (jwsAlg) {
        case "ES256" -> "SHA256withECDSAinP1363Format";
        case "ES384" -> "SHA384withECDSAinP1363Format";
        case "RS256" -> "SHA256withRSA";
        case "PS256" -> "RSASSA-PSS";
        default -> throw new GeneralSecurityException("algorithm not allowed: " + jwsAlg);
      };
      boolean keyFits = jwsAlg.startsWith("ES") ? key instanceof java.security.interfaces.ECPublicKey
                                                : key instanceof java.security.interfaces.RSAPublicKey;
      if (!keyFits) throw new GeneralSecurityException(jwsAlg + " does not match a " + key.getAlgorithm() + " key");
      Signature signature = Signature.getInstance(jca);
      if (jwsAlg.equals("PS256")) {
        signature.setParameter(new java.security.spec.PSSParameterSpec("SHA-256", "MGF1",
            java.security.spec.MGF1ParameterSpec.SHA256, 32, 1));
      }
      signature.initVerify(key);
      return signature;
    }

相关错误

浏览完整的签名错误库