The Basics of Ethereum Keys, IDs and Signatures
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: