Zum Inhalt springen
ecdsa.com
Java · Kotlin

Bouncy Castle (Java)

Der Java-Provider und das PKIX-Toolkit der Legion of the Bouncy Castle: jede Kurve, die das JDK gestrichen hat, deterministisches ECDSA auf Wunsch, PEM-Parsing und die größte Auswahl an Post-Quanten-Signaturen auf der JVM.
Lizenz
MIT
Geprüfte Version
1.86 ·
Quellcode
github.com/bcgit/bc-java
Dokumentation
www.bouncycastle.org/documentation/documentation-java/

Kompatibilität auf einen Blick

ECDSAEdDSAPost-Quanten-Verfahren

ECDSA-Kurven
P-224P-256P-384P-521secp256k1brainpoolP256r1brainpoolP384r1brainpoolP512r1
EdDSA
Ed25519Ed448
Post-Quanten-Algorithmen
ML-KEMML-DSASLH-DSAFalconLMSXMSS

Bouncy Castle ist zweierlei zugleich: ein JCA-Provider (BC), der sich in Signature, KeyPairGenerator und KEM einklinkt, und schlanke APIs wie ECDSASigner, die ohne die JCA funktionieren. bcpkix ergänzt Zertifikate, CMS, OCSP und den PEMParser, der dem JDK bis heute fehlt. Der meiste JVM-Code, der mit secp256k1, Brainpool, PGP oder Zertifikaten arbeitet, hängt von Bouncy Castle ab.

Die ECDSA-Standardeinstellungen entsprechen denen des JDK: SHA256withECDSA erzeugt DER mit zufälliger Nonce und lässt s unnormalisiert, und die Prüfung akzeptiert beide Hälften (Low-S und High-S). Die Unterschiede stecken in Algorithmusnamen, die du ausdrücklich wählen musst. SHA256withPLAIN-ECDSA erzeugt das 64 Byte lange rohe r‖s, das JWS erwartet; SHA256withECDDSA signiert deterministisch, und der schlanke ECDSASigner mit einem HMacDSAKCalculator reproduzierte den Testvektor aus RFC 6979 exakt. Wie bei SunEC führt eine rohe Signatur für den DER-Algorithmus zu SignatureException, statt false zu liefern.

Die Kurvenauswahl ist für die meisten der Grund für Bouncy Castle: Mit P-224 bis P-521, secp256k1 und den Brainpool-r1-Kurven funktionierten Signieren und Prüfen, ebenso mit Ed25519 und Ed448. Registriere den Provider und gib ihn explizit an – KeyPairGenerator.getInstance("EC", "BC") –, denn sonst wird zuerst SunEC aus dem JDK befragt, und SunEC lehnt secp256k1 ab; das Beispiel umgeht genau das.

Die Post-Quanten-Unterstützung in 1.86 ist die breiteste aller geprüften Bibliotheken: ML-KEM über javax.crypto.KEM, ML-DSA, SLH-DSA und LMS im Provider BC sowie Falcon und XMSS in BCPQC. Probiere die Algorithmen im Playground für Post-Quanten-Signaturen aus und untersuche hybride Zertifikate mit dem PQ-Zertifikatsinspektor.

JcaPEMWriter schreibt private Schlüssel vom Typ EC als SEC1 -----BEGIN EC PRIVATE KEY-----, die PEMParser wieder als PEMKeyPair einliest; für Tools, die PKCS#8 erwarten, muss der Schlüssel erst konvertiert werden. Der Konverter DER ⇄ Raw hilft, wenn eine PLAIN- und eine DER-Signatur verwechselt werden.

Fakten und die Prüfungen dahinter

Nichts im Folgenden ist aus einer Dokumentation abgeschrieben. Das Prüfskript content/libraries/verify/bouncy-castle-java/run.sh hat Bouncy Castle (Java) 1.86 am 20. Oktober 2026 im Container-Image maven:3.9.16-eclipse-temurin-25 ausgeführt; die Seite muss mit seiner Ausgabe übereinstimmen, und jeder Fakt führt die zugehörigen Zeilen auf.

  • Kodierung von ECDSA-Signaturen

    der

    SHA256withECDSA liefert DER; SHA256withPLAIN-ECDSA liefert 64 Byte rohes r‖s.

    Von der Prüfung aufgezeichnet
    fact ecdsa-signature-encoding = der
    evidence ecdsa-signature-encoding: SHA256withPLAIN-ECDSA output is 64 bytes, parses as DER: false
  • ECDSA-Nonce

    rfc6979-opt-in

    Standardmäßig zufällig; SHA256withECDDSA lieferte für dieselbe Eingabe identische Signaturen, und ECDSASigner mit HMacDSAKCalculator reproduzierte RFC 6979, Anhang A.2.5.

    Von der Prüfung aufgezeichnet
    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 beim Signieren

    either

    s wird nicht normalisiert: Unter 64 Signaturen traten High-S-Werte auf.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-sign = either
  • High-S bei der Prüfung

    accepts-high-s

    Eine DER-Signatur, in der s durch n − s ersetzt war, bestand die Prüfung.

    Von der Prüfung aufgezeichnet
    fact ecdsa-low-s-verify = accepts-high-s
  • Was der Signaturaufruf hasht

    hashes-message-or-digest

    SHA256withECDSA hasht; NONEwithECDSA signiert einen Digest, und diese Signatur bestand die Prüfung gegen die Nachricht.

    Von der Prüfung aufgezeichnet
    fact ecdsa-prehash = hashes-message-or-digest
  • Fehlerhafte ECDSA-Signatur

    throws

    Eine rohe r‖s-Signatur und ein 3-Byte-Blob, an SHA256withECDSA übergeben, lösen SignatureException aus.

    Von der Prüfung aufgezeichnet
    fact ecdsa-malformed-signature = throws
    evidence ecdsa-malformed-signature: raw r||s to SHA256withECDSA: throws SignatureException; 3 bytes: throws SignatureException
  • ECDSA-Kurven

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

    Signieren und Prüfen funktionierten mit P-224, P-256, P-384, P-521, secp256k1 und brainpoolP256r1/P384r1/P512r1.

    Von der Prüfung aufgezeichnet
    fact ecdsa-curves = P-224, P-256, P-384, P-521, secp256k1, brainpoolP256r1, brainpoolP384r1, brainpoolP512r1
  • EdDSA

    Ed25519Ed448

    Ed25519 und Ed448.

    Von der Prüfung aufgezeichnet
    fact eddsa = Ed25519, Ed448
  • Post-Quanten-Algorithmen

    ML-KEMML-DSASLH-DSAFalconLMSXMSS

    ML-KEM (über javax.crypto.KEM), ML-DSA, SLH-DSA und LMS im Provider BC, Falcon und XMSS in BCPQC – alle bestanden in der Prüfung den Roundtrip.

    Von der Prüfung aufgezeichnet
    fact pqc = ML-KEM, ML-DSA, SLH-DSA, Falcon, LMS, XMSS
  • Formate öffentlicher Schlüssel

    spki-pemspki-der

    Öffentliche Schlüssel werden aus SPKI als PEM über PEMParser und aus SPKI als DER gelesen.

    Von der Prüfung aufgezeichnet
    fact public-key-formats = spki-pem, spki-der
  • Formate privater Schlüssel

    pkcs8-dersec1-pem

    JcaPEMWriter schreibt private Schlüssel vom Typ EC als SEC1-PEM (EC PRIVATE KEY), die PEMParser als PEMKeyPair liest; PKCS#8 als DER wird über die JCA geladen.

    Von der Prüfung aufgezeichnet
    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

Verwendung

Erzeuge im Provider BC einen secp256k1-Schlüssel, signiere deterministisch mit SHA256withECDDSA und prüfe die Signatur.
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));
    }
}

Die Snippet-Testumgebung führt jedes Beispiel unverändert im Container-Image maven:3.9.16-eclipse-temurin-25 aus, und der Lauf schlägt fehl, wenn die Ausgabe nicht übereinstimmt.

Einrichtung
mvn -q -B dependency:copy -Dartifact=org.bouncycastle:bcprov-jdk18on:1.86 -DoutputDirectory=lib >/dev/null
Befehl
java -cp lib/bcprov-jdk18on-1.86.jar Usage.java
Ausgabe muss passen (regulärer Ausdruck)
verified: true, DER starts with 0x30

Bibliotheken