#!/usr/bin/env python # # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution # Copyright (C) 2013 by philemon # # 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 . """ mmgen-keygen: Generate addresses/secret keys from a mmgen deterministic wallet for a range of addresses. Call as 'btc-addrgen' for safe, reduced functionality with no output of secret keys. """ import sys from mmgen.Opts import * from mmgen.config import * from mmgen.license import * from mmgen.utils import * from mmgen.addr import * invoked_as = sys.argv[0].split("-")[-1] gen_what = "addresses" if invoked_as == "addrgen" else "keys" if invoked_as == "keygen": extra_help_data = ( "\n-A, --no-addresses Print only secret keys, no addresses", "\n-x, --b16 Print secret keys in hexadecimal too", ".\nBy default, both addresses and secret keys are generated" ) else: extra_help_data = ("","","") help_data = { 'prog_name': sys.argv[0].split("/")[-1], 'desc': """Generate a range of {} from a {} wallet, mnemonic, seed or password""".format(gen_what,proj_name), 'usage':"[opts] [infile]
", 'options': """ -h, --help Print this help message{} -d, --outdir d Specify an alternate directory 'd' for output -e, --echo-passphrase Display passphrase or mnemonic on screen upon entry -K, --no-keyconv Use internal libraries for address generation instead of 'keyconv' -l, --seed-len N Length of seed. Options: {} (default: {}) -p, --hash-preset p Use scrypt.hash() parameters from preset 'p' when hashing password (default: '{}') -P, --show-hash-presets Show information on available hash presets -q, --quiet Suppress warnings; overwrite files without asking -S, --stdout Print {W} to stdout -v, --verbose Produce more verbose output{} -b, --from-brain l,p Generate {W} from a user-created password, i.e. a "brainwallet", using seed length 'l' and hash preset 'p' (comma-separated) -m, --from-mnemonic Generate {W} from an electrum-like mnemonic -s, --from-seed Generate {W} from a seed in .{S} format Address range may be a single number or a range in the form XXX-YYY{} If available, external 'keyconv' program will be used for address generation Data for the --from- options will be taken from if is specified. Otherwise, the user will be prompted to enter the data. Note that passphrase data in a file may be arranged in free-form fashion, using any combination of spaces, tabs or newlines to separate words BRAINWALLET NOTE: As brainwallets require especially strong hashing to thwart dictionary attacks, the brainwallet hash preset must be specified by the user, using the 'p' parameter of the '--from-brain' option The '--from-brain' option also requires the user to specify a seed length (the 'l' parameter) For a brainwallet passphrase to always generate the same keys and addresses, the same 'l' and 'p' parameters to '--from-brain' must be used in all future invocations with that passphrase """.format( extra_help_data[0], ", ".join([str(i) for i in seed_lens]), seed_len, hash_preset, extra_help_data[1], extra_help_data[2], W=gen_what, S=seed_ext ) } so = "h","A","d:","e","K","l:","p:","P","q","S","v","x","b:","m","s" lo = "help","no_addresses","outdir=","echo_passphrase","no_keyconv",\ "seed_len=","hash_preset=","show_hash_presets","quiet","stdout",\ "verbose","b16","from_brain=","from_mnemonic","from_seed" if invoked_as == "addrgen": short_opts = so[0:1] + so[2:10] + so[11:] long_opts = lo[0:1] + lo[2:10] + lo[11:] else: short_opts,long_opts = so,lo opts,cmd_args = process_opts(sys.argv,help_data,"".join(short_opts),long_opts) if 'show_hash_presets' in opts: show_hash_presets() # Sanity checking and processing of command-line arguments: opts['gen_what'] = gen_what set_if_unset_and_typeconvert(opts,( ('hash_preset',hash_preset,'str'), ('seed_len',seed_len,'int') )) # Exits on invalid input check_opts(opts,('hash_preset','seed_len','outdir','from_brain')) if debug: print "Processed options: %s" % repr(opts) print "Cmd args: %s" % repr(cmd_args) if len(cmd_args) == 1 and ( 'from_mnemonic' in opts or 'from_brain' in opts or 'from_seed' in opts ): infile,addr_range = "",cmd_args[0] elif len(cmd_args) == 2: infile,addr_range = cmd_args check_infile(infile) else: usage(help_data) start,end = parse_address_range(addr_range) if not 'quiet' in opts: do_license_msg(); msg("\n") # Interact with user: if invoked_as == "keygen" and not 'quiet' in opts: confirm_or_exit(cmessages['unencrypted_secret_keys'], 'continue') # Generate data: if invoked_as == "addrgen": opts['print_addresses_only'] = True else: if not 'no_addresses' in opts: opts['print_secret'] = True seed = get_seed(infile,opts) seed_id = make_chksum_8(seed) addr_data = generate_addrs(seed, start, end, opts) addr_data_str = format_addr_data(addr_data, seed_id, opts) # Output data: if 'stdout' in opts: if invoked_as == "keygen" and not 'quiet' in opts: confirm = True else: confirm = False write_to_stdout(addr_data_str,confirm) elif not sys.stdout.isatty(): write_to_stdout(addr_data_str,confirm=False) else: write_addr_data_to_file(seed, addr_data_str, start, end, opts)