Ethereum private/public keys, addresses and PEM certificates
Public key to Ethereum address
A public key must be 64 bytes long (65 bytes with the constant 0x04
prefix). An Ethereum address is made of 20 bytes, it is commonly represented by adding the 0x prefix. In order to derive it, one should take the keccak-256
hash (SHA3-256) of the hexadecimal form of a public key (without the 0x04
prefix), then keep only the last 20 bytes. See this blog post for further details. Example:
# Generate the hash and take the address part > cat pub | keccak-256sum -x -l | tr -d ' -' | tail -c 41
Caveat
An implementation of the SHA3 (Keccak) is not easy to obtain on every platform. Most popular implementation is maandree/sha3sum based on maandree/libkeccak. However, it requires a compilation of the source code.
Python 3.6 hashlib provides an implementation of this algorithm.
Ethereum private to public key
A private key must be 32 bytes long. To obtain a public key, the secp256k1
generator point G must be multiplied by the secret key (which is the private key). An algorithmic description of the elliptic curve point multiplication can be found here. An implementation in Python derived from this thread:
PEM private key and certificate from hex private/public keys
A secp256k1
private key in PEM format (including the public key) can be constructed by openssl
with an intermediate step over a DER format key expressed in ASN.1 syntax (openssl nconf):
asn1 = SEQUENCE:seq_section [seq_section] version = INTEGER:01 privateKey = FORMAT:HEX,OCT:<private key hex> parameters = EXPLICIT:0,OID:secp256k1 publicKey = EXPLICIT:1,FORMAT:HEX,BITSTR:<public key hex>
A PEM file can be then obtained by:
> openssl asn1parse -noout -genconf privkey.asn1 -out privkey.der > openssl ec -inform DER -in privkey.der -out privkey.pem
PEM key check
> openssl ec -noout -text -in privkey.pem
PEM certificate from PEM key
> openssl req -new -nodes -key privkey.pem -x509 -days 365 -out certificate.pem -subj "/CN=localhost"
Check certificate
> openssl x509 -noout -text -in certificate.pem