Error message
java.security.InvalidKeyException: No installed provider supports this key: sun.security.rsa.RSAPublicKeyImpl
Also printed as
- 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
The text after the colon is the key's implementation class (`sun.security.rsa.RSAPublicKeyImpl`, `sun.security.ec.ECPublicKeyImpl`, `sun.security.ec.ed.EdDSAPublicKeyImpl`, a Bouncy Castle class…). A `null` key fails earlier with "Key must not be null" on current JDKs.
Java (JDK) — Signature.initVerify / initSign, Cipher.init
What it means
JCA looked for a provider whose implementation of the requested algorithm accepts this key object, and none did. With the default providers this almost always means the key and the algorithm belong to different families — an RSA key handed to `SHA256withECDSA`, an EC key to `SHA256withRSA`, an Ed25519 key to ECDSA. The class name at the end tells you what kind of key actually arrived.
Why it happens
Algorithm and key type do not match
commonTypical in JWT code that derives the JCA algorithm from the token header but uses a statically configured key — after the issuer switches from RS256 to ES256, or when tokens from two issuers reach one verifier.
An Ed25519 or X25519 key treated as an EC key
occasionalEd25519 keys are elliptic-curve keys, but not ECDSA keys: they need `Signature.getInstance("Ed25519")` (JDK 15+). X25519 keys are for key agreement only and cannot sign at all.
A key object from a provider that is not registered
occasionalKeys created by an HSM/PKCS#11 provider or by Bouncy Castle can only be used by that provider. If it is not registered (or you request the algorithm from another provider), no provider accepts the key.
How to fix it
- 1.
Derive and check the algorithm against the key
Map the allowed JWS algorithms to JCA names explicitly and refuse combinations where the key type does not fit, so the failure is a clear policy error instead of a provider lookup error.
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; }