Profile picture

Adjunct Professor @ University of Lausanne

Blockchain and Distributed Ledgers

Last updated: September 18th, 20192019-09-18Project preview
In [18]:
from fastecdsa.curve import secp256k1 as curve
In [19]:
# The generating point G
curve.G
Out[19]:
X: 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Y: 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
(On curve <secp256k1>)
In [20]:
# The coefficient a in y^2 = x^3 + ax + b
curve.a
Out[20]:
0
In [21]:
# The coefficient b in y^2 = x^3 + ax + b
curve.b
Out[21]:
7
In [705]:
# The number of elments in the underlying Galois field
curve.p
Out[705]:
115792089237316195423570985008687907853269984665640564039457584007908834671663
In [704]:
# The number of solutions (including the neutral element at infinity)
curve.q
Out[704]:
115792089237316195423570985008687907852837564279074904382605163141518161494337
In [714]:
from fastecdsa.curve import secp256k1 as curve
import fastecdsa.keys as keys
from mod import Mod

# every message needs to be hashed into a number
def encrypt_string(hash_str):
    return int(hashlib.sha256(hash_str.encode()).hexdigest(), 16)

# The private key is a random number from [1, p - 1] where
# p is the order of the underlying Galois field
private_key = keys.gen_private_key(curve)

# The public key is 
public_key = curve.G*private_key

# There are n solutions on the elliptic curve 
# including the point at "infinity"
n = curve.q

# We send the clear message...
message = "I love this lecture"

# nonce
i = keys.gen_private_key(curve)

# nonce on elliptic curve
P = curve.G*i

# compute the signature
r = Mod(P.x,n)
inv_i = Mod(i,n).inverse()
s = (inv_i*(encrypt_string(message)+r*private_key))._value
# The sender transmits (r,s), the clear message and his public key
# s depends on the private key and the hashcode of the message. 
# However it is not possible to extract the private key from s

# The receiver can now check whether the message is consistent
# This simple test returns False if
# - the text of the message has been changed.
# - if the sent public_key is consistent with  the private key 
#   of the sender, without ever revealing the private key

# check the signature
w = Mod(s,n).inverse()
u1 = encrypt_string(message)*w
u2 = r*w

# addition of two residue classes and multiplication with Point
(curve.G*u1 + public_key*u2).x == r
Out[714]:
True
In [719]:
# We can hide a lot of the complexity
from fastecdsa.curve import secp256k1 as curve
import fastecdsa.keys as keys
from hashlib import sha256

private_key = keys.gen_private_key(curve)
public_key = keys.get_public_key(private_key, curve)

# We send the clear message...
message = "I love this lecture"

# standard signature, returns two integers
r, s = ecdsa.sign(message, private_key, curve, hashfunc=sha256)

# should return True as the signature we just generated is valid.
valid = ecdsa.verify((r, s), message, public_key, curve, hashfunc=sha256)
assert valid

# output the signature
print(r)
print(s)
print(public_key)
92638279574439449367469751620279883526129614094420035354557226216594551995720
56150953375323829929699404540178501317383477984004211069133248276172762035017
X: 0xed9671d3d1e3b8ee77a887517a9a019829354474a8e080ca1524712f53153da1
Y: 0x268d62b89f2b0ad04a2e8a3f2d60c75c138d74c7ea387098e9537d0add89e39e
(On curve <secp256k1>)
In [ ]:
 
Notebooks AI
Notebooks AI Profile20060