Fehlermeldung
invalid signature length
Auch ausgegeben als
- Error: invalid signature length
viem (TypeScript) — recoverMessageAddress / recoverAddress / recoverTypedDataAddress / recoverPublicKey
Was der Fehler bedeutet
Die Recovery-Funktionen von viem akzeptieren eine Signatur als Hex oder Bytes mit genau 65 Byte (r‖s‖v) und brechen bei jeder anderen Länge mit diesem schlichten `Error` ab – auch bei der kompakten 64-Byte-Form nach EIP-2098, die viem nur über explizite Konvertierungsfunktionen unterstützt. Es wurde nichts wiederhergestellt; die Signatur liegt in einem anderen Format vor, oder sie ist gar keine EOA-Signatur.
Warum der Fehler auftritt
Eine kompakte 64-Byte-Signatur (EIP-2098)
häufigManche Wallets, Relayer und Contracts speichern Signaturen in der kompakten Form (yParity in s eingebettet). ethers akzeptiert sie direkt, die `recover*`-Funktionen von viem nicht.
Eine Smart-Account-Signatur
häufigERC-1271- und ERC-6492-Signaturen von Safe, Coinbase Smart Wallet oder anderen Smart Accounts sind länger als 65 Byte, und aus ihnen lässt sich keine Adresse wiederherstellen; sie müssen gegen den Konto-Contract geprüft werden.
Base64- oder doppelte Hex-Kodierung
gelegentlichEine als base64 übertragene Signatur oder ein Hex-String, der noch einmal als Hex kodiert wurde, hat beim Einlesen durch viem die falsche Länge.
So behebst du den Fehler
- 1.
Kompakte Signaturen vor der Wiederherstellung konvertieren
`parseCompactSignature` zusammen mit `compactSignatureToSignature` macht aus der 64-Byte-Form die 65-Byte-Form.
ts import { compactSignatureToSignature, parseCompactSignature, recoverMessageAddress, serializeSignature, size } from "viem"; const sig = size(signature) === 64 ? serializeSignature(compactSignatureToSignature(parseCompactSignature(signature))) : signature; const signer = await recoverMessageAddress({ message, signature: sig }); - 2.
Für Wallets aller Art publicClient.verifyMessage verwenden
Ein Public Client prüft EOA-Signaturen lokal und Smart-Account-Signaturen über ERC-1271/ERC-6492, sodass derselbe Code für jeden Wallet-Typ funktioniert.
ts import { createPublicClient, http } from "viem"; import { mainnet } from "viem/chains"; // Handles EOAs, ERC-1271 smart accounts and ERC-6492 (undeployed) accounts. const client = createPublicClient({ chain: mainnet, transport: http(process.env.RPC_URL) }); const valid = await client.verifyMessage({ address, message, signature });