Aller au contenu
ecdsa.com
ethers v6 (JavaScript)Portefeuilles et signatures Web3

Message d’erreur

invalid raw signature length

Également affiché sous la forme

  • invalid raw signature length (argument="signature", value="0x…", code=INVALID_ARGUMENT, version=6.17.0)
  • TypeError: invalid raw signature length

`err.shortMessage` vaut « invalid raw signature length » ; `err.message` y ajoute l’argument, la valeur et la version d’ethers. L’erreur est une `TypeError` avec `code: "INVALID_ARGUMENT"`.

ethers v6 (JavaScript) — Signature.from() inside verifyMessage / verifyTypedData / recoverAddress

Ce que cela signifie

ethers a tenté d’interpréter les octets de la signature comme une signature ECDSA pour récupérer une adresse, et leur longueur ne correspond à aucune des formes qu’il connaît : 65 octets (r‖s‖v) ou 64 octets (la forme compacte EIP-2098). Aucune récupération n’a été tentée. Ces octets sont généralement un tout autre type de signature : une signature de compte intelligent, qui doit être vérifiée sur la blockchain, ou une signature encodée en DER provenant d’un service de gestion des clés.

Pourquoi cela se produit

Comment corriger l’erreur

  1. 1.

    Vérifier les comptes intelligents sur la blockchain

    Appelez `isValidSignature` (ERC-1271) sur le compte, ou utilisez une bibliothèque qui implémente ERC-6492 pour les comptes contrefactuels (par exemple `verifyMessage` de viem avec un client public).

    js
    import { Contract, hashMessage, JsonRpcProvider } from "ethers";
    
    // Smart accounts (Safe, Coinbase Smart Wallet, ERC-4337 accounts) are verified on-chain (ERC-1271).
    const provider = new JsonRpcProvider(process.env.RPC_URL);
    const account = new Contract(address, ["function isValidSignature(bytes32,bytes) view returns (bytes4)"], provider);
    const magic = await account.isValidSignature(hashMessage(message), signature);
    const valid = magic === "0x1626ba7e";
  2. 2.

    Convertir le DER en r‖s‖v

    Analysez r et s, normalisez s dans la moitié inférieure de l’ordre (Ethereum rejette les valeurs high-S), et essayez les deux bits de récupération pour trouver celui qui donne l’adresse attendue.

    js
    import { Signature, recoverAddress, hashMessage, toBeHex } from "ethers";
    import { secp256k1 } from "@noble/curves/secp256k1.js"; // @noble/curves v2
    
    const N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n; // secp256k1 order
    
    // KMS/HSM: parse DER, move s to the lower half (Ethereum rejects high-s), then find the recovery bit.
    function derToEthSignature(derBytes, digest, expectedAddress) {
      const { r, s } = secp256k1.Signature.fromBytes(derBytes, "der");
      const lowS = s > N / 2n ? N - s : s;
      for (const yParity of [0, 1]) {
        const candidate = Signature.from({ r: toBeHex(r, 32), s: toBeHex(lowS, 32), yParity });
        if (recoverAddress(digest, candidate) === expectedAddress) return candidate.serialized; // 65 bytes
      }
      throw new Error("signature does not belong to " + expectedAddress);
    }
    
    const signature = derToEthSignature(kmsDer, hashMessage(message), kmsAddress);

Erreurs associées

Parcourir toute la base de données des erreurs de signature