Solidity
如果 toSignString 僅包含數字,則 ecrecover 返回錯誤的地址
//web3 code let hash = web3.utils.soliditySha3("String"); //if replace "String" with "0" "123" etc , ecrecover returns wrong address console.log("hash", web3.utils.soliditySha3("\x19Ethereum Signed Message:\n32", hash)) let signature = await web3.eth.personal.sign(hash, currentAccount); console.log("signature", signature); let r = signature.slice(0, 66); let s = "0x" + signature.slice(66, 130); let v = web3.utils.hexToNumberString("0x" + signature.slice(130, 132)); console.log("r", r); console.log("s", s); console.log("v", v);
//solidity code function extractSigner( uint8 v, bytes32 r, bytes32 s ) internal view returns (address) { string memory n = toString(nonce); //nonce corresponding to "String" in web3 code above bytes32 hash = keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256(bytes(n)) ) ); return ecrecover(hash, v, r, s); }
整個過程是,使用web3js對字元串進行簽名,並在solidity中輸入v,r,s。如果 toSignString 包含任何字母,solidity 會返回正確的地址。但是如果 toSignString 只包含數字,solidity 返回一個錯誤的地址,為什麼?
你的問題在這裡:
let hash = web3.utils.soliditySha3("String");
根據文件,非數字字元串將被解釋為,
string
而數字字元串輸入將被解釋為,uint256
但在可靠性方面,您將字節解釋為string
輸入。abi 編碼不同,您沒有驗證已簽名的相同數據。如果您想確保在簽名者方面進行字元串解釋,則可以快速解決:
let hash = web3.utils.soliditySha3({ type: "string", value: "YOUR-STRING-DATA" });
這樣,傳遞的任何數據都
soliditiSha3
將被解釋為字元串,匹配驗證者的邏輯並允許您恢復正確的地址。