I used a smart contract to verify signatures:

function verify(string memory _msg, bytes memory _sig) public pure returns (address) {
    bytes memory _msgHex = bytes(_msg);
    bytes32 prefixedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", uint2str(_msgHex.length), _msgHex));
    (bytes32 _r, bytes32 _s, uint8 _v) = splitSignature(_sig);
    address signer = ecrecover(prefixedHash, _v, _r, _s);
    return signer;

function splitSignature(bytes memory sig) internal pure returns (bytes32 r, bytes32 s, uint8 v) {
    require(sig.length == 65, "invalid signature length");
    assembly {
        r := mload(add(sig, 32))
        s := mload(add(sig, 64))
        v := byte(0, mload(add(sig, 96)))

The function uint2str body is not important. It converts for example 438 to "438".

The main function verify returns signer address depending on message and signature values.

This works good for all signatures, but for a specific signature it returns 0x0000000000000000000000000000000000000000 for whatever message that is given to it.

This special signature is:


But MEW verifies this signature without any problem.

Can anyone suggest a way to verify this signature?

P.S: This signature is produced by Ledger wallet.

  • 1
    The problem is that ECRecover expect the v parameter to be 27 or 28 and in the signature it is 0.
    – Ismael
    Commented Jul 14, 2021 at 1:10
  • Thanks. So how MEW verifies this signature correctly? Commented Jul 14, 2021 at 2:53
  • Where is a documentation about ECRecover parameters? Commented Jul 14, 2021 at 3:16
  • 2
    I had suffered similar problem with eth.sign the last byte is either 00 o 01, and I had to replace it by 1B or 1C (I'd guess that MEW does replace it). The Yellow paper at appendix F - signing transactions says v is 27 or 28. Also check EIP 155 that changes the accepted v values depending on the network id.
    – Ismael
    Commented Jul 14, 2021 at 3:46
  • 1
    @Ismael Please post your comment as an answer, so I give the bounty to your answer. Commented Jul 17, 2021 at 14:31

2 Answers 2


The problem is that ECRecover expect the v parameter to be 27 or 28 and in the signature it is 0.

  • r: 8ecd9d9f1ece5bd0ea1638d9a05bc194bb7536aed42fd6a09fbeb1a9479c3167
  • s: 60ce3ff2dfbf73ad7a488e6d46988a443430a13153b26b99a83d1101d00e36bb
  • v: 00

From Ethereum's Yellow Paper Appendix F - Signing Transactions. The acceptable values for v are 27 or 28.

A solution is to replace the byte at the end of the signature: 00 by 1B (27) or 01 by 1C (28).


If you use golang to verify ledger signatures, this repository may help you: https://github.com/storyicon/sigverify

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.