Javascript

簽署原始交易,錯誤的 R 和 S 值

  • May 14, 2020

我正在嘗試在 javascript 中籤署原始交易,而不依賴於 web3、ethereumjs 等依賴項。

我正在關注此處找到的 python 教程,並隨時移植到 JS:https ://lsongnotes.wordpress.com/2018/01/14/signing-an-ethereum-transaction-the-hard-way/


我首先建構 RLP 編碼的事務:


var FROM_PRIV = "00d862c318d05de0a1c25242c21989e15e35e70c55996fbc4238cd2f2f6a8f62";
//var FROM_ADDR = "8d900bfa2353548a4631be870f99939575551b60";

var NOUNCE = "80";
var GAS_PRICE = "85" + "0BA43B7400";
var GAS_LIMIT = "82" + "5208";

var TO = "94" + "7917bc33eea648809c285607579c9919fb864f8f";

var VALUE = "87" + "03BAF82D03A000";

var CODE = "80";

var EIP_155 = "018080";

//

var SIGN_DATA_NO_LEN = NOUNCE + GAS_PRICE + GAS_LIMIT + TO + VALUE + CODE + EIP_155;

var SIGN_DATA = "EB" + SIGN_DATA_NO_LEN;

console.log("SIGN_DATA " + SIGN_DATA);

哪個正確記錄:

SIGN_DATA EB80850BA43B7400825208947917bc33eea648809c285607579c9919fb864f8f8703BAF82D03A00080018080

接下來,我將其轉換為 Message Hash 以供以後簽名:

var TXN = new Buffer.from(SIGN_DATA, 'hex');

var SIGNING_HASH = keccak256(TXN);//Edit: This is using pre-nist variation of keccack256 from sha3: https://github.com/emn178/js-sha3

console.log("SIGNING_HASH " + SIGNING_HASH);

這也正確記錄:

SIGNING_HASH a4060d01d4add248db470b4121616cbe5b2015daf328809000ec9a1d0954d649

到目前為止,一切似乎都與 python 教程的輸出相匹配,

接下來,我用私鑰(又名 FROM_PRIV)簽署消息雜湊(又名 SIGNING_HASH)


const SIGNATURE = secp256k1.ecdsaSign(Buffer.from(SIGNING_HASH, 'hex'), Buffer.from(FROM_PRIV, 'hex'));

console.log("SIGNATURE " + toHexString(SIGNATURE.signature));

var R_HEX = toHexString(SIGNATURE.signature).slice(0,64);
var S_HEX = toHexString(SIGNATURE.signature).slice(64,64*2);

console.log("RECIEVED R_HEX " + R_HEX);
console.log("RECIEVED S_HEX " + S_HEX);

console.log("EXPECTED R_HEX " + "067940651530790861714b2e8fd8b080361d1ada048189000c07a66848afde46");
console.log("EXPECTED S_HEX " + "69b041db7c29dbcc6becf42017ca7ac086b12bd53ec8ee494596f790fb6a0a69");

輸出的 R 和 S 值與教程生成的不匹配,這裡是日誌:

RECIEVED R_HEX 4c1c84da0afb3b38984fcb56953481bc2c8262f3473e28591384f63baa5e979e
RECIEVED S_HEX 7aa01ea9cb0fc0af56102045c69b46d00c18e4f19fbb612c4ae43e13302c475d

EXPECTED R_HEX 067940651530790861714b2e8fd8b080361d1ada048189000c07a66848afde46
EXPECTED S_HEX 69b041db7c29dbcc6becf42017ca7ac086b12bd53ec8ee494596f790fb6a0a69

我已經secp256k1為 ecdsa 簽名嘗試了三種不同的 npm 依賴項,它們都產生了相同的錯誤輸出。(我目前正在使用const secp256k1 = require('secp256k1');

教程中的預期簽名是067940651530790861714b2e8fd8b080361d1ada048189000c07a66848afde4669b041db7c29dbcc6becf42017ca7ac086b12bd53ec8ee494596f790fb6a0a69,但我得到了簽名4c1c84da0afb3b38984fcb56953481bc2c8262f3473e28591384f63baa5e979e7aa01ea9cb0fc0af56102045c69b46d00c18e4f19fbb612c4ae43e13302c475d

我必須在簽名之前不正確地格式化 SIGNING_HASH 或私鑰,或者 secp256k1-ecdsa 不是我應該使用的?


更有趣的是,如果我完成了教程並使用這些錯誤的 R+S 值建構了一個簽名的 TXN,則 txn 可以正常工作,我只是在主網上廣播了一個來確認,資金確實移動了,並且已經收到了 12 個確認。 . 這是否意味著 secp256k1 的 JS 實現的 R&S 值與你在 python 中得到的不同並不一定重要?python教程也成功廣播了所以目前還不清楚……我們都輸出不同的R,S值,但是當推到推擠時我們都成功廣播了?非常令人費解…

如果我完成了教程並使用這些錯誤的 R+S 值建構了一個簽名的 TXN,則 txn 有效

這似乎表明簽名secp256k1.ecdsaSign是正確的,但不是確定性的,即每次您簽名時它都會改變,即使使用相同的密鑰和數據也是如此。

請注意本教程使用 private_key。sign_deterministic因此,要產生相同的結果,還需要使用確定性實現,即RFC 6979。如果有支持 RFC 的 npm 模組,結果應該匹配。

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