Mensaje de error
java.security.InvalidAlgorithmParameterException: Curve not supported: secp256k1 (1.3.132.0.10)
También se muestra como
- Legacy SunEC curve disabled
Lo lanzan `KeyPairGenerator.initialize`, `KeyFactory.generatePublic/Private` (envuelto en `InvalidKeySpecException`) y `Signature.initVerify`, según dónde aparezca la curva por primera vez. JDK 15 ya había desactivado estas curvas por defecto (JDK-8237219) con el mensaje «Legacy SunEC curve disabled», y se podían volver a activar con `-Djdk.sunec.disableNative=false`; JDK 14 y anteriores las admitían.
Java (JDK 16+) — KeyPairGenerator / KeyFactory / Signature with the SunEC provider
Qué significa
El JDK conoce el nombre secp256k1 (la curva que usan Bitcoin y Ethereum) —incluso lo resuelve a su OID 1.3.132.0.10—, pero su proveedor integrado SunEC ya no la implementa. JDK 16 eliminó las curvas heredadas junto con la biblioteca EC nativa (nota de la versión «Removal of Legacy Elliptic Curves», JDK-8235710) y conservó solo las curvas con implementaciones modernas: P-256, P-384, P-521, X25519/X448 y Ed25519/Ed448. El código que funcionaba en Java 8 u 11 falla aquí tras una actualización.
Por qué ocurre
Ejecución en JDK 16 o posterior
frecuenteLa lista de curvas de SunEC se redujo en JDK 16. Actualizar el entorno de ejecución de un servicio relacionado con blockchain es el desencadenante más habitual.
JWT con ES256K o JWK de secp256k1
ocasionalLas bibliotecas JOSE que delegan en JCA (por ejemplo, Nimbus) necesitan un proveedor con secp256k1 para `ES256K` (RFC 8812).
Código copiado de un ejemplo anterior a 2021
ocasionalLos ejemplos que usan `ECGenParameterSpec("secp256k1")` con el proveedor predeterminado son anteriores a la eliminación.
Cómo solucionarlo
- 1.
Usar el proveedor Bouncy Castle
Bouncy Castle implementa secp256k1 en Java puro. Regístralo y solicítalo explícitamente con `"BC"`.
java import java.security.*; import java.security.spec.ECGenParameterSpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; Security.addProvider(new BouncyCastleProvider()); KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "BC"); generator.initialize(new ECGenParameterSpec("secp256k1")); KeyPair pair = generator.generateKeyPair(); Signature signature = Signature.getInstance("SHA256withECDSA", "BC"); - 2.
Para trabajar con Ethereum, usar una biblioteca hecha para ello
web3j y otras bibliotecas similares se encargan por ti de secp256k1, de los ID de recuperación y de los prefijos EIP-191, algo que JCA por sí solo no hace.
java // Ethereum signing/recovery: web3j implements secp256k1 itself (on top of Bouncy Castle). org.web3j.crypto.ECKeyPair keyPair = org.web3j.crypto.Keys.createEcKeyPair(); org.web3j.crypto.Sign.SignatureData sig = org.web3j.crypto.Sign.signPrefixedMessage(message, keyPair);