Skip to content

Commit

Permalink
Support customizing prefix of private key (binary)
Browse files Browse the repository at this point in the history
  • Loading branch information
10gic committed Jan 2, 2021
1 parent 2fc4e80 commit 055f932
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 26 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## If compiling on mac, comment out LIBS and CFLAGS below, and use the MacOS ones below
LIBS=-lpcre -lcrypto -lm -lpthread
CFLAGS=-ggdb -O3 -Wall
# CFLAGS=-ggdb -O3 -Wall -I /usr/local/cuda-10.2/include/

## If compiling on a mac make sure you install and use homebrew and run the following command `brew install pcre pcre++`
## Uncomment lines below and run `make all`
Expand Down
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
Vanity address generator for BTC, ETH, LTC, etc (more than 100 crypto currencies).

# Build
Run:
Intall building dependencies in Redhat/CentOS:
```
$ yum install openssl-devel
$ yum install libcurl-devel
```

Build executable file:
```
$ make # build: vanitygen++ keyconv
$ make all # build: vanitygen++ keyconv oclvanitygen++ oclvanityminer
Expand Down Expand Up @@ -52,6 +58,27 @@ ETH Privkey: 0xdb3813534c0c9595f9b8b35d6f544827065b33930ae42c38a9d7ce41a1d74669

If you have OpenCL-compatible GPU, please use `oclvanitygen++`, it's faster.

# Solve Puzzle
This tool can be used for solving the [Bitcoin puzzle](https://bitcointalk.org/index.php?topic=1306983.0).

For example, solve puzzle 6:
```
$ ./vanitygen++ -F compressed -Z 0000000000000000000000000000000000000000000000000000000000000000 -l $((256-6)) 1PitScNLyp2HCygzad
Difficulty: 376259307977702824629384382540
Pattern: 1PitScNLyp2HCygzad
Address: 1PitScNLyp2HCygzadCh7FveTnfmpPbfp8
Privkey: KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU7Tmu6qHxS
```

Solve puzzle 20:
```
$ ./vanitygen++ -F compressed -Z 0000000000000000000000000000000000000000000000000000000000000000 -l $((256-20)) 1HsMJxNiV7TLxmoF6u
Difficulty: 376259307977702824629384382540
Pattern: 1HsMJxNiV7TLxmoF6u
Address: 1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum
Privkey: KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rHfuE2Tg4nJW
```

# Credit
Many thanks to following projects:
1. https://github.com/samr7/vanitygen
Expand Down
22 changes: 13 additions & 9 deletions oclengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -2100,24 +2100,28 @@ vg_opencl_loop(vg_exec_context_t *arg)
vg_exec_context_upgrade_lock(vxcp);

pattern_generation = vcp->vc_pattern_generation;

regen_key:
/* Generate a new random private key */
EC_KEY_generate_key(pkey);
npoints = 0;
if (vcp->vc_privkey_prefix_length > 0) {
if (vcp->vc_privkey_prefix_nbits > 0) {
/* Adjust private key to meet the requirement of privkey prefix (specified by option -Z) */
BIGNUM *pkbn = BN_dup(EC_KEY_get0_private_key(pkey));
unsigned char pkey_arr[32];
assert(BN_bn2bin(pkbn, pkey_arr) < 33);
memcpy((char *) pkey_arr, vcp->vc_privkey_prefix, vcp->vc_privkey_prefix_length);
for (i = 0; i < vcp->vc_privkey_prefix_length / 2; i++) {
int k = pkey_arr[i];
pkey_arr[i] = pkey_arr[vcp->vc_privkey_prefix_length - 1 - i];
pkey_arr[vcp->vc_privkey_prefix_length - 1 - i] = k;
}
copy_nbits((unsigned char *) pkey_arr, (unsigned char *)vcp->vc_privkey_prefix, vcp->vc_privkey_prefix_nbits);
BN_bin2bn(pkey_arr, 32, pkbn);
EC_KEY_set_private_key(pkey, pkbn);
if (BN_is_zero(pkbn)) {
fprintf(stderr, "the generated private key is zero, regenerate it\n");
goto regen_key;
}
// FIXME: private key (pbkn) may be too big if prefix specified by -Z has many FF
EC_KEY_set_private_key(pkey, pkbn); /* set private key in pkey */

EC_POINT *origin = EC_POINT_new(pgroup);
/* EC_POINT_mul: compute public_key = k * private_key
here, origin is public_key, pkbn is private_key
save public_key into 2nd param (origin) */
EC_POINT_mul(pgroup, origin, pkbn, NULL, NULL, vxcp->vxc_bnctx);
EC_KEY_set_public_key(pkey, origin);
}
Expand Down
29 changes: 26 additions & 3 deletions oclvanitygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ usage(const char *name)
"-o <file> Write pattern matches to <file>\n"
"-s <file> Seed random number generator from <file>\n"
"-Z <prefix> Private key prefix in hex (1Address.io Dapp front-running protection)\n"
"-l <nbits> Specify the bits of prefix, only relevant when -Z is specified\n"
"-z Format output of matches in CSV(disables verbose mode)\n"
" Output as [COIN],[PREFIX],[ADDRESS],[PRIVKEY]\n",
version, name);
Expand Down Expand Up @@ -131,6 +132,7 @@ main(int argc, char **argv)
int opened = 0;
char privkey_prefix[32];
int privkey_prefix_length = 0;
int privkey_prefix_nbits = 0;

FILE *pattfp[MAX_FILE], *fp;
int pattfpi[MAX_FILE];
Expand All @@ -142,7 +144,7 @@ main(int argc, char **argv)
int i;

while ((opt = getopt(argc, argv,
"vqrik1zC:X:Y:F:eE:p:P:d:w:t:g:b:VSh?f:o:s:D:Z:a:")) != -1) {
"vqrik1zC:X:Y:F:eE:p:P:d:w:t:g:b:VSh?f:o:s:D:Z:a:l:")) != -1) {
switch (opt) {
case 'r':
regex = 1;
Expand Down Expand Up @@ -368,9 +370,12 @@ main(int argc, char **argv)
for (i = 0; i < privkey_prefix_length; i++) {
int value; // Can't sscanf directly to char array because of overlapping on Win32
sscanf(&optarg[i*2], "%2x", &value);
privkey_prefix[privkey_prefix_length - 1 - i] = value;
privkey_prefix[i] = value;
}
break;
case 'l':
privkey_prefix_nbits = atoi(optarg);
break;
default:
usage(argv[0]);
return 1;
Expand All @@ -386,6 +391,24 @@ main(int argc, char **argv)
}
#endif

/* Option -Z can be used with or without option -l
but, option -l must use together with option -Z */
if (privkey_prefix_length == 0) { /* -Z not specified */
if (privkey_prefix_nbits > 0) { /* -l specified */
fprintf(stderr, "-l must use together with -Z)\n");
return 1;
}
} else if (privkey_prefix_length > 0) { /* -Z specified */
if (privkey_prefix_nbits == 0) { /* -l not specified */
privkey_prefix_nbits = privkey_prefix_length * 8;
} else if (privkey_prefix_nbits > 0) { /* -l specified */
if (privkey_prefix_nbits > privkey_prefix_length * 8) {
fprintf(stderr, "bits (specified by -l) is too big, must small than bits of prefix (%d bits)\n", privkey_prefix_length * 8);
return 1;
}
}
}

if (caseinsensitive && regex)
fprintf(stderr,
"WARNING: case insensitive mode incompatible with "
Expand Down Expand Up @@ -430,7 +453,7 @@ main(int argc, char **argv)
vcp->vc_pubkeytype = addrtype;
vcp->vc_pubkey_base = pubkey_base;
memcpy(vcp->vc_privkey_prefix, privkey_prefix, privkey_prefix_length);
vcp->vc_privkey_prefix_length = privkey_prefix_length;
vcp->vc_privkey_prefix_nbits = privkey_prefix_nbits;

vcp->vc_output_match = vg_output_match_console;
vcp->vc_output_timing = vg_output_timing_console;
Expand Down
2 changes: 1 addition & 1 deletion pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ struct _vg_context_s {
int vc_pubkeytype;
EC_POINT *vc_pubkey_base;
char vc_privkey_prefix[32];
int vc_privkey_prefix_length;
int vc_privkey_prefix_nbits;
int vc_halt;

vg_exec_context_t *vc_threads;
Expand Down
18 changes: 18 additions & 0 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1455,3 +1455,21 @@ eth_encode_checksum_addr(void * input, int inlen, char *output, int outlen)
}
}
}

// Like memcpy, but length specified by bits (rather than bytes)
void copy_nbits(unsigned char *dst, unsigned char *src, int nbits) {
// An example:
// dst(input): MMMMMMMM NNNNNNNN
// src: IIIIIIII JJJJJJJJ
// nbits: 11
// dst(output): IIIIIIII JJJNNNNN
int nbytes = (nbits / 8) + 1; // (11 / 8) + 1 = 2
int extra_nbits = nbytes * 8 - nbits; // 2 * 8 - 11 = 5
char tab[8] = {0, 1, 3 /* 2 bits 1 */, 7 /* 3 bits 1 */, 15 /* 4 bits 1 */, 31 /* 5 bits 1 */,
63 /* 6 bits 1 */, 127 /* 7 bits 1 */};
unsigned char backup = dst[nbytes - 1]; // NNNNNNNN
memcpy(dst, src, nbytes);
unsigned char after = dst[nbytes - 1]; // JJJJJJJJ
dst[nbytes - 1] = (backup & tab[extra_nbits]) // 000NNNNN
| (after & ~tab[extra_nbits]); // JJJ00000
}
1 change: 1 addition & 0 deletions util.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,5 @@ extern void eth_pubkey2addr(const unsigned char* pubkey_buf, int addrformat, uns

extern void eth_encode_checksum_addr(void *input, int inlen, char *output, int outlen);

extern void copy_nbits(unsigned char *dst, unsigned char *src, int nbits);
#endif /* !defined (__VG_UTIL_H__) */
55 changes: 43 additions & 12 deletions vanitygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/objects.h>

#include "pattern.h"
#include "util.h"
Expand Down Expand Up @@ -127,24 +128,29 @@ vg_thread_loop(void *arg)
while (!vcp->vc_halt) {
if (++npoints >= rekey_at) {
vg_exec_context_upgrade_lock(vxcp);
regen_key:
/* Generate a new random private key */
EC_KEY_generate_key(pkey);
if (vcp->vc_privkey_prefix_length > 0) {
if (vcp->vc_privkey_prefix_nbits > 0) {
/* Adjust private key to meet the requirement of privkey prefix (specified by option -Z) */
BIGNUM *pkbn = BN_dup(EC_KEY_get0_private_key(pkey));
unsigned char pkey_arr[32];
assert(BN_bn2bin(pkbn, pkey_arr) < 33);
memcpy((char *) pkey_arr, vcp->vc_privkey_prefix, vcp->vc_privkey_prefix_length);
for (i = 0; i < vcp->vc_privkey_prefix_length / 2; i++) {
int k = pkey_arr[i];
pkey_arr[i] = pkey_arr[vcp->vc_privkey_prefix_length - 1 - i];
pkey_arr[vcp->vc_privkey_prefix_length - 1 - i] = k;
}
copy_nbits((unsigned char *) pkey_arr, (unsigned char *)vcp->vc_privkey_prefix, vcp->vc_privkey_prefix_nbits);
BN_bin2bn(pkey_arr, 32, pkbn);
EC_KEY_set_private_key(pkey, pkbn);
if (BN_is_zero(pkbn)) {
fprintf(stderr, "the generated private key is zero, regenerate it\n");
goto regen_key;
}
// FIXME: private key (pbkn) may be too big if prefix specified by -Z has many FF
EC_KEY_set_private_key(pkey, pkbn); /* set private key in pkey */

EC_POINT *origin = EC_POINT_new(pgroup);
/* EC_POINT_mul: compute public_key = k * private_key
here, origin is public_key, pkbn is private_key
save public_key into 2nd param (origin) */
EC_POINT_mul(pgroup, origin, pkbn, NULL, NULL, vxcp->vxc_bnctx);
EC_KEY_set_public_key(pkey, origin);
EC_KEY_set_public_key(pkey, origin); /* set public key in pkey */
}
npoints = 0;

Expand Down Expand Up @@ -194,6 +200,8 @@ vg_thread_loop(void *arg)
for (nbatch = 0;
(nbatch < ptarraysize) && (npoints < rekey_at);
nbatch++, npoints++) {
/* compute public keys from continuous private key,
save public keys into array ppnt */
EC_POINT_add(pgroup,
ppnt[nbatch],
ppnt[nbatch],
Expand Down Expand Up @@ -332,6 +340,7 @@ usage(const char *name)
"-o <file> Write pattern matches to <file>\n"
"-s <file> Seed random number generator from <file>\n"
"-Z <prefix> Private key prefix in hex (1Address.io Dapp front-running protection)\n"
"-l <nbits> Specify the bits of prefix, only relevant when -Z is specified\n"
"-z Format output of matches in CSV(disables verbose mode)\n"
" Output as [COIN],[PREFIX],[ADDRESS],[PRIVKEY]\n",
version, name);
Expand Down Expand Up @@ -368,6 +377,7 @@ main(int argc, char **argv)
EC_POINT *pubkey_base = NULL;
char privkey_prefix[32];
int privkey_prefix_length = 0;
int privkey_prefix_nbits = 0;

FILE *pattfp[MAX_FILE], *fp;
int pattfpi[MAX_FILE];
Expand All @@ -377,7 +387,7 @@ main(int argc, char **argv)

int i;

while ((opt = getopt(argc, argv, "vqnrik1ezE:P:C:X:Y:F:t:h?f:o:s:Z:a:")) != -1) {
while ((opt = getopt(argc, argv, "vqnrik1ezE:P:C:X:Y:F:t:h?f:o:s:Z:a:l:")) != -1) {
switch (opt) {
case 'c':
compressed = 1;
Expand Down Expand Up @@ -565,9 +575,12 @@ main(int argc, char **argv)
for (i = 0; i < privkey_prefix_length; i++) {
int value; // Can't sscanf directly to char array because of overlapping on Win32
sscanf(&optarg[i*2], "%2x", &value);
privkey_prefix[privkey_prefix_length - 1 - i] = value;
privkey_prefix[i] = value;
}
break;
case 'l':
privkey_prefix_nbits = atoi(optarg);
break;
default:
usage(argv[0]);
return 1;
Expand Down Expand Up @@ -658,6 +671,24 @@ main(int argc, char **argv)
return 0;
}

/* Option -Z can be used with or without option -l
but, option -l must use together with option -Z */
if (privkey_prefix_length == 0) { /* -Z not specified */
if (privkey_prefix_nbits > 0) { /* -l specified */
fprintf(stderr, "-l must use together with -Z)\n");
return 1;
}
} else if (privkey_prefix_length > 0) { /* -Z specified */
if (privkey_prefix_nbits == 0) { /* -l not specified */
privkey_prefix_nbits = privkey_prefix_length * 8;
} else if (privkey_prefix_nbits > 0) { /* -l specified */
if (privkey_prefix_nbits > privkey_prefix_length * 8) {
fprintf(stderr, "bits (specified by -l) is too big, must small than bits of prefix (%d bits)\n", privkey_prefix_length * 8);
return 1;
}
}
}

if (caseinsensitive && regex)
fprintf(stderr,
"WARNING: case insensitive mode incompatible with "
Expand Down Expand Up @@ -714,7 +745,7 @@ main(int argc, char **argv)
vcp->vc_pubkeytype = pubkeytype;
vcp->vc_pubkey_base = pubkey_base;
memcpy(vcp->vc_privkey_prefix, privkey_prefix, privkey_prefix_length);
vcp->vc_privkey_prefix_length = privkey_prefix_length;
vcp->vc_privkey_prefix_nbits = privkey_prefix_nbits;

vcp->vc_output_match = vg_output_match_console;
vcp->vc_output_timing = vg_output_timing_console;
Expand Down

0 comments on commit 055f932

Please sign in to comment.