[Ethereum] Generating an address from a public key

addresses

Been learning about generating wallets in Ethereum and things have been smooth until the point where I turn a public key into an actual address.

Multiple sources say to use Keccak to hash the public key (sans first byte), then take the last 20 bytes of the resulting hash as the address.

The public key I'm using (generated from a tool that I hope does this correctly), is:
0x025f37d20e5b18909361e0ead7ed17c69b417bee70746c9e9c2bcb1394d921d4ae
And the resulting address is supposed to be:
0xd09D3103CcABfb769eDc3e9B01500Ca7241D470A

But none of the various implementations of Keccak (yes, even the ones that are really Keccak and not SHA3) are giving me something that resembles that address.

The hash I'm getting is 83453a8e57a0a2bb1277baea830983bd264e23140ef2cadd74b1e68c5c12f98f which means the address would be the last 20 bytes, or 0x830983bd264e23140ef2cadd74b1e68c5c12f98f

What am I doing wrong here?

Best Answer

This program computes your address given a public key. In your case it returns "0xd09d3103ccabfb769edc3e9b01500ca7241d470a" as address

const assert = require('assert');
const EC = require('elliptic').ec;
const keccak256 = require('js-sha3').keccak256;

async function main() {
  try {
    const ec = new EC('secp256k1');

    // Decode public key
    const key = ec.keyFromPublic('025f37d20e5b18909361e0ead7ed17c69b417bee70746c9e9c2bcb1394d921d4ae', 'hex');

    // Convert to uncompressed format
    const publicKey = key.getPublic().encode('hex').slice(2);

    // Now apply keccak
    const address = keccak256(Buffer.from(publicKey, 'hex')).slice(64 - 40);

    console.log(`Public Key: 0x${publicKey}`);
    console.log(`Address: 0x${address.toString()}`);
  } catch (err) {
    console.log(err);
  }
}

main();

If you have the private key you can replace ec.keyFromPublic('025f...', 'hex') with ec.keyFromPrivate('4444...', 'hex') and should output the same address.

Related Topic