Zum Inhalt springen
ecdsa.com
Java (JDK)Java

Fehlermeldung

java.security.SignatureException: Invalid encoding for signature

Das Detail unter `Caused by` variiert (zum Beispiel „Invalid lenByte“ oder „Not the correct tag“), je nachdem, an welchem Byte das DER-Parsing gescheitert ist. Der umgekehrte Fehler fällt nicht auf: Eine DER-Signatur, die an `SHA256withECDSAinP1363Format` übergeben wird, wirft keine Exception, sondern liefert bei der Prüfung einfach `false`.

Java (JDK) — Signature.verify with SHA256withECDSA (SunEC)

Was der Fehler bedeutet

`SHA256withECDSA` erwartet eine ECDSA-Signatur in ASN.1 DER (`30 … 02 r 02 s`), und die Bytes, die du übergeben hast, sind kein DER. Fast immer handelt es sich um die andere Standardkodierung: die Verkettung r‖s mit fester Länge (IEEE P1363), die JWS, WebCrypto und viele Bibliotheken außerhalb von Java verwenden – 64 Byte für P-256. Auch dieses Format kann das JDK prüfen, unter dem Algorithmusnamen `SHA256withECDSAinP1363Format`.

Warum der Fehler auftritt

So behebst du den Fehler

  1. 1.

    Rohe Signaturen mit dem P1363-Algorithmus prüfen

    Seit JDK 9 im Provider SunEC für SHA-1/224/256/384/512 mit ECDSA verfügbar. Keine Konvertierung nötig.

    java
    // JWS (ES256) and WebCrypto subtle.sign() produce raw r||s; WebAuthn and X.509 use DER.
    Signature verifier = Signature.getInstance("SHA256withECDSAinP1363Format");
    verifier.initVerify(publicKey);
    verifier.update(signedBytes);
    boolean ok = verifier.verify(rawSignature); // 64 bytes for P-256
  2. 2.

    Oder r‖s in DER konvertieren

    Besteht eine API auf DER (zum Beispiel ein HSM-Provider), verpacke r und s als minimale DER-INTEGERs in einer SEQUENCE. Der Konverter DER ⇄ Raw prüft deine Umwandlung.

    java
    static byte[] p1363ToDer(byte[] raw) {
      int n = raw.length / 2;
      byte[] r = derInteger(java.util.Arrays.copyOfRange(raw, 0, n));
      byte[] s = derInteger(java.util.Arrays.copyOfRange(raw, n, raw.length));
      var out = new java.io.ByteArrayOutputStream();
      out.write(0x30);
      out.write(r.length + s.length); // < 128 for P-256 and P-384
      out.writeBytes(r);
      out.writeBytes(s);
      return out.toByteArray();
    }
    
    static byte[] derInteger(byte[] v) {
      int i = 0;
      while (i < v.length - 1 && v[i] == 0) i++;
      boolean pad = (v[i] & 0x80) != 0;
      byte[] out = new byte[2 + (pad ? 1 : 0) + v.length - i];
      out[0] = 0x02;
      out[1] = (byte) (out.length - 2);
      System.arraycopy(v, i, out, pad ? 3 : 2, v.length - i);
      return out;
    }

Verwandte Fehler

Gesamte Signaturfehler-Datenbank durchsuchen