dimanche 28 mai 2017

Modify vanitygen/keyconv to generate deterministic bitcoin address

Vanitygen is a C program software that permits to generate a Bitcoin address starting with a specific string (for example starting with "JohnDoe" like 1JohnDoeXku52yT5jhYht4852HVg547).

Keyconv is part of the Vanitygen toolset, and is a C program that permits to generate a random bitcoin Address/Private key pair, using ECDSA algorithm for the random factor.

Sources can be found here : http://ift.tt/1dRmOqc

How generating Bitcoin PrivateKey/Address works?

Basically, a bitcoin private key is a number, to which are applied mathematical and cryptographic calculations. The result of these calculations is the Bitcoin WIF Private Key (WIF for Wallet Import Format ). Once you have that Private Key you can generate the Bitcoin Address with other mathematical/cryptographic calculations. The valid range for the initial random number is between 1 and 115792089237316195423570985008687907852837564279074904382605163141518161494336 inclusive.

A description of the different calculations performed can be found here : http://ift.tt/1l34mjq

How keyconv works?

It takes a random number from the ECDSA algorithm (included in the OpenSSL library) and then performs the different mathematical/cryptographic calculations to generate Bitcoin Private Key and associated Bitcoin Address.

Here is an extract of keyconv.c with the portion of code that interest us for the problem :

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>

#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/obj_mac.h>

int
main(int argc, char **argv)
{
    char pwbuf[128];
    char ecprot[128];
    char pbuf[1024];
    const char *key_in;
    const char *pass_in = NULL;
    const char *key2_in = NULL;
    EC_KEY *pkey;
    int parameter_group = -1;
    int privtype, addrtype;
    int pkcs8 = 0;
    int pass_prompt = 0;
    int verbose = 0;
    int generate = 0;
    int opt;
    int res;

    while ((opt = getopt(argc, argv, "8E:ec:vG")) != -1) {
        switch (opt) {
        /* ... */
        case 'G':
            generate = 1;
            break;
        default:
            usage(argv[0]);
            return 1;
        }
    }


    OpenSSL_add_all_algorithms();

    pkey = EC_KEY_new_by_curve_name(NID_secp256k1);

    /* How do I print the value of pkey? */

    if (generate) {
        unsigned char *pend = (unsigned char *) pbuf;
        addrtype = 0;
        privtype = 128;
        EC_KEY_generate_key(pkey);
        res = i2o_ECPublicKey(pkey, &pend);
        fprintf(stderr, "Pubkey (hex): ");
        dumphex((unsigned char *)pbuf, res);
        fprintf(stderr, "Privkey (hex): ");
        dumpbn(EC_KEY_get0_private_key(pkey));
        vg_encode_address(EC_KEY_get0_public_key(pkey),
                  EC_KEY_get0_group(pkey),
                  addrtype, ecprot);
        printf("Address: %s\n", ecprot);
        vg_encode_privkey(pkey, privtype, ecprot);
        printf("Privkey: %s\n", ecprot);
        return 0;
    }

/* .... */

What's the purpose of modifying keyconv?

I would like to slightly change the "randomness factor", by being able to avoid the first few trillions at the beginning and at the end of the "huge number" range. To avoid some standard brute force attack.

I would like to modify keyconv code in order to be able to generate a deterministic bitcoin address.

By deterministic bitcoin address, I mean 2 things :

1 - to be able to generate the PrivateKey/Address pair from an input "huge number" (-d for deterministic)

keyconv -d <huge number>

Example : keyconv -d 115792089237316195423570985008687907852837564279074904382605163141518161494336

would return me the Private Key / Address pair for the input number "11579208923731..."

2- to be able to generate the PrivateKey/Address pair from an input range (percentage of the global range of all possible numbers) (-r for range)

keyconv -r <floor percentage> <ceil percentage>

Example : keyconv -r 20 40

will return me a random Private Key / Address pair taking the range 20% of maximal number to 40% of maximal number

Since I'm not really used to C programming, I am trying few things but can't get it to work. From reading the code, I suspect that I will have to pass my huge number value to the functions vg_encode_address() and vg_encode_privkey() but I first need to know what kind of arguments it deals with.

The problem is that we deal with huge numbers, and that the default types included in C do not handle this type of numbers. So we have to create specific types.

First question:

I'm trying to start with getting the "content value" that the pointer pkey is pointing to. I tried to print it via :

printf("pkey value : %s\n", *pkey);

but it returned me the following error :

cc -ggdb -O3 -Wall   -c -o keyconv.o keyconv.c
keyconv.c: In function ‘main’:
keyconv.c:100:30: error: dereferencing pointer to incomplete type ‘EC_KEY {aka struct ec_key_st}’
  printf("pkey value : %s\n", *pkey);
                              ^
<builtin>: recipe for target 'keyconv.o' failed
make: *** [keyconv.o] Error 1

So I understand that I need to specify a type 'EC_KEY' in the print function, but how do I do that?

Second question:

Has anyone already tried to code what I'm trying to do?




Aucun commentaire:

Enregistrer un commentaire