move coin privkey bytes derivation to derive.py
This commit is contained in:
parent
c8f4e0c050
commit
2e1f3b93e4
4 changed files with 73 additions and 24 deletions
|
|
@ -210,7 +210,6 @@ class AddrList(MMGenObject): # Address info for a single seed ID
|
|||
(chk,rec)[record] )
|
||||
|
||||
def generate(self,seed,addr_idxs):
|
||||
assert type(addr_idxs) is AddrIdxList
|
||||
|
||||
seed = self.scramble_seed(seed.data)
|
||||
dmsg_sc('seed',seed[:8].hex())
|
||||
|
|
@ -227,31 +226,24 @@ class AddrList(MMGenObject): # Address info for a single seed ID
|
|||
if self.add_p2pkh:
|
||||
ag2 = AddrGenerator( self.proto, 'compressed' )
|
||||
|
||||
t_addrs,out = ( len(addr_idxs), AddrListData() )
|
||||
le = self.entry_type
|
||||
num,pos = (0,0)
|
||||
|
||||
from hashlib import sha256,sha512
|
||||
from .globalvars import g
|
||||
from .derive import derive_coin_privkey_bytes
|
||||
|
||||
while pos != t_addrs:
|
||||
seed = sha512(seed).digest()
|
||||
num += 1 # round
|
||||
t_addrs = len(addr_idxs)
|
||||
le = self.entry_type
|
||||
out = AddrListData()
|
||||
CR = '\n' if g.debug_addrlist else '\r'
|
||||
|
||||
if num != addr_idxs[pos]:
|
||||
continue
|
||||
|
||||
pos += 1
|
||||
for pk_bytes in derive_coin_privkey_bytes(seed,addr_idxs):
|
||||
|
||||
if not g.debug:
|
||||
qmsg_r(f'\rGenerating {self.gen_desc} #{num} ({pos} of {t_addrs})')
|
||||
qmsg_r(f'{CR}Generating {self.gen_desc} #{pk_bytes.idx} ({pk_bytes.pos} of {t_addrs})')
|
||||
|
||||
e = le(proto=self.proto,idx=num)
|
||||
e = le( proto=self.proto, idx=pk_bytes.idx )
|
||||
|
||||
# Secret key is double sha256 of seed hash round /num/
|
||||
e.sec = PrivKey(
|
||||
self.proto,
|
||||
sha256(sha256(seed).digest()).digest(),
|
||||
pk_bytes.data,
|
||||
compressed = mmtype.compressed,
|
||||
pubkey_type = mmtype.pubkey_type )
|
||||
|
||||
|
|
@ -269,10 +261,8 @@ class AddrList(MMGenObject): # Address info for a single seed ID
|
|||
|
||||
out.append(e)
|
||||
|
||||
if g.debug_addrlist:
|
||||
Msg(f'generate():\n{e.pfmt()}')
|
||||
|
||||
qmsg('\r{}: {} {}{} generated{}'.format(
|
||||
qmsg('{}{}: {} {}{} generated{}'.format(
|
||||
CR,
|
||||
self.al_id.hl(),
|
||||
t_addrs,
|
||||
self.gen_desc,
|
||||
|
|
|
|||
48
mmgen/derive.py
Executable file
48
mmgen/derive.py
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
derive.py: coin private key secret derivation for the MMGen suite
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
from hashlib import sha512,sha256
|
||||
from .addrlist import AddrIdxList
|
||||
|
||||
pk_bytes = namedtuple('coin_privkey_bytes',['idx','pos','data'])
|
||||
|
||||
def derive_coin_privkey_bytes(seed,idxs):
|
||||
|
||||
assert isinstance(idxs,AddrIdxList)
|
||||
|
||||
t_keys = len(idxs)
|
||||
pos = 0
|
||||
|
||||
for idx in range( 1, AddrIdxList.max_len+1 ): # key/addr indexes begin from one
|
||||
|
||||
seed = sha512(seed).digest()
|
||||
|
||||
if idx == idxs[pos]:
|
||||
|
||||
pos += 1
|
||||
|
||||
# secret is double sha256 of seed hash round /idx/
|
||||
yield pk_bytes( idx, pos, sha256(sha256(seed).digest()).digest() )
|
||||
|
||||
if pos == t_keys:
|
||||
break
|
||||
|
|
@ -52,6 +52,7 @@ If no test is specified, all available tests are run
|
|||
sys.argv.insert(1,'--skip-cfg-file')
|
||||
|
||||
opts.UserOpts._reset_ok += ('use_internal_keccak_module',)
|
||||
g._reset_ok += ('debug_addrlist',)
|
||||
|
||||
cmd_args = opts.init(opts_data)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,16 @@ from mmgen.addrlist import AddrIdxList,AddrList,KeyList,KeyAddrList
|
|||
from mmgen.passwdlist import PasswordList
|
||||
from mmgen.protocol import init_proto
|
||||
|
||||
def do_test(list_type,chksum,pw_id_str=None,add_kwargs=None):
|
||||
def do_test(list_type,chksum,idx_spec=None,pw_id_str=None,add_kwargs=None):
|
||||
qmsg(blue(f'Testing {list_type.__name__}'))
|
||||
proto = init_proto('btc')
|
||||
seed = Seed(seed_bin=bytes.fromhex('feedbead'*8))
|
||||
mmtype = MMGenAddrType(proto,'C')
|
||||
idxs = AddrIdxList('1-3')
|
||||
idxs = AddrIdxList(idx_spec or '1-3')
|
||||
|
||||
if opt.verbose:
|
||||
debug_addrlist_save = g.debug_addrlist
|
||||
g.debug_addrlist = True
|
||||
|
||||
kwargs = {
|
||||
'seed': seed,
|
||||
|
|
@ -43,12 +47,18 @@ def do_test(list_type,chksum,pw_id_str=None,add_kwargs=None):
|
|||
if chksum:
|
||||
assert al.chksum == chksum, f'{al.chksum} != {chksum}'
|
||||
|
||||
if opt.verbose:
|
||||
g.debug_addrlist = debug_addrlist_save
|
||||
|
||||
return True
|
||||
|
||||
class unit_tests:
|
||||
|
||||
def addr(self,name,ut):
|
||||
return do_test(AddrList,'BCE8 082C 0973 A525')
|
||||
return (
|
||||
do_test(AddrList,'BCE8 082C 0973 A525','1-3') and
|
||||
do_test(AddrList,'88FA B04B A380 C1CB','199999,99-101,77-78,7,3,2-9')
|
||||
)
|
||||
|
||||
def key(self,name,ut):
|
||||
return do_test(KeyList,None)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue