Message d’erreur
java.security.SignatureException: Invalid encoding for signature
Le détail `Caused by` varie (par exemple « Invalid lenByte » ou « Not the correct tag ») selon l’octet qui a fait échouer l’analyse DER. L’erreur inverse est silencieuse : une signature DER passée à `SHA256withECDSAinP1363Format` ne lève pas d’exception, la vérification renvoie simplement `false`.
Java (JDK) — Signature.verify with SHA256withECDSA (SunEC)
Ce que cela signifie
`SHA256withECDSA` attend une signature ECDSA en ASN.1 DER (`30 … 02 r 02 s`), et les octets que vous avez transmis ne sont pas du DER. Dans presque tous les cas, il s’agit de l’autre encodage standard : la concaténation r‖s de longueur fixe (IEEE P1363) qu’utilisent JWS, WebCrypto et de nombreuses bibliothèques non Java, soit 64 octets pour P-256. Le JDK sait aussi vérifier ce format, sous le nom d’algorithme `SHA256withECDSAinP1363Format`.
Pourquoi cela se produit
Signature r‖s brute vérifiée comme du DER
fréquenteLes signatures issues d’un JWT (ES256), de `crypto.subtle.sign`, d’un code qui concatène r et s à la main ou d’outils blockchain sont des séquences brutes de 64/96/132 octets. Les noms d’algorithme ECDSA par défaut de Java attendent du DER.
Les octets de la signature ont été mal décodés
occasionnelleUn segment JWS base64url décodé avec le décodeur basique (après un remplacement de caractères mal fait), ou de l’hexadécimal décodé comme du base64, produit des octets qui ne sont pas du tout une signature.
Une signature RSA transmise à un vérificateur ECDSA
occasionnelleUne signature RSA de 256 octets n’est pas non plus du DER. Vérifiez l’algorithme du jeton ou du document avant de choisir le vérificateur.
Comment corriger l’erreur
- 1.
Vérifier les signatures brutes avec l’algorithme P1363
Disponible depuis le JDK 9 dans le fournisseur SunEC pour SHA-1/224/256/384/512 avec ECDSA. Aucune conversion n’est nécessaire.
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.
Ou convertir r‖s en DER
Lorsqu’une API impose le DER (par exemple un fournisseur HSM), encapsulez r et s sous forme d’INTEGER DER minimaux dans une SEQUENCE. Le convertisseur DER ⇄ brut vérifie votre conversion.
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; }