From 7ee7d9b0aa5b3841d17f0be14d2cc00f719b579f Mon Sep 17 00:00:00 2001 From: Scott Alfter Date: Thu, 16 May 2013 10:29:03 -0700 Subject: [PATCH] add Litecoin address and compressed address support --- pattern.c | 16 ++++++++++++---- pattern.h | 1 + util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ util.h | 3 +++ vanitygen.c | 28 +++++++++++++++++++++------- 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/pattern.c b/pattern.c index 79e2091..b925a47 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)) { 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..7c66cfb 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]); @@ -311,10 +311,11 @@ usage(const char *name) "-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" "-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 +359,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, "Lvqnrik1eE:P:NTX:F:t:h?f:o:s:")) != -1) { switch (opt) { + case 'c': + compressed = 1; + break; case 'v': verbose = 2; break; @@ -389,6 +394,11 @@ main(int argc, char **argv) privtype = 180; scriptaddrtype = -1; break; + case 'L': + addrtype = 48; + privtype = 176; + scriptaddrtype = -1; + break; case 'T': addrtype = 111; privtype = 239; @@ -402,7 +412,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 +557,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;