簽署原始交易,錯誤的 R 和 S 值
我正在嘗試在 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 模組,結果應該匹配。