33import hmac
44
55from .utils import (
6- HARDENED_INDEX , _derive_hardened_private_child ,
7- _derive_unhardened_private_child , _derive_public_child ,
8- _serialize_extended_key , _unserialize_extended_key ,
9- _hardened_index_in_path , _privkey_to_pubkey , _deriv_path_str_to_list
6+ HARDENED_INDEX ,
7+ _derive_hardened_private_child ,
8+ _derive_unhardened_private_child ,
9+ _derive_public_child ,
10+ _serialize_extended_key ,
11+ _unserialize_extended_key ,
12+ _hardened_index_in_path ,
13+ _privkey_to_pubkey ,
14+ _deriv_path_str_to_list ,
1015)
1116
1217
1318class PrivateDerivationError (ValueError ):
1419 """
1520 Tried to use a derivation requiring private keys, without private keys.
1621 """
22+
1723 pass
1824
1925
@@ -23,8 +29,16 @@ def __init__(self, message):
2329
2430
2531class BIP32 :
26- def __init__ (self , chaincode , privkey = None , pubkey = None , fingerprint = None ,
27- depth = 0 , index = 0 , network = "main" ):
32+ def __init__ (
33+ self ,
34+ chaincode ,
35+ privkey = None ,
36+ pubkey = None ,
37+ fingerprint = None ,
38+ depth = 0 ,
39+ index = 0 ,
40+ network = "main" ,
41+ ):
2842 """
2943 :param chaincode: The master chaincode, used to derive keys. As bytes.
3044 :param privkey: The master private key for this index (default 0).
@@ -81,11 +95,13 @@ def get_extended_privkey_from_path(self, path):
8195 chaincode , privkey = self .master_chaincode , self .master_privkey
8296 for index in path :
8397 if index & HARDENED_INDEX :
84- privkey , chaincode = \
85- _derive_hardened_private_child (privkey , chaincode , index )
98+ privkey , chaincode = _derive_hardened_private_child (
99+ privkey , chaincode , index
100+ )
86101 else :
87- privkey , chaincode = \
88- _derive_unhardened_private_child (privkey , chaincode , index )
102+ privkey , chaincode = _derive_unhardened_private_child (
103+ privkey , chaincode , index
104+ )
89105
90106 return chaincode , privkey
91107
@@ -121,18 +137,19 @@ def get_extended_pubkey_from_path(self, path):
121137 if _hardened_index_in_path (path ):
122138 for index in path :
123139 if index & HARDENED_INDEX :
124- key , chaincode = \
125- _derive_hardened_private_child (key , chaincode , index )
140+ key , chaincode = _derive_hardened_private_child (
141+ key , chaincode , index
142+ )
126143 else :
127- key , chaincode = \
128- _derive_unhardened_private_child (key , chaincode , index )
144+ key , chaincode = _derive_unhardened_private_child (
145+ key , chaincode , index
146+ )
129147 pubkey = _privkey_to_pubkey (key )
130148 # We won't need private keys for the whole path, so let's only use
131149 # public key derivation.
132150 else :
133151 for index in path :
134- pubkey , chaincode = \
135- _derive_public_child (pubkey , chaincode , index )
152+ pubkey , chaincode = _derive_public_child (pubkey , chaincode , index )
136153
137154 return chaincode , pubkey
138155
@@ -165,10 +182,14 @@ def get_xpriv_from_path(self, path):
165182 else :
166183 parent_pubkey = self .get_pubkey_from_path (path [:- 1 ])
167184 chaincode , privkey = self .get_extended_privkey_from_path (path )
168- extended_key = _serialize_extended_key (privkey , self .depth + len (path ),
169- parent_pubkey ,
170- path [- 1 ], chaincode ,
171- self .network )
185+ extended_key = _serialize_extended_key (
186+ privkey ,
187+ self .depth + len (path ),
188+ parent_pubkey ,
189+ path [- 1 ],
190+ chaincode ,
191+ self .network ,
192+ )
172193
173194 return base58 .b58encode_check (extended_key ).decode ()
174195
@@ -192,31 +213,41 @@ def get_xpub_from_path(self, path):
192213 else :
193214 parent_pubkey = self .get_pubkey_from_path (path [:- 1 ])
194215 chaincode , pubkey = self .get_extended_pubkey_from_path (path )
195- extended_key = _serialize_extended_key (pubkey , self .depth + len (path ),
196- parent_pubkey ,
197- path [- 1 ], chaincode ,
198- self .network )
216+ extended_key = _serialize_extended_key (
217+ pubkey ,
218+ self .depth + len (path ),
219+ parent_pubkey ,
220+ path [- 1 ],
221+ chaincode ,
222+ self .network ,
223+ )
199224
200225 return base58 .b58encode_check (extended_key ).decode ()
201226
202227 def get_master_xpriv (self ):
203228 """Get the encoded extended private key of the master private key"""
204229 if self .master_privkey is None :
205230 raise PrivateDerivationError
206- extended_key = _serialize_extended_key (self .master_privkey , self .depth ,
207- self .parent_fingerprint ,
208- self .index ,
209- self .master_chaincode ,
210- self .network )
231+ extended_key = _serialize_extended_key (
232+ self .master_privkey ,
233+ self .depth ,
234+ self .parent_fingerprint ,
235+ self .index ,
236+ self .master_chaincode ,
237+ self .network ,
238+ )
211239 return base58 .b58encode_check (extended_key ).decode ()
212240
213241 def get_master_xpub (self ):
214242 """Get the encoded extended public key of the master public key"""
215- extended_key = _serialize_extended_key (self .master_pubkey , self .depth ,
216- self .parent_fingerprint ,
217- self .index ,
218- self .master_chaincode ,
219- self .network )
243+ extended_key = _serialize_extended_key (
244+ self .master_pubkey ,
245+ self .depth ,
246+ self .parent_fingerprint ,
247+ self .index ,
248+ self .master_chaincode ,
249+ self .network ,
250+ )
220251 return base58 .b58encode_check (extended_key ).decode ()
221252
222253 @classmethod
@@ -229,11 +260,16 @@ def from_xpriv(cls, xpriv):
229260 raise InvalidInputError ("'xpriv' must be a string" )
230261
231262 extended_key = base58 .b58decode_check (xpriv )
232- (network , depth , fingerprint ,
233- index , chaincode , key ) = _unserialize_extended_key (extended_key )
263+ (
264+ network ,
265+ depth ,
266+ fingerprint ,
267+ index ,
268+ chaincode ,
269+ key ,
270+ ) = _unserialize_extended_key (extended_key )
234271 # We need to remove the trailing `0` before the actual private key !!
235- return BIP32 (chaincode , key [1 :], None , fingerprint , depth , index ,
236- network )
272+ return BIP32 (chaincode , key [1 :], None , fingerprint , depth , index , network )
237273
238274 @classmethod
239275 def from_xpub (cls , xpub ):
@@ -245,8 +281,14 @@ def from_xpub(cls, xpub):
245281 raise InvalidInputError ("'xpub' must be a string" )
246282
247283 extended_key = base58 .b58decode_check (xpub )
248- (network , depth , fingerprint ,
249- index , chaincode , key ) = _unserialize_extended_key (extended_key )
284+ (
285+ network ,
286+ depth ,
287+ fingerprint ,
288+ index ,
289+ chaincode ,
290+ key ,
291+ ) = _unserialize_extended_key (extended_key )
250292 return BIP32 (chaincode , None , key , fingerprint , depth , index , network )
251293
252294 @classmethod
@@ -255,6 +297,5 @@ def from_seed(cls, seed, network="main"):
255297
256298 :param seed: The seed as bytes.
257299 """
258- secret = hmac .new ("Bitcoin seed" .encode (), seed ,
259- hashlib .sha512 ).digest ()
300+ secret = hmac .new ("Bitcoin seed" .encode (), seed , hashlib .sha512 ).digest ()
260301 return BIP32 (secret [32 :], secret [:32 ], network = network )
0 commit comments