#!/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-addrgen: Generate a list or range of addresses from a mmgen deterministic wallet. Call as 'btc-keygen' to allow key generation as well. """ 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 list or 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 Addresses are given in a comma-separated list. Hyphen-separated ranges are also allowed.{} If available, the 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. For passphrases all combinations of whitespace are equal, and leading and trailing space are ignored. This permits reading passphrase data from a multi-line file with free spacing and indentation. This is particularly convenient for long brainwallet passphrases, for example. 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_list_arg = "",cmd_args[0] elif len(cmd_args) == 2: infile,addr_list_arg = cmd_args check_infile(infile) else: usage(help_data) addr_list = parse_address_list(addr_list_arg) if not addr_list: sys.exit(2) if not 'quiet' in opts: do_license_msg() # 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, addr_list, 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,"secret keys",confirm) elif not sys.stdout.isatty(): write_to_stdout(addr_data_str,"secret keys",confirm=False) else: write_addr_data_to_file(seed, addr_data_str, addr_list, opts)