Added 'mmgen-tool' utility with following commands:
General operations: hexdump - encode binary data in formatted hexadecimal form unhexdump - decode formatted hexadecimal data Bitcoin operations: strtob58 - convert a string to base 58 hextob58 - convert a hexadecimal number to base 58 b58tohex - convert a base 58 number to hexadecimal b58randenc - generate a random 32-byte number and convert it to base 58 randwif - generate a random private key in WIF format randpair - generate a random private key/address pair wif2addr - generate a Bitcoin address from a key in WIF format Mnemonic operations (choose "electrum" (default), "tirosh" or "all" wordlists): mn_rand128 - generate random 128-bit mnemonic mn_rand192 - generate random 192-bit mnemonic mn_rand256 - generate random 256-bit mnemonic mn_stats - show stats for mnemonic wordlist mn_printlist - print mnemonic wordlist
This commit is contained in:
parent
1a030c0684
commit
0894985bfa
26 changed files with 426 additions and 85 deletions
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
68
mmgen-tool
Executable file
68
mmgen-tool
Executable file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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/>.
|
||||
"""
|
||||
mmgen-tool: Perform various Bitcoin-related operations - part of the MMGen suite
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
from hashlib import sha256
|
||||
|
||||
from mmgen.Opts import *
|
||||
import mmgen.config as g
|
||||
from mmgen.util import pretty_hexdump
|
||||
from mmgen.tool import *
|
||||
prog_name = sys.argv[0].split("/")[-1]
|
||||
|
||||
help_data = {
|
||||
'prog_name': prog_name,
|
||||
'desc': "Perform various BTC-related operations",
|
||||
'usage': "[opts] <command> <args>",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
-q, --quiet Produce quieter output
|
||||
-v, --verbose Produce more verbose output
|
||||
|
||||
COMMANDS:{}
|
||||
Type '{} <command> --help for usage information on a particular command
|
||||
""".format(command_help,prog_name)
|
||||
}
|
||||
|
||||
short_opts = "hqv"
|
||||
long_opts = "help","quiet","verbose"
|
||||
|
||||
opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
|
||||
if 'quiet' in opts: g.quiet = True
|
||||
if 'verbose' in opts: g.verbose = True
|
||||
|
||||
if len(cmd_args) < 1:
|
||||
usage(help_data)
|
||||
sys.exit(1)
|
||||
else: command = cmd_args.pop(0)
|
||||
|
||||
if command not in commands.keys():
|
||||
msg("'%s': No such command" % command)
|
||||
sys.exit(1)
|
||||
|
||||
if cmd_args and cmd_args[0] == '--help':
|
||||
tool_usage(prog_name, command)
|
||||
sys.exit(0)
|
||||
|
||||
args = process_args(prog_name, command, cmd_args) if cmd_args else []
|
||||
|
||||
#print command + "(" + ", ".join(args) + ")"
|
||||
eval(command + "(" + ", ".join(args) + ")")
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
@ -79,36 +79,36 @@ if not 'info' in opts:
|
|||
check_infile(a)
|
||||
addr_data.append(parse_addrs_file(a))
|
||||
|
||||
def mm2btc_addr_proc(c,mmadr,acct_data,addr_data,b2m_map):
|
||||
btaddr,label = mmgen_addr_to_walletd(c,mmadr,acct_data)
|
||||
if not btaddr:
|
||||
btaddr,label = mmgen_addr_to_addr_data(mmadr,addr_data)
|
||||
b2m_map[btaddr] = mmadr,label
|
||||
return btaddr
|
||||
def mm_addr2btc_addr(c,mmadr,acct_data,addr_data,b2m_map):
|
||||
btcaddr,label = mmgen_addr_to_walletd(c,mmadr,acct_data)
|
||||
if not btcaddr:
|
||||
btcaddr,label = mmgen_addr_to_addr_data(mmadr,addr_data)
|
||||
b2m_map[btcaddr] = mmadr,label
|
||||
return btcaddr
|
||||
|
||||
for a in [i for i in cmd_args if not match_ext(i,g.addrfile_ext)]:
|
||||
if "," in a:
|
||||
a1,a2 = a.split(",")
|
||||
if is_mmgen_addr(a1) or is_btc_addr(a1):
|
||||
btaddr = mm2btc_addr_proc(c,a1,acct_data,addr_data,b2m_map) \
|
||||
if is_mmgen_addr(a1) else a1
|
||||
if is_btc_amt(a2):
|
||||
tx_out[btaddr] = check_btc_amt(a2)
|
||||
else:
|
||||
msg("%s: invalid amount in argument '%s'" % (a2,a))
|
||||
sys.exit(2)
|
||||
if is_btc_addr(a1):
|
||||
btcaddr = a1
|
||||
elif is_mmgen_addr(a1):
|
||||
btcaddr = mm_addr2btc_addr(c,a1,acct_data,addr_data,b2m_map)
|
||||
else:
|
||||
msg("%s: unrecognized subargument in argument '%s'" % (a1,a))
|
||||
sys.exit(2)
|
||||
|
||||
if is_btc_amt(a2):
|
||||
tx_out[btcaddr] = check_btc_amt(a2)
|
||||
else:
|
||||
msg("%s: invalid amount in argument '%s'" % (a2,a))
|
||||
sys.exit(2)
|
||||
elif is_mmgen_addr(a) or is_btc_addr(a):
|
||||
if change_addr:
|
||||
msg("More than one change address specified: %s, %s" %
|
||||
msg("ERROR: More than one change address specified: %s, %s" %
|
||||
(change_addr, a))
|
||||
sys.exit(2)
|
||||
if is_mmgen_addr(a):
|
||||
change_addr = mm2btc_addr_proc(c,a,acct_data,addr_data,b2m_map)
|
||||
else:
|
||||
change_addr = a
|
||||
change_addr = a if is_btc_addr(a) else \
|
||||
mm_addr2btc_addr(c,a,acct_data,addr_data,b2m_map)
|
||||
tx_out[change_addr] = 0
|
||||
else:
|
||||
msg("%s: unrecognized argument" % a)
|
||||
|
|
@ -157,7 +157,9 @@ msg("Total amount to spend: %s%s" % (
|
|||
while True:
|
||||
sel_nums = select_outputs(unspent,
|
||||
"Enter a range or space-separated list of outputs to spend: ")
|
||||
msg("Selected outputs: %s" % " ".join(str(i) for i in sel_nums))
|
||||
msg("Selected output%s: %s" %
|
||||
(("" if len(sel_nums) == 1 else "s"), " ".join(str(i) for i in sel_nums))
|
||||
)
|
||||
sel_unspent = [unspent[i-1] for i in sel_nums]
|
||||
|
||||
mmaddrs = set([parse_mmgen_label(i.account)[0] for i in sel_unspent])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
@ -73,50 +73,19 @@ elif 'export_seed' in opts:
|
|||
qmsg("Exporting seed data to file by user request")
|
||||
elif 'export_incog' in opts:
|
||||
qmsg("Exporting wallet to incognito format by user request")
|
||||
|
||||
d = get_data_from_wallet(cmd_args[0],silent=True)
|
||||
seed_id,key_id,preset,salt,enc_seed = \
|
||||
d[1][0], d[1][1], d[2].split(":")[0], d[3], d[4]
|
||||
|
||||
passwd = get_mmgen_passphrase("Enter mmgen passphrase: ",opts)
|
||||
key = make_key(passwd, salt, preset, "main key")
|
||||
# We don't need the seed; just do this to verify password.
|
||||
if decrypt_seed(enc_seed, key, seed_id, key_id) == False:
|
||||
sys.exit(2)
|
||||
|
||||
from Crypto import Random
|
||||
iv = Random.new().read(g.aesctr_iv_len)
|
||||
iv_id = make_chksum_8(iv)
|
||||
qmsg("IV ID: %s" % iv_id)
|
||||
|
||||
from binascii import hexlify
|
||||
from hashlib import sha256
|
||||
# IV is used BOTH to initialize counter and to salt password!
|
||||
key = make_key(passwd, iv, preset, "wrapper key")
|
||||
incog_enc = encrypt_seed(salt + enc_seed, key, iv=int(hexlify(iv),16))
|
||||
incog_enc,seed_id,key_id,iv_id,preset = \
|
||||
wallet_to_incog_data(cmd_args[0],opts)
|
||||
|
||||
if "export_incog_hidden" in opts:
|
||||
fname,offset = opts['export_incog_hidden'].split(",") #Already sanity-checked
|
||||
offset = int(offset)
|
||||
|
||||
check_data_fits_file_at_offset(fname,offset,len(iv + incog_enc),"write")
|
||||
|
||||
if not g.quiet: confirm_or_exit("","alter file '%s'" % fname)
|
||||
f = os.open(fname,os.O_RDWR)
|
||||
os.lseek(f, offset, os.SEEK_SET)
|
||||
os.write(f, iv + incog_enc)
|
||||
os.close(f)
|
||||
qmsg("Data written to file '%s' at offset %s" % (fname,offset),
|
||||
"Data written to file")
|
||||
export_to_hidden_incog(incog_enc,opts)
|
||||
else:
|
||||
seed_len = (len(incog_enc)-g.salt_len-g.aesctr_iv_len)*8
|
||||
fn = "%s-%s-%s[%s,%s].%s" % (
|
||||
seed_id, key_id, iv_id, len(enc_seed)*8, preset,
|
||||
seed_id, key_id, iv_id, seed_len, preset,
|
||||
g.incog_hex_ext if "export_incog_hex" in opts else g.incog_ext
|
||||
)
|
||||
data = iv + incog_enc
|
||||
if "export_incog_hex" in opts:
|
||||
data = "".join([hexlify(data[i*2:i*2+2]) + (" " if (i+1)%8 else "\n")
|
||||
for i in range(len(data)/2)])
|
||||
data = pretty_hexdump(incog_enc,2,8,line_nums=False) \
|
||||
if "export_incog_hex" in opts else incog_enc
|
||||
export_to_file(fn, data, "incognito wallet data", opts)
|
||||
|
||||
sys.exit()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# MMGen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
@ -24,9 +24,9 @@ from mmgen.util import msg, msg_r, get_char
|
|||
|
||||
gpl = {
|
||||
'warning': """
|
||||
MMGen Copyright (C) 2013 by Philemon <mmgen-py@yandex.com>. This
|
||||
program comes with ABSOLUTELY NO WARRANTY. This is free software,
|
||||
and you are welcome to redistribute it under certain conditions.
|
||||
MMGen Copyright (C) 2013-2014 by Philemon <mmgen-py@yandex.com>. This
|
||||
program comes with ABSOLUTELY NO WARRANTY. This is free software, and
|
||||
you are welcome to redistribute it under certain conditions.
|
||||
""",
|
||||
'prompt': """
|
||||
Press 'w' for conditions and warranty info, or 'c' to continue:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
@ -95,7 +95,7 @@ def check_wordlist(wl_str,label):
|
|||
|
||||
from hashlib import sha256
|
||||
|
||||
print "Length: %i" % len(wl)
|
||||
print "Length: %i words" % len(wl)
|
||||
new_chksum = sha256(" ".join(wl)).hexdigest()[:8]
|
||||
|
||||
if new_chksum != wl_checksums[label]:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -218,6 +218,5 @@ tests = {
|
|||
"wiftoaddr_comp": ['wif [str]'],
|
||||
}
|
||||
|
||||
|
||||
args = process_test_args(sys.argv, tests)
|
||||
eval(sys.argv[1])(*args)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
mnemonic.py: Test suite for mmgen.mnemonic module
|
||||
"""
|
||||
|
||||
from mmgen.mnemonic import *
|
||||
from test import *
|
||||
|
||||
import sys
|
||||
from binascii import hexlify
|
||||
|
||||
from mmgen.mnemonic import *
|
||||
from mmgen.mn_electrum import electrum_words as el
|
||||
from mmgen.mn_tirosh import tirosh_words as tl
|
||||
|
||||
|
|
|
|||
244
mmgen/tool.py
Executable file
244
mmgen/tool.py
Executable file
|
|
@ -0,0 +1,244 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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/>.
|
||||
"""
|
||||
tool.py: Routines and data for the mmgen-tool utility
|
||||
"""
|
||||
|
||||
import sys
|
||||
import mmgen.bitcoin as bitcoin
|
||||
|
||||
from mmgen.util import *
|
||||
|
||||
commands = {
|
||||
# "keyconv_compare": ['wif [str]'],
|
||||
# "keyconv_compare_randloop": ['iterations [int]'],
|
||||
# "hextob58_pad": ['hexnum [str]],
|
||||
# "b58tohex_pad": ['b58num [str]'],
|
||||
# "hextob58_pad_randloop": ['iterations [int]'],
|
||||
# "test_wiftohex": ['wif [str]'],
|
||||
# "hextosha256": ['hexnum [str]'],
|
||||
# "hextowiftopubkey": ['hexnum [str]'],
|
||||
# "pubhextoaddr": ['hexnum [str]'],
|
||||
# "hextowif_comp": ['hexnum [str]'],
|
||||
# "wiftohex_comp": ['wif [str]'],
|
||||
# "privhextoaddr_comp": ['hexnum [str]'],
|
||||
# "wiftoaddr_comp": ['wif [str]'],
|
||||
"strtob58": ['<string> [str]'],
|
||||
"hextob58": ['<hex number> [str]'],
|
||||
"b58tohex": ['<b58 number> [str]'],
|
||||
"b58randenc": [],
|
||||
"randwif": ['compressed [bool=False]'],
|
||||
"randpair": ['compressed [bool=False]'],
|
||||
"wif2addr": ['<wif> [str]', 'compressed [bool=False]'],
|
||||
"hexdump": ['<infile> [str]', 'cols [int=8]', 'line_nums [bool=True]'],
|
||||
"unhexdump": ['<infile> [str]'],
|
||||
"mn_rand128": ['wordlist [str="electrum"]'],
|
||||
"mn_rand192": ['wordlist [str="electrum"]'],
|
||||
"mn_rand256": ['wordlist [str="electrum"]'],
|
||||
"mn_stats": ['wordlist [str="electrum"]'],
|
||||
"mn_printlist": ['wordlist [str="electrum"]']
|
||||
}
|
||||
|
||||
command_help = """
|
||||
General operations:
|
||||
hexdump - encode binary data in formatted hexadecimal form
|
||||
unhexdump - decode formatted hexadecimal data
|
||||
|
||||
Bitcoin operations:
|
||||
strtob58 - convert a string to base 58
|
||||
hextob58 - convert a hexadecimal number to base 58
|
||||
b58tohex - convert a base 58 number to hexadecimal
|
||||
b58randenc - generate a random 32-byte number and convert it to base 58
|
||||
randwif - generate a random private key in WIF format
|
||||
randpair - generate a random private key/address pair
|
||||
wif2addr - generate a Bitcoin address from a key in WIF format
|
||||
|
||||
Mnemonic operations (choose "electrum" (default), "tirosh" or "all" wordlists):
|
||||
mn_rand128 - generate random 128-bit mnemonic
|
||||
mn_rand192 - generate random 192-bit mnemonic
|
||||
mn_rand256 - generate random 256-bit mnemonic
|
||||
mn_stats - show stats for mnemonic wordlist
|
||||
mn_printlist - print mnemonic wordlist
|
||||
|
||||
IMPORTANT NOTE: Though MMGen mnemonics use the Electrum wordlist, they're
|
||||
computed using a different algorithm and are NOT Electrum-compatible!
|
||||
"""
|
||||
|
||||
def tool_usage(prog_name, command):
|
||||
print "USAGE: '%s %s%s'" % (prog_name, command,
|
||||
(" "+" ".join(commands[command]) if commands[command] else ""))
|
||||
|
||||
def process_args(prog_name, command, uargs):
|
||||
cargs = commands[command]
|
||||
cargs_req = [[i.split(" [")[0],i.split(" [")[1][:-1]]
|
||||
for i in cargs if "=" not in i]
|
||||
cargs_nam = dict([[
|
||||
i.split(" [")[0],
|
||||
[i.split(" [")[1].split("=")[0], i.split(" [")[1].split("=")[1][:-1]]
|
||||
] for i in cargs if "=" in i])
|
||||
uargs_req = [i for i in uargs if "=" not in i]
|
||||
uargs_nam = dict([i.split("=") for i in uargs if "=" in i])
|
||||
|
||||
# print cargs_req; print cargs_nam; print uargs_req; print uargs_nam; sys.exit()
|
||||
|
||||
n = len(cargs_req)
|
||||
if len(uargs_req) != n:
|
||||
print "ERROR: %s argument%s required" % (n, " is" if n==1 else "s are")
|
||||
tool_usage(prog_name, command)
|
||||
sys.exit(1)
|
||||
|
||||
for a in uargs_nam.keys():
|
||||
if a not in cargs_nam.keys():
|
||||
print "'%s' invalid named argument" % a
|
||||
sys.exit(1)
|
||||
|
||||
def test_type(arg_type,arg,name=""):
|
||||
try:
|
||||
t = type(eval(arg))
|
||||
assert(t == eval(arg_type))
|
||||
except:
|
||||
print "'%s': Invalid argument for argument %s ('%s' required)" % \
|
||||
(arg, name, arg_type)
|
||||
sys.exit(1)
|
||||
return True
|
||||
|
||||
ret = []
|
||||
|
||||
for i in range(len(cargs_req)):
|
||||
arg,arg_type = uargs_req[i], cargs_req[i][1]
|
||||
if arg == "true" or arg == "false": arg = arg.capitalize()
|
||||
if arg_type == "str":
|
||||
ret.append('"%s"' % (arg))
|
||||
elif test_type(arg_type, arg, "#"+str(i+1)):
|
||||
ret.append('%s' % (arg))
|
||||
|
||||
for k in uargs_nam.keys():
|
||||
arg,arg_type = uargs_nam[k], cargs_nam[k][0]
|
||||
if arg == "true" or arg == "false": arg = arg.capitalize()
|
||||
if arg_type == "str":
|
||||
ret.append('%s="%s"' % (k, arg))
|
||||
elif test_type(arg_type, arg, "'"+k+"'"):
|
||||
ret.append('%s=%s' % (k, arg))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
# Individual commands
|
||||
|
||||
def print_convert_results(indata,enc,dec,no_recode=False):
|
||||
vmsg("Input: [%s]" % indata)
|
||||
vmsg_r("Encoded data: ["); msg_r(enc); vmsg_r("]"); msg("")
|
||||
if not no_recode:
|
||||
vmsg("Recoded data: [%s]" % dec)
|
||||
if indata != dec:
|
||||
msg("WARNING! Recoded number doesn't match input stringwise!")
|
||||
|
||||
def hexdump(infile, cols=8, line_nums=True):
|
||||
data = get_data_from_file(infile)
|
||||
o = pretty_hexdump(data, 2, cols, line_nums)
|
||||
print o
|
||||
|
||||
def unhexdump(infile):
|
||||
data = get_data_from_file(infile)
|
||||
o = decode_pretty_hexdump(data)
|
||||
sys.stdout.write(o)
|
||||
|
||||
def strtob58(s):
|
||||
enc = bitcoin.b58encode(s)
|
||||
dec = bitcoin.b58decode(enc)
|
||||
print_convert_results(s,enc,dec)
|
||||
|
||||
def hextob58(s,f_enc=bitcoin.b58encode, f_dec=bitcoin.b58decode):
|
||||
enc = f_enc(unhexlify(s))
|
||||
dec = hexlify(f_dec(enc))
|
||||
print_convert_results(s,enc,dec)
|
||||
|
||||
def b58tohex(s,f_enc=bitcoin.b58decode, f_dec=bitcoin.b58encode):
|
||||
tmp = f_enc(s)
|
||||
if tmp == False: sys.exit(1)
|
||||
enc = hexlify(tmp)
|
||||
dec = f_dec(unhexlify(enc))
|
||||
print_convert_results(s,enc,dec)
|
||||
|
||||
def get_random(length):
|
||||
from Crypto import Random
|
||||
return Random.new().read(length)
|
||||
|
||||
def b58randenc():
|
||||
r = get_random(32)
|
||||
enc = bitcoin.b58encode(r)
|
||||
dec = bitcoin.b58decode(enc)
|
||||
print_convert_results(hexlify(r),enc,hexlify(dec))
|
||||
|
||||
def randwif(compressed=False):
|
||||
r_hex = hexlify(get_random(32))
|
||||
enc = bitcoin.hextowif(r_hex,compressed)
|
||||
print_convert_results(r_hex,enc,"",no_recode=True)
|
||||
|
||||
def randpair(compressed=False):
|
||||
r_hex = hexlify(get_random(32))
|
||||
wif = bitcoin.hextowif(r_hex,compressed)
|
||||
addr = bitcoin.privnum2addr(int(r_hex,16),compressed)
|
||||
vmsg("Key (hex): %s" % r_hex)
|
||||
vmsg_r("Key (WIF): "); msg(wif)
|
||||
vmsg_r("Addr: "); msg(addr)
|
||||
|
||||
def wif2addr(s_in,compressed=False):
|
||||
s_enc = bitcoin.wiftohex(s_in,compressed)
|
||||
if s_enc == False:
|
||||
msg("Invalid address")
|
||||
sys.exit(1)
|
||||
addr = bitcoin.privnum2addr(int(s_enc,16),compressed)
|
||||
vmsg_r("Addr: "); msg(addr)
|
||||
|
||||
from mmgen.mnemonic import *
|
||||
from mmgen.mn_electrum import electrum_words as el
|
||||
from mmgen.mn_tirosh import tirosh_words as tl
|
||||
|
||||
wordlists = sorted(wl_checksums.keys())
|
||||
|
||||
def get_wordlist(wordlist):
|
||||
wordlist = wordlist.lower()
|
||||
if wordlist not in wordlists:
|
||||
msg('"%s": invalid wordlist. Valid choices: %s' %
|
||||
(wordlist,'"'+'" "'.join(wordlists)+'"'))
|
||||
sys.exit(1)
|
||||
return el if wordlist == "electrum" else tl
|
||||
|
||||
def do_random_mn(nbytes,wordlist):
|
||||
r = get_random(nbytes)
|
||||
wlists = wordlists if wordlist == "all" else [wordlist]
|
||||
for wl in wlists:
|
||||
l = get_wordlist(wl)
|
||||
if wl == wlists[0]: vmsg("Seed: %s" % hexlify(r))
|
||||
mn = get_mnemonic_from_seed(r,l.strip().split("\n"),
|
||||
wordlist,print_info=False)
|
||||
vmsg("%s wordlist mnemonic:" % (wl.capitalize()))
|
||||
print " ".join(mn)
|
||||
|
||||
def mn_rand128(wordlist="electrum"): do_random_mn(16,wordlist)
|
||||
def mn_rand192(wordlist="electrum"): do_random_mn(24,wordlist)
|
||||
def mn_rand256(wordlist="electrum"): do_random_mn(32,wordlist)
|
||||
|
||||
def mn_stats(wordlist="electrum"):
|
||||
l = get_wordlist(wordlist)
|
||||
check_wordlist(l,wordlist)
|
||||
|
||||
def mn_printlist(wordlist="electrum"):
|
||||
l = get_wordlist(wordlist)
|
||||
print "%s" % l.strip()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
@ -994,5 +994,61 @@ def do_pager(text):
|
|||
else: print text+end
|
||||
|
||||
|
||||
def export_to_hidden_incog(incog_enc,opts):
|
||||
fname,offset = opts['export_incog_hidden'].split(",") #Already sanity-checked
|
||||
|
||||
check_data_fits_file_at_offset(fname,int(offset),len(incog_enc),"write")
|
||||
|
||||
if not g.quiet: confirm_or_exit("","alter file '%s'" % fname)
|
||||
f = os.open(fname,os.O_RDWR)
|
||||
os.lseek(f, int(offset), os.SEEK_SET)
|
||||
os.write(f, incog_enc)
|
||||
os.close(f)
|
||||
qmsg("Data written to file '%s' at offset %s" % (fname,offset),
|
||||
"Data written to file")
|
||||
|
||||
|
||||
def pretty_hexdump(data,gw,cols,line_nums=False):
|
||||
r = 1 if len(data) % gw else 0
|
||||
return "".join(
|
||||
[
|
||||
("" if (line_nums == False or i % cols) else "%03i: " % (i/cols)) +
|
||||
hexlify(data[i*gw:i*gw+gw]) +
|
||||
(" " if (i+1) % cols else "\n")
|
||||
for i in range(len(data)/gw + r)
|
||||
]
|
||||
).rstrip()
|
||||
|
||||
def decode_pretty_hexdump(data):
|
||||
import re
|
||||
lines = [re.sub('^\d+:\s+','',l) for l in data.split("\n")]
|
||||
return unhexlify("".join(("".join(lines).split())))
|
||||
|
||||
def wallet_to_incog_data(infile,opts):
|
||||
|
||||
d = get_data_from_wallet(infile,silent=True)
|
||||
seed_id,key_id,preset,salt,enc_seed = \
|
||||
d[1][0], d[1][1], d[2].split(":")[0], d[3], d[4]
|
||||
|
||||
passwd = get_mmgen_passphrase("Enter mmgen passphrase: ",opts)
|
||||
key = make_key(passwd, salt, preset, "main key")
|
||||
# We don't need the seed; just do this to verify password.
|
||||
if decrypt_seed(enc_seed, key, seed_id, key_id) == False:
|
||||
sys.exit(2)
|
||||
|
||||
from Crypto import Random
|
||||
iv = Random.new().read(g.aesctr_iv_len)
|
||||
iv_id = make_chksum_8(iv)
|
||||
qmsg("IV ID: %s" % iv_id)
|
||||
|
||||
from binascii import hexlify
|
||||
from hashlib import sha256
|
||||
# IV is used BOTH to initialize counter and to salt password!
|
||||
key = make_key(passwd, iv, preset, "wrapper key")
|
||||
wrap_enc = encrypt_seed(salt + enc_seed, key, iv=int(hexlify(iv),16))
|
||||
|
||||
return iv+wrap_enc,seed_id,key_id,iv_id,preset
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print "util.py"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
|
||||
# Copyright (C) 2013 by philemon <mmgen-py@yandex.com>
|
||||
# Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -20,6 +20,7 @@ setup(
|
|||
'mmgen.mn_tirosh',
|
||||
'mmgen.Opts',
|
||||
'mmgen.term',
|
||||
'mmgen.tool',
|
||||
'mmgen.tx',
|
||||
'mmgen.util',
|
||||
'mmgen.walletgen',
|
||||
|
|
@ -52,5 +53,6 @@ setup(
|
|||
'mmgen-txsign',
|
||||
'mmgen-txsend',
|
||||
'mmgen-pywallet'
|
||||
'mmgen-tool',
|
||||
]
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue