2013-07-16 26 views
8

Piszę prosty kod w C++ za pomocą OpenSSL, aby wygenerować poprawny adres bitcoin - parę kluczy prywatnych.Generowanie adresu Bitcoin z klucza publicznego ECDSA

Używam tego fragmentu kodu, aby wygenerować klucz publiczny z danymi sześciokątnej formie klucza prywatnego:

#include <stdio.h> 
#include <stdlib.h> 
#include <openssl/ec.h> 
#include <openssl/obj_mac.h> 
#include <openssl/bn.h> 

int main() 
{ 
    EC_KEY *eckey = NULL; 
    EC_POINT *pub_key = NULL; 
    const EC_GROUP *group = NULL; 
    BIGNUM start; 
    BIGNUM *res; 
    BN_CTX *ctx; 



    BN_init(&start); 
    ctx = BN_CTX_new(); // ctx is an optional buffer to save time from allocating and deallocating memory whenever required 

    res = &start; 
    BN_hex2bn(&res,"30caae2fcb7c34ecadfddc45e0a27e9103bd7cfc87730d7818cc096b1266a683"); 
    eckey = EC_KEY_new_by_curve_name(NID_secp256k1); 
    group = EC_KEY_get0_group(eckey); 
    pub_key = EC_POINT_new(group); 

    EC_KEY_set_private_key(eckey, res); 

    /* pub_key is a new uninitialized `EC_POINT*`. priv_key res is a `BIGNUM*`. */ 
    if (!EC_POINT_mul(group, pub_key, res, NULL, NULL, ctx)) 
     printf("Error at EC_POINT_mul.\n"); 

    EC_KEY_set_public_key(eckey, pub_key); 

    char *cc = EC_POINT_point2hex(group, pub_key, 4, ctx); 

    char *c=cc; 

    int i; 

    for (i=0; i<130; i++) // 1 byte 0x42, 32 bytes for X coordinate, 32 bytes for Y coordinate 
    { 
     printf("%c", *c++); 
    } 

    printf("\n"); 

    BN_CTX_free(ctx); 

    free(cc); 

    return 0; 
} 

co chcę, aby przekształcić ten klucz publiczny adres Bitcoin - co to najszybszy sposób, aby go osiągnąć ? Nie wiem jak stworzyć RIPEMD160 z BIGNUM OpenSSL. A może jest inne, lepsze rozwiązanie?

+1

Czy masz wynikowy kod? brzmi interesująco – Nande

Odpowiedz

12

Zakładając, co robisz jest oparte na tej konwersji:

enter image description here

opiszę, co można zrobić w pseudo-kod:

pierwszym ekstraktem x, y z kluczem publicznym .

// get x and y from Public key "point" 
EC_POINT_get_affine_coordinates_GFp(group, pub_key, x, y, ctx); 
// convert BIGNUMs x, y into binary form 
BN_bn2bin(x,x_char); 
BN_bn2bin(y,y_char); 

Następnie należy kilkakrotnie wykonać syntezę wiadomości, w tym 3 sha256 i 1 ripemd160. W poniższym pseudo-kodzie pokażę ci, jak zrobić ripemd160. Aby zrobić sha256 z EVP_MD, wystarczy wymienić EVP_ripemd160() na EVP_sha256() i zaktualizować (wprowadzić do EVP_MD) swoją wiadomość wejściową jednym lub kilkoma EVP_DigestUpdate().

EVP_MD_CTX ctx; 
EVP_MD_CTX_init(&md_ctx); 
EVP_DigestInit(&md_ctx, EVP_ripemd160()); 
// hdr = 0x04 
EVP_DigestUpdate(&md_ctx,hdr,1); 
EVP_DigestUpdate(&md_ctx,x_char,32); 
EVP_DigestUpdate(&md_ctx,y_char,32); 
// put message degest into dgst and set length to dgstlen 
EVP_DigestFinal(&md_ctx,dgst,&dgstlen); 
EVP_MD_CTX_cleanup(&md_ctx); 

Lub łatwiejszy sposób, zadzwoń sha256() i ripemd160() bezpośrednio. Ale przed wywołaniem funkcji skrótu należy przygotować komunikat wejściowy: sha256() lub.

25-bajtowy adres binarny jest wynikiem ripemd160, wraz z pierwszymi 4 bajtami sumy kontrolnej 32-bajtowej. Musisz znaleźć sposób na przekonwertowanie go z Base 256 do Base 58. Nie sądzę, żeby to było wsparcie OpenSSL.

+0

Dzięki! Bardzo mi to pomogło! – mpestkow