-
Notifications
You must be signed in to change notification settings - Fork 0
/
library.py
88 lines (69 loc) · 2.99 KB
/
library.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from os import urandom # Should be a good source of entropy
import json
import coincurve # faster than ecdsa to compute public key from private key
import ed25519
"""
Low-level tools to deal with private key, public key
and address
"""
################## General tools #############
max_32bitvalue = 0xffffffff
def curveorder(algorithm='ecdsa-secp256k1'):
if(algorithm=='ecdsa-secp256k1'):
# max val of the secp256k1 eliptic curve
maxval=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
elif(algorithm=='ed25519'):
# max val of the ed25519 eliptic curve
maxval = 2**252 + 27742317777372353535851937790883648493
return maxval
def gen_private_key(algorithm='ecdsa-secp256k1'):
# max value of the eliptic curve
maxval = curveorder(algorithm=algorithm)
p = urandom(32) # almost any 32 random bytes array is a private key
pint = int.from_bytes(p,'big')
while(pint>maxval or pint<0): # a private key cannot be zero (or below)
# and should be lower than the maximal value of the eliptic curve
p = urandom(32)
pint = int.from_bytes(p,'big')
return p
def priv_to_pub(key,compressed=True,algorithm='ecdsa-secp256k1'):
if(algorithm=='ecdsa-secp256k1'):
return coincurve.PublicKey.from_secret(key).format(compressed=compressed)
elif(algorithm=='ed25519'):
return ed25519.SigningKey(key).get_verifying_key().to_bytes()
def priv_to_pub_raw(key): # only for ecdsa-secp256k1 curve
return priv_to_pub(key,compressed=False)[1:]
def pub_to_pub(pub,compressed=True):
return coincurve.PublicKey(pub).format(compressed=compressed)
def pub_from_signature(signature, message, curve='ecdsa-secp256k1'):
if(curve == 'ecdsa-secp256k1'):
public_key = coincurve.PublicKey.from_signature_and_message(signature, message.encode()).format()
return public_key
else:
return "not available yet"
class Account:
def __init__(self,private=None,algorithm='ecdsa-secp256k1'):
if(private is None): # need to check type of input (bytes only)
private=gen_private_key(algorithm=algorithm)
self.pk = private
self.curve = algorithm
@classmethod
def fromhex(cls, hexa): # need to check type of input (str only)
return cls(bytes.fromhex(hexa))
@classmethod
def fromfile(cls, file_name):
with open(file_name) as json_file:
data = json.load(json_file)
return cls.fromhex(data["private_key"])
def private_key(self):
return self.pk.hex()
def to_file(self, file_name):
key = {"private_key": self.private_key()}
with open(file_name, 'w') as key_file:
json.dump(key, key_file)
def sign(self,message):
if(self.curve == 'ecdsa-secp256k1'):
signature = coincurve.PrivateKey(self.pk).sign(message.encode())
else:
signature = ed25519.SigningKey(self.pk).sign(message.encode())
return signature