The Basics of Ethereum Keys, IDs and Signatures

Node.js is a great advancement in creating back-end code. So, let’s use it to understand how Ethereum uses its keys and signs for messages…

Photo by Angela Merenkova on Unsplash

The Basics of Ethereum Keys, IDs and Signatures

Node.js is a great advancement in creating back-end code. So, let’s use it to understand how Ethereum uses its keys and signs for messages. Overall, we use public-key encryption and which uses the elliptic curve that Satoshi Nakamoto selected for Bitcoin: secp256k1. With this, we have a random private key of 32 bytes (256 bits). If we run our local blockchain with Ganache, it will show us a number of account addresses:

This is a public identifier for each user. Underneath this is a private key, and which should not be exposed to anyone:

This private key is used to sign for transactions and has an associated public key. The conversion of the private address to a public address is to perform an ECDSA signature, and then take a hash of this with Keccak-256. The address is the first 40 bytes of this signature:

The great thing about this public address is that the public key can be easily extracted from the identifier. This allows everyone to check the signature on a transaction. In the following, we use Node.js to generate a private key, and then sign for a message [here]:

We generate a random 32 byte key with:

const privateKey = crypto.randomBytes(32).toString("hex");

And then generate the public key and the address from:

const publicKey = EthCrypto.publicKeyByPrivateKey(privateKey);
const address = EthCrypto.publicKey.toAddress(publicKey);

Next, we can take a message, and generate a hash of this, and then generate a signature. This requires the private key of the user:

const hash = EthCrypto.hash.keccak256 ([{type: "string", value: message},]);
const signature = EthCrypto.sign(privateKey, hash);

We can check the public key of a signer by recovering it from the signature and the hash of the message:

const signer = EthCrypto.recoverPublicKey(signature, hash);

Finally we can check the signature, by recovering the identity of the signer:

const senderAddress = EthCrypto.recover(signature,hash);

And that’s basically it for keys and signatures in Ethereum. A sample run is [here]:

Private key: 2b6ceaa26d40398a5d4072fc255d2582335ddbc9d0db1cd8c721f485395407c4
Public key: be3335c09520a160bd3fc2faed453be39cea34dbbd4b131eff25160eb78ba28d4c08a314d19fc9579f9dee164e25784990333f2dd7c1ddace41e04cff0b49a8a
Signer address 0x669654868972029F1Bd75c1b5a7A2cB42Dcd70E3
Message: Test
Hash: 0x85cc825a98ec217d960f113f5f80a95d7fd18e3725d37df428eb14f880bdfc12
Signature: 0xd82f3bef84da99d909d973b3caf37231e4db97ec606ba2f0f6ac820b61c86d1741cc7fbe92fc145d59d14d73a9465437b2ee1a2f50018be839256013a6be231c1b
--- Now checking signature ---
Public key recovered: be3335c09520a160bd3fc2faed453be39cea34dbbd4b131eff25160eb78ba28d4c08a314d19fc9579f9dee164e25784990333f2dd7c1ddace41e04cff0b49a8a
Sender (recovered): 0x669654868972029F1Bd75c1b5a7A2cB42Dcd70E3
Now we will encrypt ...
Cipher: {
iv: '26dab379573738a107fa3150b037f79b',
ephemPublicKey: '047329eb00a6787a3e13321b9894db3c00539d3cf14fc685acdd7bebab5e22457f35494d461f0664c070fd8a86914ab67626cdc8cb61431184405d0a0d99e52eef',
ciphertext: '0b9eb5c69899c912bc198b843bea930f',
mac: 'ae430fdeb89c4d6e2ac6344de95138b0cd361ad7cf9383c9747c64bb778c49cd'
}
Decryption: Test

Isn’t ECDSA just magic?

A running demo is here:

https://asecuritysite.com/ethereum/js_ethereum

And on Repl.it: