Mensaje de error
java.security.InvalidKeyException: No installed provider supports this key: sun.security.rsa.RSAPublicKeyImpl
También se muestra como
- 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
El texto que sigue a los dos puntos es la clase de implementación de la clave (`sun.security.rsa.RSAPublicKeyImpl`, `sun.security.ec.ECPublicKeyImpl`, `sun.security.ec.ed.EdDSAPublicKeyImpl`, una clase de Bouncy Castle…). Una clave `null` falla antes, con «Key must not be null», en los JDK actuales.
Java (JDK) — Signature.initVerify / initSign, Cipher.init
Qué significa
JCA buscó un proveedor cuya implementación del algoritmo solicitado aceptara este objeto de clave, y no encontró ninguno. Con los proveedores predeterminados, esto casi siempre significa que la clave y el algoritmo pertenecen a familias distintas: una clave RSA pasada a `SHA256withECDSA`, una clave EC a `SHA256withRSA`, una clave Ed25519 a ECDSA. El nombre de clase del final te dice qué tipo de clave llegó en realidad.
Por qué ocurre
El algoritmo y el tipo de clave no coinciden
frecuenteEs típico del código JWT que deduce el algoritmo JCA del encabezado del token pero usa una clave configurada de forma estática: ocurre cuando el emisor pasa de RS256 a ES256 o cuando a un mismo verificador llegan tokens de dos emisores.
Una clave Ed25519 o X25519 tratada como clave EC
ocasionalLas claves Ed25519 son claves de curva elíptica, pero no claves ECDSA: necesitan `Signature.getInstance("Ed25519")` (JDK 15 o posterior). Las claves X25519 sirven solo para el acuerdo de claves y no pueden firmar en absoluto.
Un objeto de clave de un proveedor que no está registrado
ocasionalLas claves creadas por un proveedor HSM/PKCS#11 o por Bouncy Castle solo las puede usar ese proveedor. Si no está registrado (o pides el algoritmo a otro proveedor), ningún proveedor acepta la clave.
Cómo solucionarlo
- 1.
Deducir el algoritmo y comprobarlo frente a la clave
Asigna explícitamente los algoritmos JWS permitidos a nombres JCA y rechaza las combinaciones en las que el tipo de clave no encaja, para que el fallo sea un error de política claro y no un error en la búsqueda de proveedor.
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; }