Accounts
獲取任何乙太坊賬戶的公鑰
0x54dbb737eac5007103e729e9ab7ce64a6850a310
我能以某種方式獲得只知道相應的乙太坊地址(例如)的乙太坊賬戶的公鑰嗎?
當且僅當交易已從帳戶發送時,您才可以。當您發送 tx 時,您簽署了交易,它包括這些
v
r
和s
值。你從簽名的 tx 中解析這些,然後將這些v
r
和s
值以及交易的雜湊傳遞回一個函式,它會吐出公鑰。這實際上是您獲取交易發件人地址的方式。您可以使用ethereumjs-utils 之類的工具自己執行此操作:
/** * ECDSA public key recovery from signature * @param {Buffer} msgHash * @param {Number} v * @param {Buffer} r * @param {Buffer} s * @return {Buffer} publicKey */ exports.ecrecover = function (msgHash, v, r, s) { var signature = Buffer.concat([exports.setLength(r, 32), exports.setLength(s, 32)], 64) var recovery = v - 27 if (recovery !== 0 && recovery !== 1) { throw new Error('Invalid signature v value') } var senderPubKey = secp256k1.recover(msgHash, signature, recovery) return secp256k1.publicKeyConvert(senderPubKey, false).slice(1) }
作為另一個真實場景,ethereumjs-tx使用這個函式來驗證簽名:
/** * Determines if the signature is valid * @return {Boolean} */ verifySignature () { const msgHash = this.hash(false) // All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid. if (this._homestead && new BN(this.s).cmp(N_DIV_2) === 1) { return false } try { let v = ethUtil.bufferToInt(this.v) if (this._chainId > 0) { v -= this._chainId * 2 + 8 } this._senderPubKey = ethUtil.ecrecover(msgHash, v, this.r, this.s) } catch (e) { return false } return !!this._senderPubKey }
有關
v
r
和的更多資訊s
:v、r 和 s 是可以從簽名中解析的參數。這是 ethereumjs utils 庫中的一個很好的例子:
var sig = secp256k1.sign(msgHash, privateKey) var ret = {} ret.r = sig.signature.slice(0, 32) ret.s = sig.signature.slice(32, 64) ret.v = sig.recovery + 27
請注意如何解析給定簽名中的每個值。