Java-Code signiert über java.security.Signature, KeyPairGenerator und KeyFactory, und die Arbeit erledigen die Provider des JDK selbst: SunEC für elliptische Kurven und EdDSA, dazu die neueren Provider für ML-KEM (javax.crypto.KEM, JDK 24) und ML-DSA. Android, Kotlin und jedes JVM-Framework bauen auf derselben API auf, deshalb tauchen ihre Standardeinstellungen in Spring, Keycloak und unzähligen SDKs auf.
Der Algorithmusname bestimmt die Kodierung. SHA256withECDSA erzeugt und erwartet ASN.1-DER; SHA256withECDSAinP1363Format verwendet das 64 Byte lange rohe r‖s, das JWS und WebCrypto brauchen, wie im Beispiel. Eine Verwechslung wirkt sich asymmetrisch aus: Eine rohe Signatur, an SHA256withECDSA übergeben, löst SignatureException aus, während eine DER-Signatur, an die P1363-Variante übergeben, einfach false zurückgibt. NONEwithECDSA signiert einen Digest, den du selbst berechnet hast – die Signatur bestand mit SHA256withECDSA die Prüfung gegen die Nachricht –, und der Hashname ist unabhängig von der Kurve: SHA256withECDSA mit einem P-384-Schlüssel ist zulässig und scheitert bei Gegenstellen, die SHA-384 erwarten.
SunEC in JDK 25 bietet für ECDSA nur secp256r1, secp384r1 und secp521r1: P-224, secp256k1 und die Brainpool-Kurven lösten Fehler aus, weshalb Bitcoin- und Ethereum-Code auf der JVM Bouncy Castle oder web3j verwendet. Nonces sind zufällig, s wird nicht normalisiert, und die Prüfung akzeptiert beide Hälften; für Gegenstellen, die strikt Low-S verlangen, muss s in den Signaturen daher durch n − s ersetzt werden.
Schlüssel werden als X.509-SPKI in DER (X509EncodedKeySpec), als PKCS#8 in DER (PKCS8EncodedKeySpec) oder als rohe Komponenten (ECPrivateKeySpec) geladen. PEM-Unterstützung kam in JDK 25 als Preview-API (java.security.PEMDecoder, JEP 470), die in der Prüfung einen öffentlichen Schlüssel nur mit --enable-preview dekodierte; Produktionscode entfernt weiterhin selbst die PEM-Kopf- und -Fußzeilen und dekodiert den base64-Inhalt. Die Post-Quanten-Unterstützung ist tatsächlich nutzbar: Kapselung mit ML-KEM-512/768/1024 sowie Signieren und Prüfen mit ML-DSA-44/65/87 funktionierten; SLH-DSA ist in diesem JDK nicht enthalten.
Vergleiche Signaturkodierungen mit dem Konverter DER ⇄ Raw und untersuche signierte JARs mit dem JAR-Signaturinspektor.