Перейти к содержимому
ecdsa.com
Java (JDK 16+)Java

Сообщение об ошибке

java.security.InvalidAlgorithmParameterException: Curve not supported: secp256k1 (1.3.132.0.10)

Также выводится как

  • Legacy SunEC curve disabled

Исключение выбрасывают `KeyPairGenerator.initialize`, `KeyFactory.generatePublic/Private` (в обёртке `InvalidKeySpecException`) и `Signature.initVerify` — в зависимости от того, где кривая встречается впервые. В JDK 15 эти кривые уже были отключены по умолчанию (JDK-8237219) с сообщением «Legacy SunEC curve disabled», и снова включить их можно было флагом `-Djdk.sunec.disableNative=false`; JDK 14 и более ранние версии их поддерживали.

Java (JDK 16+) — KeyPairGenerator / KeyFactory / Signature with the SunEC provider

Что это означает

JDK знает имя secp256k1 (кривая, которую используют Bitcoin и Ethereum) и даже сопоставляет ему OID 1.3.132.0.10, но встроенный провайдер SunEC её больше не реализует. В JDK 16 устаревшие кривые удалили вместе с нативной библиотекой EC (примечание к выпуску «Removal of Legacy Elliptic Curves», JDK-8235710) и оставили только кривые с современными реализациями: P-256, P-384, P-521, X25519/X448 и Ed25519/Ed448. Код, который работал на Java 8 или 11, после обновления падает здесь.

Почему это происходит

Как исправить

  1. 1.

    Используйте провайдер Bouncy Castle

    Bouncy Castle реализует secp256k1 на чистой Java. Зарегистрируйте провайдер и явно запрашивайте его через `"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. 2.

    Для работы с Ethereum используйте специализированную библиотеку

    web3j и подобные библиотеки сами работают с secp256k1, идентификаторами восстановления и префиксами EIP-191, а обычный JCA этого не делает.

    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);

Связанные ошибки

Открыть всю базу ошибок подписей