Message d’erreur
Unexpected recoverable signature length: Expected 65, but got 64 bytes
Également affiché sous la forme
- eth_utils.exceptions.ValidationError: Unexpected recoverable signature length: Expected 65, but got 64 bytes
Le nombre d’octets après « but got » est la longueur de votre signature. La classe de l’exception est `eth_utils.exceptions.ValidationError`.
web3.py / eth-account / eth-keys (Python) — eth_utils.exceptions.ValidationError from Account.recover_message
Ce que cela signifie
eth-keys (utilisé par eth-account et web3.py) ne construit une signature récupérable qu’à partir d’exactement 65 octets : r (32), s (32) et l’octet de récupération v. La signature que vous avez passée a une autre longueur (ici 64 octets) : la récupération n’a donc pas pu commencer. `w3.eth.account.recover_message` de web3.py lève la même erreur, car il délègue à eth-account.
Pourquoi cela se produit
v a été stocké séparément ou supprimé
fréquenteLes back-ends qui stockent des colonnes `r` et `s`, ou les front-ends qui découpent la signature, perdent le dernier octet. Sans v, la clé publique ne peut pas être récupérée sans ambiguïté.
Une signature compacte EIP-2098
occasionnelleLes signatures compactes de 64 octets intègrent le bit de récupération dans le bit de poids fort de s. eth-account ne les accepte pas directement.
Texte hexadécimal passé comme octets
occasionnellePasser `signature_hex.encode()` donne 132 octets d’ASCII au lieu de 65 octets de signature. Passez la chaîne hexadécimale elle-même ou `bytes.fromhex(...)` sans le `0x`.
Comment corriger l’erreur
- 1.
Passer la signature complète telle que renvoyée par le portefeuille
`personal_sign` / `eth_signTypedData_v4` renvoient une chaîne hexadécimale de 65 octets ; conservez-la intacte de bout en bout.
python from eth_account import Account from eth_account.messages import encode_defunct # Pass the 0x-prefixed hex string exactly as the wallet returned it (132 hex chars + "0x"). signer = Account.recover_message(encode_defunct(text=message), signature=signature_hex) assert signer.lower() == expected_address.lower() - 2.
Développer les signatures compactes
Extrayez yParity du bit de poids fort de la seconde moitié et ajoutez v = 27 + yParity à la fin.
python def expand_eip2098(sig: bytes) -> bytes: """64-byte compact signature (r || yParityAndS) -> 65-byte r || s || v.""" r, ys = sig[:32], int.from_bytes(sig[32:], "big") y_parity = ys >> 255 s = ys & ((1 << 255) - 1) return r + s.to_bytes(32, "big") + bytes([27 + y_parity])