2013-07-16 19 views
8

Tôi đang viết mã đơn giản trong C++ sử dụng OpenSSL để tạo địa chỉ bitcoin hợp lệ - cặp khóa riêng.Tạo địa chỉ Bitcoin từ ECDSA Public Key

Tôi đang sử dụng đoạn mã này để tạo khóa công khai từ khóa riêng cho hex-form:

#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; 
} 

Những gì tôi muốn là để chuyển đổi Public Key này để Bitcoin địa chỉ - cách nhanh nhất để đạt được nó là gì ? Tôi không biết cách tạo RIPEMD160 từ BIGNUM của OpenSSL. Hoặc có thể có một giải pháp tốt hơn?

+1

bạn có mã kết quả không? nghe có vẻ thú vị – Nande

Trả lời

12

Giả sử những gì bạn đang làm là dựa trên chuyển đổi này:

enter image description here

tôi sẽ mô tả những gì bạn có thể làm trong pseudo-code:

Đầu tiên giải nén x, y từ khóa công khai .

// 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); 

Tiếp theo, bạn cần thực hiện thông báo tiêu hóa nhiều lần, bao gồm 3 sha256 và 1 ripemd160. Trong đoạn mã giả sau tôi sẽ chỉ cho bạn cách làm ripemd160. Để thực hiện sha256 với EVP_MD, chỉ cần thay thế EVP_ripemd160() bằng EVP_sha256() và cập nhật (nhập vào EVP_MD) thông điệp đầu vào của bạn bằng một hoặc nhiều số 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); 

Hoặc cách dễ dàng hơn, hãy gọi sha256()ripemd160() trực tiếp. Nhưng bạn cần chuẩn bị thông điệp đầu vào của mình trước khi gọi hàm băm sha256() hoặc ripemd160().

Địa chỉ nhị phân 25 byte là kết quả của ripemd160, cùng với 4 byte đầu tiên của tổng kiểm tra 32 byte. Bạn cần phải tìm cách chuyển đổi nó từ Base 256 sang Base 58. Tôi không nghĩ OpenSSL hỗ trợ điều đó.

+0

Cảm ơn! Nó đã giúp tôi rất nhiều! – mpestkow

Các vấn đề liên quan