diff --git a/README b/README index c2c4790..bcf1305 100644 --- a/README +++ b/README @@ -46,6 +46,13 @@ Pattern: 1Love Address: 1LoveRg5t2NCDLUZh6Q8ixv74M5YGVxXaN Privkey: 5JLUmjZiirgziDmWmNprPsNx8DYwfecUNk1FQXmDPaoKB36fX1o +example for a peercoin address generation is: +$ ./vanitygen -G PFuzzy +Difficulty: 264104224 +Pattern: PFuzzy +Address: PFuzzyiHvUuwh6VbUTy2PXGqDtFA3kUcZQ +Privkey: 78yCPnuXLe8cD2PUjjy1iq23WbSPhw3cp1aLiGHZz9Df9uZGKgg + Currently, it is difficult to import the private key into bitcoin. Sipa's showwallet branch has a new command called "importprivkey" that accepts the base-58 encoded private key. Vanitygen has been tested to diff --git a/oclvanitygen.c b/oclvanitygen.c index 9755ef6..d476e16 100644 --- a/oclvanitygen.c +++ b/oclvanitygen.c @@ -58,6 +58,7 @@ usage(const char *name) "-k Keep pattern and continue search after finding a match\n" "-1 Stop after first match\n" "-N Generate namecoin address\n" +"-G Generate Peercoin address\n" "-T Generate bitcoin testnet address\n" "-X Generate address with the given version\n" "-e Encrypt private keys, prompt for password\n" @@ -123,7 +124,7 @@ main(int argc, char **argv) int i; while ((opt = getopt(argc, argv, - "vqik1NTX:eE:p:P:d:w:t:g:b:VSh?f:o:s:D:")) != -1) { + "vqik1NGTX:eE:p:P:d:w:t:g:b:VSh?f:o:s:D:")) != -1) { switch (opt) { case 'v': verbose = 2; @@ -144,6 +145,10 @@ main(int argc, char **argv) addrtype = 52; privtype = 180; break; + case 'G': + addrtype = 55; + privtype = 183; + break; case 'T': addrtype = 111; privtype = 239; diff --git a/pattern.c b/pattern.c index 79e2091..c267e4e 100644 --- a/pattern.c +++ b/pattern.c @@ -528,9 +528,14 @@ vg_output_match_console(vg_context_t *vcp, EC_KEY *pkey, const char *pattern) } assert(EC_KEY_check_key(pkey)); - vg_encode_address(ppnt, - EC_KEY_get0_group(pkey), - vcp->vc_pubkeytype, addr_buf); + if (vcp->vc_compressed) + vg_encode_address_compressed(ppnt, + EC_KEY_get0_group(pkey), + vcp->vc_pubkeytype, addr_buf); + else + vg_encode_address(ppnt, + EC_KEY_get0_group(pkey), + vcp->vc_pubkeytype, addr_buf); if (isscript) vg_encode_script_address(ppnt, EC_KEY_get0_group(pkey), @@ -550,7 +555,10 @@ vg_output_match_console(vg_context_t *vcp, EC_KEY *pkey, const char *pattern) } } if (!vcp->vc_key_protect_pass) { - vg_encode_privkey(pkey, vcp->vc_privtype, privkey_buf); + if (vcp->vc_compressed) + vg_encode_privkey_compressed(pkey, vcp->vc_privtype, privkey_buf); + else + vg_encode_privkey(pkey, vcp->vc_privtype, privkey_buf); } if (!vcp->vc_result_file || (vcp->vc_verbose > 0)) { @@ -1401,6 +1409,10 @@ vg_prefix_context_add_patterns(vg_context_t *vcp, ats = "namecoin"; bw = "\"M\" or \"N\""; break; + case 55: + ats = "peercoin"; + bw = "\"P\""; + break; default: break; } diff --git a/pattern.h b/pattern.h index b440751..ffa88c4 100644 --- a/pattern.h +++ b/pattern.h @@ -88,6 +88,7 @@ enum vg_format { /* Application-level context, incl. parameters and global pattern store */ struct _vg_context_s { + int vc_compressed; int vc_addrtype; int vc_privtype; unsigned long vc_npatterns; diff --git a/util.c b/util.c index 165f82c..aa76155 100644 --- a/util.c +++ b/util.c @@ -259,6 +259,30 @@ vg_encode_address(const EC_POINT *ppoint, const EC_GROUP *pgroup, vg_b58_encode_check(binres, sizeof(binres), result); } +void +vg_encode_address_compressed(const EC_POINT *ppoint, const EC_GROUP *pgroup, + int addrtype, char *result) +{ + unsigned char eckey_buf[128], *pend; + unsigned char binres[21] = {0,}; + unsigned char hash1[32]; + + pend = eckey_buf; + + EC_POINT_point2oct(pgroup, + ppoint, + POINT_CONVERSION_COMPRESSED, + eckey_buf, + sizeof(eckey_buf), + NULL); + pend = eckey_buf + 0x21; + binres[0] = addrtype; + SHA256(eckey_buf, pend - eckey_buf, hash1); + RIPEMD160(hash1, sizeof(hash1), &binres[1]); + + vg_b58_encode_check(binres, sizeof(binres), result); +} + void vg_encode_script_address(const EC_POINT *ppoint, const EC_GROUP *pgroup, int addrtype, char *result) @@ -306,6 +330,26 @@ vg_encode_privkey(const EC_KEY *pkey, int addrtype, char *result) vg_b58_encode_check(eckey_buf, 33, result); } +void +vg_encode_privkey_compressed(const EC_KEY *pkey, int addrtype, char *result) +{ + unsigned char eckey_buf[128]; + const BIGNUM *bn; + int nbytes; + + bn = EC_KEY_get0_private_key(pkey); + + eckey_buf[0] = addrtype; + nbytes = BN_num_bytes(bn); + assert(nbytes <= 32); + if (nbytes < 32) + memset(eckey_buf + 1, 0, 32 - nbytes); + BN_bn2bin(bn, &eckey_buf[33 - nbytes]); + eckey_buf[nbytes+1] = 1; + + vg_b58_encode_check(eckey_buf, 34, result); +} + int vg_set_privkey(const BIGNUM *bnpriv, EC_KEY *pkey) { diff --git a/util.h b/util.h index 5969b87..850fad5 100644 --- a/util.h +++ b/util.h @@ -38,10 +38,13 @@ extern int vg_b58_decode_check(const char *input, void *buf, size_t len); extern void vg_encode_address(const EC_POINT *ppoint, const EC_GROUP *pgroup, int addrtype, char *result); +extern void vg_encode_address_compressed(const EC_POINT *ppoint, const EC_GROUP *pgroup, + int addrtype, char *result); extern void vg_encode_script_address(const EC_POINT *ppoint, const EC_GROUP *pgroup, int addrtype, char *result); extern void vg_encode_privkey(const EC_KEY *pkey, int addrtype, char *result); +extern void vg_encode_privkey_compressed(const EC_KEY *pkey, int addrtype, char *result); extern int vg_set_privkey(const BIGNUM *bnpriv, EC_KEY *pkey); extern int vg_decode_privkey(const char *b58encoded, EC_KEY *pkey, int *addrtype); diff --git a/vanitygen.c b/vanitygen.c index 9d88121..86e4b4d 100644 --- a/vanitygen.c +++ b/vanitygen.c @@ -114,7 +114,7 @@ vg_thread_loop(void *arg) } else { eckey_buf = hash_buf; - hash_len = 65; + hash_len = (vcp->vc_compressed)?33:65; } while (!vcp->vc_halt) { @@ -194,11 +194,11 @@ vg_thread_loop(void *arg) for (i = 0; i < nbatch; i++, vxcp->vxc_delta++) { /* Hash the public key */ len = EC_POINT_point2oct(pgroup, ppnt[i], - POINT_CONVERSION_UNCOMPRESSED, + (vcp->vc_compressed)?POINT_CONVERSION_COMPRESSED:POINT_CONVERSION_UNCOMPRESSED, eckey_buf, - 65, + (vcp->vc_compressed)?33:65, vxcp->vxc_bnctx); - assert(len == 65); + assert(len == 65 || len == 33); SHA256(hash_buf, hash_len, hash1); RIPEMD160(hash1, sizeof(hash1), &vxcp->vxc_binres[1]); @@ -308,13 +308,16 @@ usage(const char *name) "-n Simulate\n" "-r Use regular expression match instead of prefix\n" " (Feasibility of expression is not checked)\n" +"-c Use compressed address\n" "-i Case-insensitive prefix search\n" "-k Keep pattern and continue search after finding a match\n" "-1 Stop after first match\n" +"-L Generate litecoin address\n" "-N Generate namecoin address\n" +"-G Generate Peercoin address\n" "-T Generate bitcoin testnet address\n" "-X Generate address with the given version\n" -"-F Generate address with the given format (pubkey or script)\n" +"-F Generate address with the given format (pubkey, compressed, script)\n" "-P Specify base public key for piecewise key generation\n" "-e Encrypt private keys, prompt for password\n" "-E Encrypt private keys with (UNSAFE)\n" @@ -358,11 +361,15 @@ main(int argc, char **argv) int pattfpi[MAX_FILE]; int npattfp = 0; int pattstdin = 0; + int compressed = 0; int i; - while ((opt = getopt(argc, argv, "vqnrik1eE:P:NTX:F:t:h?f:o:s:")) != -1) { + while ((opt = getopt(argc, argv, "Lvqnrcik1eE:P:NGTX:F:t:h?f:o:s:")) != -1) { switch (opt) { + case 'c': + compressed = 1; + break; case 'v': verbose = 2; break; @@ -389,6 +396,16 @@ main(int argc, char **argv) privtype = 180; scriptaddrtype = -1; break; + case 'L': + addrtype = 48; + privtype = 176; + scriptaddrtype = -1; + break; + case 'G': + addrtype = 55; + privtype = 183; + scriptaddrtype = -1; + break; case 'T': addrtype = 111; privtype = 239; @@ -402,7 +419,10 @@ main(int argc, char **argv) case 'F': if (!strcmp(optarg, "script")) format = VCF_SCRIPT; - else + else + if (!strcmp(optarg, "compressed")) + compressed = 1; + else if (strcmp(optarg, "pubkey")) { fprintf(stderr, "Invalid format '%s'\n", optarg); @@ -544,6 +564,7 @@ main(int argc, char **argv) caseinsensitive); } + vcp->vc_compressed = compressed; vcp->vc_verbose = verbose; vcp->vc_result_file = result_file; vcp->vc_remove_on_match = remove_on_match;