Accounts

獲取任何乙太坊賬戶的公鑰

  • January 13, 2021

0x54dbb737eac5007103e729e9ab7ce64a6850a310我能以某種方式獲得只知道相應的乙太坊地址(例如)的乙太坊賬戶的公鑰嗎?

當且僅當交易已從帳戶發送時,您才可以。當您發送 tx 時,您簽署了交易,它包括這些v rs值。你從簽名的 tx 中解析這些,然後將這些v rs值以及交易的雜湊傳遞回一個函式,它會吐出公鑰。這實際上是您獲取交易發件人地址的方式。

您可以使用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

請注意如何解析給定簽名中的每個值。

來源

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