Ethereum Classic Public And Private Keys: A Little Enlightenment

in #eth4 years ago (edited)



Interactions with the Ethereum Classic (ETC) system depend on special numbers referred to as public keys and private keys. Private keys are used to transfer funds, install programs, and, run programs. These numbers must be kept secret at all times. Public keys are used to confirm knowledge of private keys without their disclosure. Public keys also provide a means of identifying accounts.



Private keys are 32 byte numbers between 1 and


inclusive. People randomly select them. Some may be concerned that two people might unintentionally select the same private key. The odds of that happening are vanishingly small. In fact, the number of possible private keys is approximately equal to the number of atoms in the entire universe!

Public keys are 64 byte numbers derived from private keys using an odd type of arithmetic with respect to pairs of numbers. Here is a Python script that calculates public keys from private keys:

#!/usr/bin/env python3

Calculates ETC public keys from ETC private keys.

Usage: etc_pub_key <private key>

import random
import sys

A           = 0
N           = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
P           = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
GX          = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
GY          = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
NUM_FORMAT  = "{{:0{}x}}".format(len(hex(P)[2:]))

def inverse(number):
        Inverts a number.

        inverse = 1
        power   = number
        for e in bin(P - 2)[2:][::-1]:
                if int(e):
                        inverse = (inverse * power) % P
                power = (power ** 2) % P

        return inverse

def add(pair_1, pair_2):
        Adds two pairs.

        if   pair_1 == "identity":
                sum_ = pair_2
        elif pair_2 == "identity":
                sum_ = pair_1
                if pair_1 == pair_2:
                        numer   = 3 * pair_1[0] ** 2 + A
                        lambda_ = (numer * inverse(2 * pair_1[1])) % P
                        numer   = pair_2[1] - pair_1[1]
                        denom   = pair_2[0] - pair_1[0]
                        lambda_ = (numer * inverse(denom)) % P
                x    = (lambda_ ** 2 - pair_1[0] - pair_2[0])  % P
                y    = (lambda_ * (pair_1[0] - x) - pair_1[1]) % P
                sum_ = (x, y)

        return sum_

def multiply(number, pair):
        Multiplies a pair by a number.

        product = "identity"
        power   = pair[:]
        for e in bin(number)[2:][::-1]:
                if int(e):
                        product = add(power, product)
                power = add(power, power)

        return product

def convert(pair):
        Converts pairs to numbers by concatenating the elements.

        return int("".join([NUM_FORMAT.format(e) for e in pair]), HEXADECIMAL)

print(convert(multiply(int(sys.argv[1]), (GX, GY))))

The reason for this convoluted process is so that private keys cannot be derived from public keys. If you want to learn more, investigate elliptic curve cryptography. The reason for this name is that historically it followed from calculations of the arc lengths of ellipses.




The first 20 bytes of Keccak 256 hashes of public keys are referred to as account addresses. These are most often used to identify accounts rather than public keys. Interestingly, public keys cannot be determined solely from addresses.

Here is a Python script that calculates addresses from public keys. It requires the PySHA3 package. Addresses are typically expressed in hexadecimal notation and that convention is followed in this script:

#!/usr/bin/env python3

Calculates ETC addresses from ETC public keys.

Usage: etc_address <public key>

import sha3
import binascii
import sys


public_key = (int(sys.argv[1])).to_bytes(N_PUB_KEY_BYTES, byteorder = "big")
print(sha3.keccak_256(public_key).hexdigest()[-2 * N_ADDRESS_BYTES:])


Private keys provide a way to effectively sign transactions. For this, ETC uses the Elliptic Curve Digital Signature Algorithm (ECDSA). The basic idea is to create sets of numbers, corresponding to transactions, that can only be generated by the sending account private keys. This is analogous to handwritten signatures that can only be generated by the corresponding hands.


Programs, or smart contracts, do not have their own public and private keys. Therefore, programs cannot digitally sign transactions. Furthermore, program account addresses must be selected by some other means.



Here is a slightly edited session, on a Linux computer, that calculates a public key and address with regards to a random private key. It uses the aforementioned scripts saved in files called etc_pub_key and etc_address respectively:

% PRIVATE_KEY="92788259381212812445638172234843282167646237087212249687358593145563035518424"

% PUBLIC_KEY=`etc_pub_key $PRIVATE_KEY`

% ADDRESS=`etc_address $PUBLIC_KEY`


% echo $PUBLIC_KEY 

% echo $ADDRESS



Public and private keys are widely used in ETC and in other technologies. Therefore, I hope this has been enlightening.


Feel free to leave any comments or questions below. You can also contact me by clicking any of these icons:

twitter facebook linkedin


I would like to thank IOHK (Input Output Hong Kong) for funding this effort.



This work is licensed under the Creative Commons Attribution ShareAlike 4.0 International License.