Ich versuche herauszufinden, wie ich einen öffentlichen Schlüssel (nicht die Adresse) eines Ethereum-Kontos mithilfe der Methode von ethereumjs-util ableiten ecrecover
kann.
Grundsätzlich erhalte ich eine Transaktion per Hash mit Web3, convert r
und s
like v
in this answer und übergebe sie an ecrecover
. Es ergibt zwar einen öffentlichen Schlüssel, aber dieser Schlüssel entspricht nicht der Adresse des Absenders der Transaktion.
Was mache ich falsch?
Code unten:
const ethJsUtil = require('ethereumjs-util');
class EthPubKeyReg {
constructor(web3, chainId) {
this.chainId = chainId;
this.web3 = web3;
}
async extractPubKey(txHash, chainId) {
chainId = (chainId || this.chainId);
let tx = await this.web3.eth.getTransaction(txHash);
let v = parseInt(tx.v);
let msgHash = ethJsUtil.toBuffer(tx.hash);
let r = ethJsUtil.toBuffer(tx.r);
let s = ethJsUtil.toBuffer(tx.s);
let pubKey = ethJsUtil.ecrecover(msgHash, v, r, s);
console.log("address", ethJsUtil.bufferToHex(ethJsUtil.pubToAddress(pubKey)));
return pubKey;
}
async extractPubKeyString(txHash, chainId) {
return ethJsUtil.bufferToHex(await this.extractPubKey(txHash, chainId));
}
}
===== Aktualisierung =====
Ich habe meinen Code so aktualisiert, wie @libertylocked in seiner Antwort unten vorgeschlagen hat:
const Web3 = require('web3');
const ethJsUtil = require('ethereumjs-util');
const Transaction = require('ethereumjs-tx');
const HDWalletProvider = require('truffle-hdwallet-provider');
let provider = new HDWalletProvider(
'some words to instantiate this truffe hdwallet provider',
"https://mainnet.infura.io/[ACCCESS TOKEN]"
);
let web3 = new Web3(provider);
/*
* Extracts the public key of the sender of a
* signed and mined transaction as Buffer
*/
async function extractPubKey(txHash, web3) {
const tx = await web3.eth.getTransaction(txHash) // insert txhash here
console.log("tx.from", tx.from);
const txDetails = new Transaction({
nonce: tx.nonce,
gasPrice: `0x${tx.gasPrice.toString(16)}`,
gasLimit: tx.gas,
to: tx.to,
value: `0x${tx.value.toString(16)}`,
data: tx.input,
chainId: web3.version.network,
r: tx.r,
s: tx.s,
v: tx.v,
});
const pubkey = txDetails.getSenderPublicKey()
console.log("txDetails.getSenderAddress", txDetails.getSenderAddress().toString('hex'));
console.log("Pubkey to address", ethJsUtil.bufferToHex(ethJsUtil.pubToAddress(pubkey)));
return pubkey;
}
/*
* Extracts the public key of the sender of a
* signed and mined transaction as hex string
*/
async function extractPubKeyAsString(txHash, web3) {
return ethJsUtil.bufferToHex(await extractPubKey(txHash, web3));
}
// link to tx on Etherscan: https://etherscan.io/tx/0xbee6f2a54e1c4921dec2d6834334acd3177ce42229e1d1c4d2490fb60839634e
extractPubKeyAsString('0xbee6f2a54e1c4921dec2d6834334acd3177ce42229e1d1c4d2490fb60839634e', web3)
.then(pubkey => {
console.log("pubkeystring", pubkey);
})
.finally(() => process.exit());
Dies ergibt jedoch immer noch eine falsche Absenderadresse:
tx.from 0xBa34A08bcAe1AB74b5e52b6eE06b108945A387f0
txDetails.getSenderAddress efc92668485027e2d41bd229d66111ad0aaa8a16
Pubkey to address 0xefc92668485027e2d41bd229d66111ad0aaa8a16
pubkeystring 0x6d5441c4e53bb8c4dd69b16e79d5ca4f51a84eebaded3b6dfc5b51dd63ee7b5c5707ca1e788653b07872dd8c13293be840c93aeae582f2c080ff8a3aef79a24f
Die einfachste Lösung ist die Verwendung von ethereumjs-tx
module.
Wenn Sie verwenden web3@0.20
:
const Transaction = require('ethereumjs-tx')
const tx = web3.eth.getTransaction(txHash) // insert txhash here
const pubkey = new Transaction({
nonce: tx.nonce,
gasPrice: `0x${tx.gasPrice.toString(16)}`,
gasLimit: tx.gas,
to: tx.to,
value: `0x${tx.value.toString(16)}`,
data: tx.input,
chainId: 1, // mainnet network ID is 1. or use web3.version.network to find out
r: tx.r,
s: tx.s,
v: tx.v,
}).getSenderPublicKey()
console.log(pubkey.toString('hex'))
Wenn Sie web3 1.0 Beta verwenden (und Sie verwenden ethereumjs-util
), müssen Sie einige Werte in Hex-Strings mit vorangestelltem 0x konvertieren
new Transaction({
nonce: tx.nonce,
gasPrice: ethJsUtil.bufferToHex(new ethJsUtil.BN(tx.gasPrice)),
gasLimit: tx.gas,
to: tx.to,
value: ethJsUtil.bufferToHex(new ethJsUtil.BN(tx.value)),
data: tx.input,
chainId: 1,
r: tx.r,
s: tx.s,
v: tx.v,
});
Um zu überprüfen, ob der Pub-Schlüssel von derselben Absenderadresse abgeleitet werden kann, können Sie entweder publicToAddress(pubkey)
from ethereumjs-util
oder tx.getSenderAddress()
from verwendenethereumjs-tx
getSenderAddress().toString('hex')
? Es sollte passen tx.from
.0x
? Versuchen Sie es andernfalls verifySignature()
mit dem ethereumjs tx-Objekt
Benutzer19510
ethereumjs-tx
kann helfen.