/* * Vanitygen, vanity bitcoin address generator * Copyright (C) 2011 * * Vanitygen is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Vanitygen 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Vanitygen. If not, see . */ #include #include #include #include #include #include #include #include "oclengine.h" #include "pattern.h" #include "util.h" const char *version = VANITYGEN_VERSION; const int debug = 0; void usage(const char *name) { fprintf(stderr, "oclVanitygen %s (" OPENSSL_VERSION_TEXT ")\n" "Usage: %s [-vqrikNTS] [-d ] [-f |-] [...]\n" "Generates a bitcoin receiving address matching , and outputs the\n" "address and associated private key. The private key may be stored in a safe\n" "location or imported into a bitcoin client to spend any balance received on\n" "the address.\n" "By default, is interpreted as an exact prefix.\n" "\n" "Options:\n" "-v Verbose output\n" "-q Quiet output\n" "-r Use regular expression match instead of prefix\n" " (Feasibility of expression is not checked)\n" "-i Case-insensitive prefix search\n" "-k Keep pattern and continue search after finding a match\n" "-N Generate namecoin address\n" "-T Generate bitcoin testnet address\n" "-X Generate address with the given version\n" "-e Encrypt private keys, prompt for password\n" "-E Encrypt private keys with (UNSAFE)\n" "-p Select OpenCL platform\n" "-d Select OpenCL device\n" "-S Safe mode, disable OpenCL loop unrolling optimizations\n" "-w Set work items per thread in a work unit\n" "-t Set target thread count per multiprocessor\n" "-g x Set grid size\n" "-b Set modular inverse ops per thread\n" "-V Enable kernel/OpenCL/hardware verification (SLOW)\n" "-f File containing list of patterns, one per line\n" " (Use \"-\" as the file name for stdin)\n" "-o Write pattern matches to \n" "-s Seed random number generator from \n", version, name); } int main(int argc, char **argv) { int addrtype = 0; int privtype = 128; int regex = 0; int caseinsensitive = 0; int opt; char pwbuf[128]; int platformidx = -1, deviceidx = -1; int prompt_password = 0; char *seedfile = NULL; FILE *fp = NULL; char **patterns, *pend; int verbose = 1; int npatterns = 0; int nthreads = 0; int worksize = 0; int nrows = 0, ncols = 0; int invsize = 0; int remove_on_match = 1; int verify_mode = 0; int safe_mode = 0; vg_context_t *vcp = NULL; vg_ocl_context_t *vocp = NULL; EC_POINT *pubkey_base = NULL; const char *result_file = NULL; const char *key_password = NULL; while ((opt = getopt(argc, argv, "vqrikNTX:eE:p:P:d:w:t:g:b:VSh?f:o:s:")) != -1) { switch (opt) { case 'v': verbose = 2; break; case 'q': verbose = 0; break; case 'r': regex = 1; break; case 'i': caseinsensitive = 1; break; case 'k': remove_on_match = 0; break; case 'N': addrtype = 52; privtype = 180; break; case 'T': addrtype = 111; privtype = 239; break; case 'X': addrtype = atoi(optarg); privtype = 128 + addrtype; break; case 'e': prompt_password = 1; break; case 'E': key_password = optarg; break; case 'p': platformidx = atoi(optarg); break; case 'd': deviceidx = atoi(optarg); break; case 'w': worksize = atoi(optarg); if (worksize == 0) { fprintf(stderr, "Invalid work size '%s'\n", optarg); return 1; } break; case 't': nthreads = atoi(optarg); if (nthreads == 0) { fprintf(stderr, "Invalid thread count '%s'\n", optarg); return 1; } break; case 'g': nrows = 0; ncols = strtol(optarg, &pend, 0); if (pend && *pend == 'x') { nrows = strtol(pend+1, NULL, 0); } if (!nrows || !ncols) { fprintf(stderr, "Invalid grid size '%s'\n", optarg); return 1; } break; case 'b': invsize = atoi(optarg); if (!invsize) { fprintf(stderr, "Invalid modular inverse size '%s'\n", optarg); return 1; } if (invsize & (invsize - 1)) { fprintf(stderr, "Modular inverse size must be " "a power of 2\n"); return 1; } break; case 'V': verify_mode = 1; break; case 'S': safe_mode = 1; break; case 'P': { if (pubkey_base != NULL) { fprintf(stderr, "Multiple base pubkeys specified\n"); return 1; } EC_KEY *pkey = vg_exec_context_new_key(); pubkey_base = EC_POINT_hex2point( EC_KEY_get0_group(pkey), optarg, NULL, NULL); EC_KEY_free(pkey); if (pubkey_base == NULL) { fprintf(stderr, "Invalid base pubkey\n"); return 1; } break; } case 'f': if (fp) { fprintf(stderr, "Multiple files specified\n"); return 1; } if (!strcmp(optarg, "-")) { fp = stdin; } else { fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "Could not open %s: %s\n", optarg, strerror(errno)); return 1; } } break; case 'o': if (result_file) { fprintf(stderr, "Multiple output files specified\n"); return 1; } result_file = optarg; break; case 's': if (seedfile != NULL) { fprintf(stderr, "Multiple RNG seeds specified\n"); return 1; } seedfile = optarg; break; default: usage(argv[0]); return 1; } } #if OPENSSL_VERSION_NUMBER < 0x10000000L /* Complain about older versions of OpenSSL */ if (verbose > 0) { fprintf(stderr, "WARNING: Built with " OPENSSL_VERSION_TEXT "\n" "WARNING: Use OpenSSL 1.0.0d+ for best performance\n"); } #endif if (caseinsensitive && regex) fprintf(stderr, "WARNING: case insensitive mode incompatible with " "regular expressions\n"); if (seedfile) { opt = -1; #if !defined(_WIN32) { struct stat st; if (!stat(seedfile, &st) && (st.st_mode & (S_IFBLK|S_IFCHR))) { opt = 32; } } #endif opt = RAND_load_file(seedfile, opt); if (!opt) { fprintf(stderr, "Could not load RNG seed %s\n", optarg); return 1; } if (verbose > 0) { fprintf(stderr, "Read %d bytes from RNG seed file\n", opt); } } if (fp) { if (!vg_read_file(fp, &patterns, &npatterns)) { fprintf(stderr, "Failed to load pattern file\n"); return 1; } if (fp != stdin) fclose(fp); } else { if (optind >= argc) { usage(argv[0]); return 1; } patterns = &argv[optind]; npatterns = argc - optind; } if (regex) { vcp = vg_regex_context_new(addrtype, privtype); } else { vcp = vg_prefix_context_new(addrtype, privtype, caseinsensitive); } vcp->vc_verbose = verbose; vcp->vc_result_file = result_file; vcp->vc_remove_on_match = remove_on_match; vcp->vc_pubkey_base = pubkey_base; vcp->vc_output_match = vg_output_match_console; vcp->vc_output_timing = vg_output_timing_console; if (!vg_context_add_patterns(vcp, (const char ** const)patterns, npatterns)) return 1; if (!vcp->vc_npatterns) { fprintf(stderr, "No patterns to search\n"); return 1; } if (prompt_password) { if (!vg_read_password(pwbuf, sizeof(pwbuf))) return 1; key_password = pwbuf; } vcp->vc_key_protect_pass = key_password; if (key_password) { if (!vg_check_password_complexity(key_password, verbose)) fprintf(stderr, "WARNING: Protecting private keys with " "weak password\n"); } if ((verbose > 0) && regex && (vcp->vc_npatterns > 1)) fprintf(stderr, "Regular expressions: %ld\n", vcp->vc_npatterns); vocp = vg_ocl_context_new(vcp, platformidx, deviceidx, safe_mode, verify_mode, worksize, nthreads, nrows, ncols, invsize); if (!vocp) { return 1; } vg_opencl_loop(vocp); vg_ocl_context_free(vocp); return 0; }