OSDN Git Service

fix bug
[bytom/bytom-kit.git] / app / model / key.py
1 import random
2 import hashlib
3 import pbkdf2
4 import hmac
5 import ed25519
6 from app.model.signature import *
7
8 # create_key create 128 bits entropy
9 def create_entropy():
10     hex_str = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"]
11     entropy_str = ""
12     for _ in range(32):
13         # create interger in range [1,15]
14         num = random.randint(0,15)
15         entropy_str += hex_str[num]
16
17     return entropy_str
18
19
20 # entropy_to_mnemonic create mnemonic from 128 bits entropy(the entropy_str length is 32)
21 # return 12 mnemonics
22 # verify or get more test data, please ref: https://gist.github.com/zcc0721/63aeb5143807950f7b7051fadc08cef0
23 # test data 1:
24 #   entropy_str: 1db8b283eb4623e749732a341396e0c9
25 #   mnemonic_str: buffalo sheriff path story giraffe victory chair grab cross original return napkin
26 # test data 2:
27 #   entropy_str: 4d33735a9e92f634d22aecbb4044038d
28 #   mnemonic_str: essay oppose stove diamond control bounce emerge frown robust acquire abstract brick
29 # test data 3:
30 #   entropy_str: 089fe9bf0cac76760bc4b131d938669e
31 #   mnemonic_str: ancient young hurt bone shuffle deposit congress normal crack six boost despair
32 def entropy_to_mnemonic(entropy_str):
33     mnemonic_str = ""
34     mnemonic_length = 12
35
36     # create a 12 elements mnemonic_list 
37     mnemonic_list = []
38     for _ in range(mnemonic_length):
39         mnemonic_list.append('')
40
41     entropy_bytes = bytes.fromhex(entropy_str)
42     checksum = hashlib.sha256(entropy_bytes).hexdigest()[:1]
43     new_entropy_str = "0" + entropy_str + checksum
44     new_entropy_bytes = bytes.fromhex(new_entropy_str)
45     new_entropy_int = int.from_bytes(new_entropy_bytes, byteorder='big')
46
47     file = open('./app/model/english_mnemonic.txt', mode='r')
48     word_list = file.readlines()
49     file.close()
50
51     for i in range(11, -1, -1):
52         word_index = new_entropy_int % 2048
53         new_entropy_int = new_entropy_int >> 11
54         mnemonic_list[i] = word_list[word_index]
55
56     for i in range(12):
57         mnemonic_str += mnemonic_list[i][:-1]
58         mnemonic_str += " "
59
60     return mnemonic_str[:-1]
61
62
63 # mnemonic_to_seed create seed from mnemonic
64 # You can find more details from: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#from-mnemonic-to-seed
65 # You can verify or get more test data from: https://gist.github.com/zcc0721/4918e891073a9ca6c444ec7490298e82
66 # test data 1:
67 #   mnemonic_str: ancient young hurt bone shuffle deposit congress normal crack six boost despair
68 #   seed_str: afa3a86bbec2f40bb32833fc6324593824c4fc7821ed32eac1f762b5893e56745f66a6c6f2588b3d627680aa4e0e50efd25065097b3daa8c6a19d606838fe7d4
69 # test data 2:
70 #   mnemonic_str: rich decrease live pluck friend recipe burden minor similar agent tired horror
71 #   seed_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f
72 # test data 3:
73 #   mnemonic_str: enough ginger just mutual fit trash loop mule peasant lady market hub
74 #   seed_str: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f4af1be7b8d71cc649ac4ca3816f9ccaf11bf49f4effb845f3c19e16eaf8bfcda
75 def mnemonic_to_seed(mnemonic_str):
76     password_str = mnemonic_str
77     salt_str = "mnemonic"
78     seed_str = pbkdf2.PBKDF2(password_str, salt_str, iterations=2048, digestmodule=hashlib.sha512, macmodule=hmac).hexread(64)
79
80     return seed_str
81
82
83 # s_str must be >= 32 bytes long and gets rewritten in place.
84 # This is NOT the same pruning as in Ed25519: it additionally clears the third
85 # highest bit to ensure subkeys do not overflow the second highest bit.
86 def prune_root_scalar(s_str):
87     s_0_int = int.from_bytes(bytes.fromhex(s_str[0:2]), byteorder='big') & 248
88     s_0_str = "%0.2x" % s_0_int
89     new_s_str = s_0_str + s_str[2:]
90     s_31_int = int.from_bytes(bytes.fromhex(new_s_str[62:64]), byteorder='big') & 31
91     s_31_str = "%0.2x" % s_31_int
92     new_s_str = new_s_str[:62] + s_31_str + new_s_str[64:]
93     s_31_int = int.from_bytes(bytes.fromhex(new_s_str[62:64]), byteorder='big') | 64
94     s_31_str = "%0.2x" % s_31_int
95     new_s_str = new_s_str[:62] + s_31_str + new_s_str[64:]
96     
97     return new_s_str
98
99
100 # seed_to_root_xprv create rootxprv from seed
101 # seed_str length is 512 bits.
102 # root_xprv length is 512 bits.
103 # You can verify or get more test data from: https://gist.github.com/zcc0721/0aa1b971f4bf93d8f67e25f57b8b97ee
104 # test data 1:
105 #   seed_str: afa3a86bbec2f40bb32833fc6324593824c4fc7821ed32eac1f762b5893e56745f66a6c6f2588b3d627680aa4e0e50efd25065097b3daa8c6a19d606838fe7d4
106 #   root_xprv_str: 302a25c7c0a68a83fa043f594a2db8b44bc871fced553a8a33144b31bc7fb84887c9e75915bb6ba3fd0b9f94a60b7a5897ab9db6a48f888c2559132dba9152b0
107 # test data 2:
108 #   seed_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f
109 #   root_xprv_str: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946d478b61cc6be936f367ae769eb1dc65c473ee73cac2eb43cf6d5e7c62b7f0062
110 # test data 3:
111 #   seed_str: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f4af1be7b8d71cc649ac4ca3816f9ccaf11bf49f4effb845f3c19e16eaf8bfcda
112 #   root_xprv_str: a01d6b741b0e74b8d0836ac22b675bbf8e108148ef018d1b000aef1a899a134bd316c0f59e7333520ae1a429504073b2773869e95aa95bb3a4fa0ec76744025c
113 def seed_to_root_xprv(seed_str):
114     hc_str = hmac.HMAC(b'Root', bytes.fromhex(seed_str), digestmod=hashlib.sha512).hexdigest()
115     root_xprv_str = prune_root_scalar(hc_str[:64]) + hc_str[64:]
116
117     return root_xprv_str
118
119
120 ##################################################
121 # def xprv_to_xpub(xprv_str):
122 # private_key = ed25519.SigningKey(bytes.fromhex(xprv_str[:64]))
123 # public_key = private_key.get_verifying_key().to_ascii(encoding='hex')
124 # xpub_str = public_key.decode() + xprv_str[64:]
125 #     return xpub_str
126 ##################################################
127
128
129 # def xprv_to_child_xprv(xprv_str, path_str):
130 #     child_xprv_str = xprv_str
131 #     return child_xprv_str
132
133 # xprv_to_expanded_private_key create expanded private key from xprv
134 # You can verify or get more test data from: https://gist.github.com/zcc0721/ef0bf2e69f5e92b29d716981f2a8fe7d
135 # test data 1:
136 #   xprv_str: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50e231e65bd97048850ae6c39d0f46b63ae70aa24f5aac7877727c430c2201e6d6
137 #   expanded_private_key_str_xprv: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50d828bf44b1a109c2bbb4c72685858e2f2ab8b405beef1e4ecc12d1ed8511e8eb
138 # test data 2:
139 #   xprv_str: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946d478b61cc6be936f367ae769eb1dc65c473ee73cac2eb43cf6d5e7c62b7f0062
140 #   expanded_private_key_str_xprv: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946ddbb71e7a76595c6bc24937d76085d24315713764cbdf1364ab9091953009cd8
141 # test data 3:
142 #   xprv_str: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e114300c0a162d41c0cdf196d61f4492f546e50bfff253b9d5d930d1bb89197cd333d
143 #   expanded_private_key_str_xprv: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e11432787f5e10f9598f80fb41e4a648b609463c06e625641366f3279658b2b0f5268
144 def xprv_to_expanded_private_key(xprv_str):
145     hc_str = hmac.HMAC(b'Expand', bytes.fromhex(xprv_str), digestmod=hashlib.sha512).hexdigest()
146     expanded_private_key_str = xprv_str[:64] + hc_str[64:]
147
148     return expanded_private_key_str
149
150
151 # xpub_to_public_key create 32 bytes public key from xpub
152 # xpub length is 64 bytes.
153 # You can verify or get more test data from: https://gist.github.com/zcc0721/9e10f2fa5bd0c8f33aa6dfc87f6aa856
154 # test data 1:
155 #   xpub_str: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f4af1be7b8d71cc649ac4ca3816f9ccaf11bf49f4effb845f3c19e16eaf8bfcda
156 #   public_key_str: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f
157 # test data 2:
158 #   xpub_str: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50e231e65bd97048850ae6c39d0f46b63ae70aa24f5aac7877727c430c2201e6d6
159 #   public_key_str: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50
160 # test data 3:
161 #   xpub_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f
162 #   public_key_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1d
163 def xpub_to_public_key(xpub_str):
164     public_key_str = xpub_str[:64]
165
166     return public_key_str
167
168
169 # def xprv_sign(xprv_str, message_str):
170 #     expanded_private_key = xprv_to_expanded_private_key(xprv_str)
171
172 #     return signature_str
173     
174
175 # xpub_verify verify signature
176 # xpub_str length is 64 bytes.
177 # message_str length is variable.
178 # signature_str length is 64 bytes.
179 # You can verify or get more test data from: https://gist.github.com/zcc0721/61a26c811a632623678e274cc7e5c10b
180 # test data 1:
181 #   xprv_str: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
182 #   xpub_str: 1b0541a7664cee929edb54d9ef21996b90546918a920a77e1cd6015d97c56563d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
183 #   message_str: a6ce34eec332b32e42ef3407e052d64ac625da6f
184 #   signature_str: f02f5bb22d8b32f14e88059a786379c26256892f45cf64770c844d0c5de2e52c00307b7bb25fcbb18be13c339a2f511a7c015a8cf81ac681052efe8e50eff00e
185 # test data 2:
186 #   xprv_str: 008ce51e3b52ee03eb0ad96c55eb5c9fe8736410518b585a0b7f35b2ab48d24c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90
187 #   xpub_str: ead6415a077b91aa7de32e1cf63350f9351d0298f5accc2cf92ef9429bd1f86c166364ce19322721b7dec84442c3665d97d0e995ba4d01c0f4b19b841379ac90
188 #   message_str: 68656c6c6f206279746f6d      # value is: 'hello bytom'
189 #   signature_str: 1cc6b0f4031352ffd7a62540f13edddaaebf2df05db7a4926df5513129a8e85dcff1324545a024b16f958239ea67840ced3c2d57bb468dbf0e6cf1d1075f0b0f
190 # test data 3:
191 #   xprv_str: 88c0c40fb54ef9c1b90af8cce8dc4c9d54f915074dde93f79ab61cedae03444101ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b
192 #   xpub_str: cb22ce197d342d6bb440b0bf13ddd674f367275d28a00f893d7f0b10817690fd01ff37ac4a07869214c2735bba0175e001abe608db18538e083e1e44430a273b
193 #   message_str: 1246b84985e1ab5f83f4ec2bdf271114666fd3d9e24d12981a3c861b9ed523c6
194 #   signature_str: ab18f49b23d03295bc2a3f2a7d5bb53a2997bed733e1fc408b50ec834ae7e43f7da40fe5d9d50f6ef2d188e1d27f976aa2586cef1ba00dd098b5c9effa046306
195 def xpub_verify(xpub_str, message_str, signature_str):
196     result = False
197     result = verify(xpub_to_public_key(xpub_str), signature_str, message_str)
198
199     return result