OSDN Git Service

52f2d035995ac6c26a0d2792e25a4d7019548222
[bytom/bytom-kit.git] / app / model / key_gm.py
1 import hmac
2 import hashlib
3 from gmssl import sm2, func
4 import random
5 from app.model import pn
6
7 # get_gm_root_xprv create rootxprv from seed
8 # seed_str length is 512 bits.
9 # root_xprv length is 512 bits.
10 # You can get more test data from: https://gist.github.com/zcc0721/8bfc1e1c92b7cd9f00743d6878097809
11 # test data 1:
12 #   seed_str: ecc2bbb6c0492873cdbc81edf56bd896d3b644047879840e357be735b7fa7b6f4af1be7b8d71cc649ac4ca3816f9ccaf11bf49f4effb845f3c19e16eaf8bfcda
13 #   root_xprv_str: a61d6b741b0e74b8d0836ac22b675bbf8e108148ef018d1b000aef1a899a136bd316c0f59e7333520ae1a429504073b2773869e95aa95bb3a4fa0ec76744025c
14 # test data 2:
15 #   seed_str: afa3a86bbec2f40bb32833fc6324593824c4fc7821ed32eac1f762b5893e56745f66a6c6f2588b3d627680aa4e0e50efd25065097b3daa8c6a19d606838fe7d4
16 #   root_xprv_str: 302a25c7c0a68a83fa043f594a2db8b44bc871fced553a8a33144b31bc7fb88887c9e75915bb6ba3fd0b9f94a60b7a5897ab9db6a48f888c2559132dba9152b0
17 # test data 3:
18 #   seed_str: b435f948bd3748ede8f9d6f59728d669939e79c6c885667a5c138e05bbabde1de0dcfcbe0c6112022fbbf0da522f4e224a9c2381016380688b51886248b3156f
19 #   root_xprv_str: 6532adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb29469e6d478b61cc6be936f367ae769eb1dc65c473ee73cac2eb43cf6d5e7c62b7f0062
20 def get_gm_root_xprv(seed_str):
21     hc_str = hmac.HMAC(b'Root', bytes.fromhex(seed_str), digestmod=hashlib.sha512).hexdigest()
22     root_xprv_str = hc_str
23     return {
24         "root_xprv": root_xprv_str
25     }
26
27
28 # get_gm_xpub derives new xpub from xprv
29 # xprv length is 64 bytes.
30 # xpub length is 65 bytes.
31 # You can get more test data from: https://gist.github.com/zcc0721/9e5761e6a924cce3aa7cf7f72721218a
32 # test data 1:
33 #   xprv_str: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
34 #   xpub_str: 02476044353971ae0ed41cba76f27d0bd2e09d09db5c238bb74f69569bf343f742d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
35 # test data 2:
36 #   xprv_str: 36667587de27eec684fc4b222276f22a24d9a82e947ee0119148bedd4dec461dd4e1b1d95dfb0f78896677ea1026af7510b41fabd3bd5771311c0cb6968337b2
37 #   xpub_str: 0396a36cd902db56eca016c213a8ac25de35a7afd78061351f1898529f0956c22ed4e1b1d95dfb0f78896677ea1026af7510b41fabd3bd5771311c0cb6968337b2
38 # test data 3:
39 #   xprv_str: 74a49c698dbd3c12e36b0b287447d833f74f3937ff132ebff7054baa18623c35a705bb18b82e2ac0384b5127db97016e63609f712bc90e3506cfbea97599f46f
40 #   xpub_str: 03cafbdedea4a639d31fe4c257f1bb58303359be1a00b9f90b5c605f57e4308ed1a705bb18b82e2ac0384b5127db97016e63609f712bc90e3506cfbea97599f46f
41 def get_gm_xpub(xprv_str):
42     private_key_int = int(xprv_str[:64], 16)
43     sm2_crypt = sm2.CryptSM2(private_key=xprv_str[:64], public_key="")
44     public_key_str = sm2_crypt._kg(private_key_int, sm2.default_ecc_table['g'])
45     pc = '0' + str(int(public_key_str[-1], 16) % 2 + 2)
46     xpub_str = pc + public_key_str[:64] + xprv_str[64:]
47     return {
48         "xpub": xpub_str
49     }
50
51
52 # get_gm_xprv create expanded private key from xprv
53 # You can get more test data from: https://gist.github.com/zcc0721/ef0bf2e69f5e92b29d716981f2a8fe7d
54 # test data 1:
55 #   xprv_str: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50e231e65bd97048850ae6c39d0f46b63ae70aa24f5aac7877727c430c2201e6d6
56 #   expanded_private_key_str_xprv: 406c82307bf7978d17f3ecfeea7705370e9faef2027affa86c8027c6e11a8a50d828bf44b1a109c2bbb4c72685858e2f2ab8b405beef1e4ecc12d1ed8511e8eb
57 # test data 2:
58 #   xprv_str: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946d478b61cc6be936f367ae769eb1dc65c473ee73cac2eb43cf6d5e7c62b7f0062
59 #   expanded_private_key_str_xprv: 6032adeb967ac5ccbf988cf8190817bf9040c8cfd9cdfe3d5e400effb2946946ddbb71e7a76595c6bc24937d76085d24315713764cbdf1364ab9091953009cd8
60 # test data 3:
61 #   xprv_str: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e114300c0a162d41c0cdf196d61f4492f546e50bfff253b9d5d930d1bb89197cd333d
62 #   expanded_private_key_str_xprv: 509a095ad862322641b8d66e84561aae1d4816045167e2c4dfadf464928e11432787f5e10f9598f80fb41e4a648b609463c06e625641366f3279658b2b0f5268
63 def get_gm_xprv(xprv_str):
64     hc_str = hmac.HMAC(b'Expand', bytes.fromhex(xprv_str), digestmod=hashlib.sha512).hexdigest()
65     expanded_private_key_str = xprv_str[:64] + hc_str[64:]
66     return {
67         "expanded_private_key": expanded_private_key_str
68     }
69
70
71 # get_gm_public_key create 33 bytes public key from xpub
72 # xpub length is 65 bytes.
73 # You can get more test data from: https://gist.github.com/zcc0721/e159677bf776fe0209bca5b890cb87c3
74 # test data 1:
75 #   xpub_str: 03c74f3a946940d43e0f8c6da40680c0078e6e1008ca6ea869d57536c31b7ede20adc168c3698fa538fa587c4e519d1eb7a2593f178bfe0c93890a0f09e1634607
76 #   public_key_str: 03c74f3a946940d43e0f8c6da40680c0078e6e1008ca6ea869d57536c31b7ede20
77 # test data 2:
78 #   xpub_str: 02914d51fcc3b90a87ffe3424995a9db8757a9d67812edd85207c47edc9f7f34e368684ae4d706f68c710fe1dbd20d73a8faaaf34966678a5d58486ac193a851ca
79 #   public_key_str: 02914d51fcc3b90a87ffe3424995a9db8757a9d67812edd85207c47edc9f7f34e3
80 # test data 3:
81 #   xpub_str: 03603b2eb079257513d253a92ad45ce5ef12cc285dd8c13fc77c95844468f5eb4482f33c577c3a71ac733136b17d68b65a184b225431ab658555735e436fdb13e6
82 #   public_key_str: 03603b2eb079257513d253a92ad45ce5ef12cc285dd8c13fc77c95844468f5eb44
83 def get_gm_public_key(xpub_str):
84     public_key_str = xpub_str[:66]
85     return {
86         "public_key": public_key_str
87     }
88
89
90 # get_gm_child_xprv create new xprv through the path
91 # xprv_str length is 64 bytes.
92 # path_list item is hex string.
93 # child_xprv length is 64 bytes.
94 # You can get more test data from: https://gist.github.com/zcc0721/db45d25d3432806ff33dcd87f694588b
95 # test data 1:
96 #   xprv_str: 10fdbc41a4d3b8e5a0f50dd3905c1660e7476d4db3dbd9454fa4347500a633531c487e8174ffc0cfa76c3be6833111a9b8cd94446e37a76ee18bb21a7d6ea66b
97 #   path_list: 010400000000000000
98 #   path_list: 0100000000000000
99 #   child_xprv_str: 042f319fc7ae020937c0191294f6298b07e0f2acd01621f3ba25b2edc51b5098fde8c077dc7110da22251db1779b9a36fd92acbf559ef6fb170126074453f0a2
100 # test data 2:
101 #   xprv_str: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
102 #   path_list: 00
103 #   path_list: 00
104 #   child_xprv_str: 838159f7bcad836cc0bb5727eb446e5b989c90dd6084c723746188e84f8405f2f305b60bd191053e84aac16a91380dd67889b203c3f920a5ef06b2cb03cc0ae7
105 # test data 3:
106 #   xprv_str: c003f4bcccf9ad6f05ad2c84fa5ff98430eb8e73de5de232bc29334c7d074759d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
107 #   path_list: 010203
108 #   path_list: 7906a1
109 #   child_xprv_str: ff7fc1c5a34fbeb739f8ac77ea7728685e7a9c29048e16bde69112ecff4a9aad4f9ee5721fce2d638071bcc1e2ee7ba470cb49d6356fdcf24127a28c09558b55
110 def get_gm_child_xprv(xprv_str, path_list):
111     for i in range(len(path_list)):
112         selector_bytes = bytes.fromhex(path_list[i])
113         xpub_str = get_gm_xpub(xprv_str)['xpub']
114         xpub_bytes = bytes.fromhex(xpub_str)
115         xprv_bytes = bytes.fromhex(xprv_str)
116         hc_bytes = hmac.HMAC(xpub_bytes[33:], b'N'+xpub_bytes[:33]+selector_bytes, digestmod=hashlib.sha512).digest()
117         left_int = int(hc_bytes[:32].hex(), 16)
118         private_key_int = int(xprv_bytes[:32].hex(), 16)
119         sm2_n_str = 'FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123'
120         sm2_n_int = int(sm2_n_str, 16)
121         child_key_int = (left_int + private_key_int) % sm2_n_int
122         child_key_str = (child_key_int).to_bytes(32, byteorder='big').hex()
123         xprv_str = child_key_str + hc_bytes[32:].hex()
124     child_xprv_str = xprv_str
125     return {
126         "child_xprv": child_xprv_str
127     }
128
129
130 # decompress_public_key calculate y 
131 # dec_pubkey_str length is 33 bytes.
132 # You can get more test data from: https://gist.github.com/zcc0721/e2cb1643e9580230354e3c11e99222b6
133 # test data 1:
134 #   xpub_str: 02e097442c49eccae999f7687e088c918838df8d804980a220dba6bd7a51258e76347a32ad977251122e50456dcfe155d80cbfa83186a64f7756f044a126e664ac
135 #   y_str: f8ac4140ec52355bc699e3b21a87d7824db5443f33641aed14e2e603491b43b4
136 # test data 2:
137 #   xpub_str: 02476044353971ae0ed41cba76f27d0bd2e09d09db5c238bb74f69569bf343f742d513bc370335cac51d77f0be5dfe84de024cfee562530b4d873b5f5e2ff4f57c
138 #   y_str: 76d809326d28a80900db49341731ef43c2791d8ef34d98803252a47fbb0b4e96
139 # test data 3:
140 #   xpub_str: 03c74f3a946940d43e0f8c6da40680c0078e6e1008ca6ea869d57536c31b7ede20adc168c3698fa538fa587c4e519d1eb7a2593f178bfe0c93890a0f09e1634607
141 #   y_str: 4c12dc51fed482f03b277163fe551178f5a7059e8384236c9e4e614b90afeee1
142 def decompress_public_key(dec_pubkey_str):
143     p_int = int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
144     a_int = int('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
145     b_int = int('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
146     x_int = int(dec_pubkey_str[2:66], 16)
147     ysq = (x_int **3 + a_int * x_int + b_int) % p_int
148     y1, y2 = pn.sqrt2(ysq, p_int)
149     if y1 & 1 == 1:
150         y1, y2 = y2, y1
151     if dec_pubkey_str[:2] == '02':
152         y = y1
153     else:
154         y = y2
155     y_str = (y).to_bytes(32, byteorder='big').hex()
156     return y_str
157
158
159 # get_gm_child_xpub create new xpub through the path
160 # xpub_str length is 65 bytes.
161 # path_list item is hex string.
162 # child_xpub length is 65 bytes.
163 # You can get more test data from: https://gist.github.com/zcc0721/cc3eebe44dd4d0d613c29722c52f6e13
164 # test data 1:
165 #   xpub_str: 02e097442c49eccae999f7687e088c918838df8d804980a220dba6bd7a51258e76347a32ad977251122e50456dcfe155d80cbfa83186a64f7756f044a126e664ac
166 #   path_list: 010400000000000000
167 #   path_list: 0100000000000000
168 #   child_xpub_str: 031b17412e15f1120527104ba0643baf33f801048cccbbed848c460881d764daa71c467a603109348cd52ce3404db12c4991e3d93727430457a0d483b08b53731f
169 # test data 2:
170 #   xpub_str: 02e097442c49eccae999f7687e088c918838df8d804980a220dba6bd7a51258e76347a32ad977251122e50456dcfe155d80cbfa83186a64f7756f044a126e664ac
171 #   path_list: 00
172 #   path_list: 00
173 #   child_xpub_str: 02c616c84c8ad467f013ea6a7ae8f362b0944e0339a7ff844e0976f31ff83a9e7c9b353e3405fb6810167c105a98878d1ece351f4c4ee02b72c26afe56dd57074f
174 # test data 3:
175 #   xpub_str: 03603b2eb079257513d253a92ad45ce5ef12cc285dd8c13fc77c95844468f5eb4482f33c577c3a71ac733136b17d68b65a184b225431ab658555735e436fdb13e6
176 #   path_list: 00010203
177 #   child_xpub_str: 02d49feae4abd8e18b17e0393374b57413abfe451edbbe92c2a9fa6718078eafac854b0299bf682052e4a5783d71463571a5e403243e7ab9cf11826d282534b0f3
178 # test data 4:
179 #   xpub_str: 02e097442c49eccae999f7687e088c918838df8d804980a220dba6bd7a51258e76347a32ad977251122e50456dcfe155d80cbfa83186a64f7756f044a126e664ac
180 #   path_list: 00010203
181 #   path_list: 03ededed
182 #   path_list: 123456
183 #   child_xpub_str: 022a1e261ff45010b7107f621d9ad7db584322948d90e5042e07f2b143ec4a1bd4da193b6c9a88cf221769e16f090e20e46a465a624b9706b99720fe08135937a7
184 # test data 5:
185 #   xpub_str: 03603b2eb079257513d253a92ad45ce5ef12cc285dd8c13fc77c95844468f5eb4482f33c577c3a71ac733136b17d68b65a184b225431ab658555735e436fdb13e6
186 #   path_list: 010203
187 #   path_list: 7906a1
188 #   child_xpub_str: 0344977d5e874e50f320d4616e452468bc98fad2f855c551d0aaaedb0e1ab67f0122b808dc54075b096ef54e3fd742f8a5fd459ebb0eea95349631b3a133089ef3
189 def get_gm_child_xpub(xpub_str, path_list):
190     for i in range(len(path_list)):
191         selector_bytes = bytes.fromhex(path_list[i])
192         xpub_bytes = bytes.fromhex(xpub_str)
193         hc_str = hmac.HMAC(xpub_bytes[33:], b'N'+xpub_bytes[:33]+selector_bytes, digestmod=hashlib.sha512).hexdigest()
194         Il_int = int(hc_str[:64], 16)
195         sm2_crypt = sm2.CryptSM2(private_key="", public_key="")
196         public_key_str = sm2_crypt._kg(Il_int, sm2.default_ecc_table['g'])
197         par_public_key_str = xpub_str[2:66] + decompress_public_key(xpub_str[:66])
198         child_public_key_str = sm2_crypt._add_point(public_key_str, par_public_key_str)
199         child_public_key_str = sm2_crypt._convert_jacb_to_nor(child_public_key_str)
200         if int(child_public_key_str[:], 16) & 1 == 0:
201             xpub_str = "02" + child_public_key_str[:64] + hc_str[64:]
202         else:
203             xpub_str = "03" + child_public_key_str[:64] + hc_str[64:]
204     child_xpub_str = xpub_str
205     return {
206         "child_xpub": child_xpub_str
207     }
208
209
210
211 # def gm_xprv_sign(xprv_str, message_str):
212 #     sm2_crypt = sm2.CryptSM2(private_key=xprv_str[:64], public_key="")
213 #     K = random.randint(0, 2**256)
214 #     K_str = K.to_bytes(32, byteorder='big').hex()
215 #     data = bytes.fromhex(message_str)
216 #     sig = sm2_crypt.sign(data, K_str)
217 #     return sig
218 #     # print(sig)
219 #     # xprv_str = get_gm_xprv(xprv_str)['expanded_private_key']
220 #     # xprv_bytes = bytes.fromhex(xprv_str)
221 #     # message_bytes = bytes.fromhex(message_str)
222 #     # data_bytes = xprv_bytes[32:64]
223
224
225 # def gm_xpub_verify(xpub_str, message_str, signature_str):
226 #     public_key = xpub_str[:66]
227 #     result = False
228 #     sm2_crypt = sm2.CryptSM2(private_key="", public_key=public_key)
229 #     data = bytes.fromhex(message_str)
230 #     result = sm2_crypt.verify(signature_str, data)
231 #     return {
232 #         "result": result
233 #     }