This example outlines Ethereum signing of a message signed with ECDSA:
Ethereum Signing |
Theory
In Ethereum, we use ECC (Elliptic Curve Cryptography) to create a public key and a private key. The private key is kept secure, and then the public key is used to derive the Ethereum address. When we sign for a transaction, we use our private key, and to create a signature, and which is automatically checked against our Ethereum address.
In creating the keys (for our wallet) we generate a 256-bit private key, and then the public key is a point on the secp256k1 ECDSA curve (x,y point). This key is then hashed using Keccak-256 (aka SHA-3), and the lower 160 bits becomes the public Ethereum address :
The private key should be completely random, and there are 2²⁵⁶ different keys that can be generated, so the chance of us matching a private key to a public key is:
1 in 1,550 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 … 000 (75 zeros — 1.55 quattuorvigintillion)Code
An outline of the code for signing a message with ECDSA is:
import codecs import ecdsa import binascii from Crypto.Hash import keccak import os import sys message="hello" if (len(sys.argv)>1): message=str(sys.argv[1]) private_key_bytes = os.urandom(32) sk = ecdsa.SigningKey.from_string(private_key_bytes, curve=ecdsa.SECP256k1) vk = sk.get_verifying_key() signature = sk.sign(message.encode()) key_bytes =vk.to_string() private_key = codecs.encode(private_key_bytes, 'hex') public_key = codecs.encode(key_bytes, 'hex') print("Message: ",message) print("\nPrivate key: ",private_key) print("Public key: ",public_key) print("\nSignature: ",binascii.b2a_hex(signature)) print("Verify signature: ",vk.verify(signature, message.encode()))
A sample run is:
Message: hello Private key: 8faf1f179270b82b4186be6f9fbc58dde95aea2913c14c357fd0b01c9739dff2 Public key: c9573f0872aea836e9119c4e13969193748a6faeff00edd455f5d4796fa77e5cd7e01c9069bbd4f4c903791f3383279e6693fb69992c9dbf9a6cd23344c013db Signature: 691dfde46318a31fed3e3c639010d81f76a382b3ba897ae890c025a0ebe2cbef1418db494de73281aa6558f56d1a5892d2fc98be3d55238d4f3f7791f801b7e2 Verify signature: True