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:
0x8ecd9d9f1ece5bd0ea1638d9a05bc194bb7536aed42fd6a09fbeb1a9479c316760ce3ff2dfbf73ad7a488e6d46988a443430a13153b26b99a83d1101d00e36bb00
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.
eth.sign
the last byte is either00
o01
, and I had to replace it by1B
or1C
(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.