在 EIP 155 之後恢復公鑰不走運
我試圖了解乙太坊交易簽名,但由於某種原因我無法驗證簽名。
我有一個測試賬戶
0xb2c899884790aa9e256a2d4b2256ca3319e64e32
,它的公鑰是e7ab22c376286ccb0616888217bc41ec31eafb090fb77900a3946e39eb5c7fa374c8d5fe191f8001d287e678567bc8058eb49729780d2ac9090ffccbc506a754
我採取以下有效交易:
{ "blockHash": "0x3deebc8e1fe36af7f1268ff077cc086c0653fe6fd67aa200608a7379390365f0", "blockNumber": "0x613", "from": "0xb2c899884790aa9e256a2d4b2256ca3319e64e32", "gas": "0x493e0", "gasPrice": "0x0", "hash": "0x6831112de9dc553de7bb111591cabe0c79b5af8c6395c1bc5411ca2fda539735", "input": "0x760a8c2a", "nonce": "0x5", "to": "0x78c215f61ed07929e0084233a3e86bc011bea132", "transactionIndex": "0x0", "value": "0x0", "v": "0x14c3", "r": "0xbddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25b", "s": "0x1959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec" }
或以原始形式:
f8660580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a8214c3a0bddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25ba01959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec
根據EIP 155,我需要散列所有 9 個值,替換
v=chainId (2640)
,r=0
和s=0
. 所以我想出了以下“簽名數據”:
e60580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a820a508080
它的“簽名雜湊”是:
749a36ed5f7c67b1f5eb83a46b0dd6447e9ac050a3f469354fcc4691781a385c
其中,當通過 饋送時
ecrecover
,會給出以下公鑰:
f1308d673d1cf8014370fffb43f36d5e866e405b2b5cecb3025bfb98ae47b18e21fa07c66b31423414c38611038c4c35387db8510757f65b7a632a2d48b0276e
這顯然與實際的公鑰不匹配。
我究竟做錯了什麼?
我的測試程式碼:
var ethutil = require('ethereumjs-util'); var raw = Buffer.from('f8660580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a8214c3a0bddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25ba01959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec','hex'); var data = ethutil.rlp.decode(raw); var v = ethutil.bufferToInt(data[6]); var r = data[7]; var s = data[8]; var chainId = Math.floor((v - 35) / 2); data[6] = ethutil.intToBuffer(chainId); data[7] = Buffer.from(''); data[8] = Buffer.from(''); var msg = ethutil.rlp.encode(data); console.log(msg.toString('hex')); var msgHash = ethutil.sha3(msg); console.log(msgHash.toString('hex')); var publicKey = ethutil.ecrecover(msgHash, (v & 1) + 27, r, s); console.log(publicKey.toString('hex'));
嘗試將倒數第二行替換為:
var publicKey = ethutil.ecrecover(msgHash, (v & 1 ^ 1) + 27, r, s);
您的大部分程式碼對我來說都是正確的,但是 ecrecover 的第二個參數的奇偶校驗必須與
v
值的奇偶校驗相同。因此,如果該v
值以 27 開頭,您可以通過計算並檢查您的程式碼是否會將第二個參數設置為 28。這是錯誤的,可以通過將值與 1 進行異或來修復它。