Raw-Transaction

在 EIP 155 之後恢復公鑰不走運

  • April 25, 2018

我試圖了解乙太坊交易簽名,但由於某種原因我無法驗證簽名。

我有一個測試賬戶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=0s=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 進行異或來修復它。

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