Aller au contenu
ecdsa.com
Java · Kotlin

Bouncy Castle (Java)

Le fournisseur Java et la boîte à outils PKIX de la Legion of the Bouncy Castle : toutes les courbes retirées du JDK, ECDSA déterministe sur demande, l’analyse PEM et le plus large éventail de signatures post-quantiques sur la JVM.
Licence
MIT
Version vérifiée
1.86 ·
Code source
github.com/bcgit/bc-java
Documentation
www.bouncycastle.org/documentation/documentation-java/

Compatibilité en un coup d’œil

ECDSAEdDSAPost-quantique

Courbes ECDSA
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Algorithmes post-quantiques
ML-KEMML-DSASLH-DSAFalconLMSXMSS
Formats de clé publique
spki-pemspki-der
Formats de clé privée
pkcs8-dersec1-pem

Bouncy Castle est deux choses à la fois : un fournisseur JCA (BC) qui se branche sur Signature, KeyPairGenerator et KEM, et des API légères comme ECDSASigner qui fonctionnent sans la JCA. bcpkix ajoute les certificats, CMS, OCSP et le PEMParser qui manque toujours au JDK. La plupart du code JVM qui touche à secp256k1, à Brainpool, à PGP ou aux certificats en dépend.

Ses comportements ECDSA par défaut sont ceux du JDK : SHA256withECDSA produit du DER avec un nonce aléatoire et ne normalise pas s, et la vérification accepte les deux moitiés. Les différences passent par des noms d’algorithme à demander explicitement. SHA256withPLAIN-ECDSA produit le r‖s brut de 64 octets qu’attend JWS ; SHA256withECDDSA signe de façon déterministe, et l’ECDSASigner léger avec un HMacDSAKCalculator a reproduit exactement le vecteur de test de la RFC 6979. Comme avec SunEC, une signature brute transmise à l’algorithme DER lève SignatureException au lieu de renvoyer false.

C’est la couverture des courbes qui amène ici la plupart des développeurs : de P-224 à P-521, secp256k1 et les courbes Brainpool r1 ont toutes réussi la signature et la vérification, tout comme Ed25519 et Ed448. Enregistrez le fournisseur et nommez-le (KeyPairGenerator.getInstance("EC", "BC")), car sinon SunEC, le fournisseur du JDK, est consulté en premier et rejette secp256k1, ce que l’exemple évite.

La couverture post-quantique de la 1.86 est la plus large parmi les bibliothèques testées : ML-KEM via javax.crypto.KEM, ML-DSA, SLH-DSA et LMS dans le fournisseur BC, ainsi que Falcon et XMSS dans BCPQC. Essayez les algorithmes dans le bac à sable des signatures post-quantiques et inspectez les certificats hybrides avec l’inspecteur de certificats post-quantiques.

JcaPEMWriter écrit les clés privées EC au format SEC1 -----BEGIN EC PRIVATE KEY-----, que PEMParser relit sous forme de PEMKeyPair ; les outils qui attendent du PKCS#8 exigent d’abord une conversion de la clé. Le convertisseur DER ⇄ brut aide lorsqu’une signature PLAIN et une signature DER ont été confondues.

Les faits et les vérifications qui les fondent

Rien de ce qui suit n’est copié d’une documentation. La vérification content/libraries/verify/bouncy-castle-java/run.sh a exécuté Bouncy Castle (Java) 1.86 dans l’image de conteneur maven:3.9.16-eclipse-temurin-25 le 20 octobre 2026 ; la page doit correspondre à ce que la vérification a affiché, et chaque fait cite les lignes en question.

  • Encodage des signatures ECDSA

    der

    SHA256withECDSA renvoie du DER ; SHA256withPLAIN-ECDSA renvoie 64 octets de r‖s brut.

    Relevé par la vérification
    fact ecdsa-signature-encoding = der
    evidence ecdsa-signature-encoding: SHA256withPLAIN-ECDSA output is 64 bytes, parses as DER: false
  • Nonce ECDSA

    rfc6979-opt-in

    Aléatoire par défaut ; SHA256withECDDSA a donné des signatures identiques pour une même entrée, et ECDSASigner avec HMacDSAKCalculator a reproduit l’annexe A.2.5 de la RFC 6979.

    Relevé par la vérification
    fact ecdsa-nonce = rfc6979-opt-in
    evidence ecdsa-nonce: SHA256withECDSA repeats: false; ECDSASigner with HMacDSAKCalculator reproduces RFC 6979 A.2.5: true; SHA256withECDDSA repeats: true
  • Low-S à la signature

    either

    s n’est pas normalisé : des valeurs high-S sont apparues parmi 64 signatures.

    Relevé par la vérification
    fact ecdsa-low-s-sign = either
  • High-S à la vérification

    accepts-high-s

    Une signature DER dont s a été remplacé par n − s a été vérifiée.

    Relevé par la vérification
    fact ecdsa-low-s-verify = accepts-high-s
  • Ce que l’appel de signature hache

    hashes-message-or-digest

    SHA256withECDSA hache les données ; NONEwithECDSA signe un condensat, et cette signature a été vérifiée sur le message.

    Relevé par la vérification
    fact ecdsa-prehash = hashes-message-or-digest
  • Signature ECDSA mal formée

    throws

    Une signature r‖s brute et un bloc de 3 octets passés à SHA256withECDSA lèvent SignatureException.

    Relevé par la vérification
    fact ecdsa-malformed-signature = throws
    evidence ecdsa-malformed-signature: raw r||s to SHA256withECDSA: throws SignatureException; 3 bytes: throws SignatureException
  • Courbes ECDSA

    P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1

    Signature et vérification réussies avec P-224, P-256, P-384, P-521, secp256k1 et brainpoolP256r1/P384r1/P512r1.

    Relevé par la vérification
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 et Ed448.

    Relevé par la vérification
    fact eddsa = Ed25519, Ed448
  • Algorithmes post-quantiques

    ML-KEMML-DSASLH-DSAFalconLMSXMSS

    ML-KEM (via javax.crypto.KEM), ML-DSA, SLH-DSA et LMS dans le fournisseur BC, Falcon et XMSS dans BCPQC : tous ont fonctionné en aller-retour lors des essais.

    Relevé par la vérification
    fact pqc = ML-KEM, ML-DSA, SLH-DSA, Falcon, LMS, XMSS
  • Formats de clé publique

    spki-pemspki-der

    Clés publiques lues depuis SPKI PEM via PEMParser et depuis SPKI DER.

    Relevé par la vérification
    fact public-key-formats = spki-pem, spki-der
  • Formats de clé privée

    pkcs8-dersec1-pem

    JcaPEMWriter écrit les clés privées EC en SEC1 PEM (EC PRIVATE KEY), que PEMParser lit sous forme de PEMKeyPair ; le PKCS#8 DER se charge via la JCA.

    Relevé par la vérification
    fact private-key-formats = pkcs8-der, sec1-pem
    evidence private-key-formats: JcaPEMWriter writes an EC private key as -----BEGIN EC PRIVATE KEY-----; PEMParser returns PEMKeyPair

Utilisation

Générer une clé secp256k1 dans le fournisseur BC, signer de façon déterministe avec SHA256withECDDSA et vérifier.
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Security;
import java.security.Signature;
import java.security.spec.ECGenParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class Usage {
    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        // secp256k1 is not in the JDK's SunEC; it is in BC.
        KeyPairGenerator generator = KeyPairGenerator.getInstance("EC", "BC");
        generator.initialize(new ECGenParameterSpec("secp256k1"));
        KeyPair pair = generator.generateKeyPair();
        byte[] message = "order #1042 approved".getBytes(StandardCharsets.UTF_8);

        // ECDDSA = deterministic ECDSA (RFC 6979); PLAIN-ECDSA = raw r||s instead of DER.
        Signature signer = Signature.getInstance("SHA256withECDDSA", "BC");
        signer.initSign(pair.getPrivate());
        signer.update(message);
        byte[] der = signer.sign();

        Signature verifier = Signature.getInstance("SHA256withECDSA", "BC");
        verifier.initVerify(pair.getPublic());
        verifier.update(message);
        System.out.println("verified: " + verifier.verify(der) + ", DER starts with 0x" + Integer.toHexString(der[0] & 0xff));
    }
}

Le banc de test des extraits de code exécute chaque exemple tel quel dans l’image de conteneur maven:3.9.16-eclipse-temurin-25, et l’exécution échoue si la sortie ne correspond pas.

Mise en place
mvn -q -B dependency:copy -Dartifact=org.bouncycastle:bcprov-jdk18on:1.86 -DoutputDirectory=lib >/dev/null
Commande
java -cp lib/bcprov-jdk18on-1.86.jar Usage.java
La sortie doit correspondre à cette expression régulière
verified: true, DER starts with 0x30

Bibliothèques