-
Notifications
You must be signed in to change notification settings - Fork 0
/
ecdsa.py
72 lines (63 loc) · 2.6 KB
/
ecdsa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import binascii as bs
import random
import elliptic
import hashlib
class Ecdsa:
@classmethod
def sign(cls, ec, message, privateNumber):
"""
This method signs messages through ECDSA Algorithm.
"""
# Calculate e = HASH(m). (Here HASH is a cryptographic hash function,
# SHA-256, with the output converted to an integer)
hashMessage_temp = cls.sha256(str(message))
hashMessage = ''.join(str(w) for w in hashMessage_temp)
# Convert string to HEXA representation
z = cls.stringToNumber(hashMessage)
r, s = 0, 0
curvePoint = None
while r == 0 or s == 0:
# Select a cryptographically secure random integer k from [1,n-1].
k = random.randint(1, ec.order - 1)
# Calculate the curve point (x1,y1) = k*G
curvePoint = ec.mul(ec.G, k)
# Calculate r = x1 mod n
r = curvePoint.x % ec.order
# Calculate s = k^{-1}*(z+rd) mod n
s = ((z + r * privateNumber) *
(elliptic.inv(k, ec.order))) % ec.order
# The signature is the pair (r,s) if r = 0 or s = 0 repeat the proccess
signature = [r, s]
return signature
@classmethod
def verify(cls, ec, message, signature, publicKey):
"""
This method verifies messages through ECDSA Algorithm.
"""
# Calculate e = HASH(m), where HASH is the same function used in the signature generation.
hashMessage_temp = cls.sha256(str(message))
hashMessage = ''.join(str(w) for w in hashMessage_temp)
# Convert string to HEXA representation
z = cls.stringToNumber(hashMessage)
sigR = signature[0]
sigS = signature[1]
# Calculate invert of s for later calculations
inv = elliptic.inv(sigS, ec.order)
# Calculate u1 = zs^{-1}mod n
u1 = (z * inv) % ec.order
# Calculate u2 = rs^{-1}mod n
u2 = (sigR * inv) % ec.order
# Calculate u1*G
u1_res = ec.mul(ec.G, u1)
# Calculate u2*Qa
u2_res = ec.mul(publicKey, u2)
# Calculate the curve point (x1,y1) = u1*G+ u2*Qa
add = ec.add(u1_res, u2_res)
# The signature is valid if r mod n = x_mod n, invalid otherwise.
return sigR % ec.order == add.x % ec.order
@classmethod
def stringToNumber(cls, string):
return int(bs.hexlify(str.encode(string)), 16)
@classmethod
def sha256(cls, input_string):
return hashlib.sha256(str(input_string).encode('utf-8')).hexdigest()