Solidity

無法使用 ecrecover 驗證 Ledger 在 Solidity 中生成的簽名

  • July 19, 2021

我使用智能合約來驗證簽名:

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)))
   }
}

函式uint2str體並不重要。例如,它轉換438"438".

主函式verify根據消息和簽名值返回簽名者地址。

這適用於所有簽名,但對於特定簽名,它會返回0x0000000000000000000000000000000000000000給它的任何消息。

這個特殊的簽名是:

0x8ecd9d9f1ece5bd0ea1638d9a05bc194bb7536aed42fd6a09fbeb1a9479c316760ce3ff2dfbf73ad7a488e6d46988a443430a13153b26b99a83d1101d00e36bb00

但是 MEW 驗證這個簽名沒有任何問題。

任何人都可以建議一種驗證此簽名的方法嗎?

PS:此簽名由 Ledger 錢包製作。

問題是 ECRecover 期望 v 參數為 27 或 28,而在簽名中它為 0。

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

來自乙太坊的黃皮書附錄 F -簽名交易。v 的可接受值為 27 或 28。

一種解決方案是替換簽名末尾的字節:替換為00( 1B27) 或01替換為1C(28)。

引用自:https://ethereum.stackexchange.com/questions/103307