-
Notifications
You must be signed in to change notification settings - Fork 0
/
identity.py
160 lines (131 loc) · 3.42 KB
/
identity.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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import binascii
import hashlib
import os
import sys
from ecdsa import SigningKey, VerifyingKey, curves
from ecdsa import ecdsa
from ecdsa import util as ecdsautil
DEFAULT_KEYTYPE = curves.NIST192p
def get_keys_folder(datafolder):
"""
:param datafolder:
:return:
"""
return os.path.join(datafolder, "keys")
def get_pub_keyfilename(datafolder):
"""
:param datafolder:
:return:
"""
keyfolder = get_keys_folder(datafolder)
return os.path.join(keyfolder, "identity.pub")
def get_priv_keyfilename(datafolder):
"""
:param datafolder:
:return:
"""
keyfolder = get_keys_folder(datafolder)
return os.path.join(keyfolder, "identity.priv")
def first_run(datafolder):
"""
Do our first run and generate keys
:param datafolder:
:return:
"""
keyfolder = get_keys_folder(datafolder)
if not os.path.exists(keyfolder):
os.makedirs(keyfolder)
if not os.path.isfile(get_priv_keyfilename(datafolder)):
key = genkey()
savekey(key, keyfolder, "identity")
sys.stderr.write("ident key generated\n")
def pubkeyhash(pubkey):
"""
Get a hash of a public key
:param pubkey:
:return:
"""
return hashlib.sha512(pubkey.to_der()).hexdigest()
def genkey():
"""
Generate an ECDSA key
:return:
"""
return SigningKey.generate(curve=DEFAULT_KEYTYPE)
def savekey(keypair, path, name):
"""
Save a keypair as PEM files
:param keypair:
:param path:
:param name:
:return:
"""
privname = os.path.join(path, name + ".priv")
pubname = os.path.join(path, name + ".pub")
with open(privname, "wb") as privfile:
privfile.write(keypair.to_pem())
with open(pubname, "wb") as pubfile:
pubfile.write(keypair.get_verifying_key().to_pem())
def load(privkeypem):
"""
Load a private key from disk
:param privkeypem:
:return:
"""
with open(privkeypem, "rb") as privfile:
return SigningKey.from_pem(privfile.read())
def loadpub(pubkeypem):
"""
Load a public key from a PEM file
:param pubkeypem:
:return:
"""
with open(pubkeypem, "rb") as pubfile:
return loadpubstr(pubfile.read())
def loadpubstr(pemstring):
"""
Load a public key from PEM string
:param pemstring:
:return:
"""
return VerifyingKey.from_pem(pemstring)
def get_pubkey(datafolder):
"""
Return the public key pem file
:param datafolder:
:return:
"""
filename = get_pub_keyfilename(datafolder)
if os.path.exists(filename):
with open(filename, "r") as filehandle:
return filehandle.read()
return None
def sign_string(privkey, message):
"""
Sign a string
:param privkey:
:param message:
:return:
"""
data = str(message)
sig = privkey.sign(data, hashfunc=hashlib.sha1, sigencode=ecdsautil.sigencode_der)
return binascii.hexlify(sig)
def verify_string(pubkey, signature, message):
"""
Verify
:param pubkey:
:param signature:
:param message:
:return:
"""
data = str(message)
signature = binascii.unhexlify(signature)
return pubkey.verify(signature, data, hashfunc=hashlib.sha1, sigdecode=ecdsautil.sigdecode_der)
def ecdh(privkey, pubkey):
"""
Given a loaded private key and a loaded public key, perform an ECDH exchange
:param privkey:
:param pubkey:
:return:
"""
return ecdsa.ecdh(privkey, pubkey)