8

OpenSSL を使用して C++ で簡単なコードを作成し、有効なビットコイン アドレスと秘密鍵のペアを生成しています。

このスニペットを使用して、指定された 16 進数形式の秘密鍵から公開鍵を生成しています。

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

私が望むのは、この公開鍵をビットコイン アドレスに変換することです。それを実現する最速の方法は何ですか? OpenSSL の BIGNUM から RIPEMD160 を作成する方法がわかりません。それとも、別のより良い解決策がありますか?

4

1 に答える 1

12

あなたがしていることは、この変換に基づいていると仮定します:

ここに画像の説明を入力

疑似コードでできることを説明します。

まず、公開鍵から x, y を抽出します。

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

次に、3 つの sha256 と 1 つのripemd160 を含む、メッセージ ダイジェストを数回実行する必要があります。次の疑似コードでは、ripemd160 の実行方法を示します。EVP_MD で sha256 を実行するには、 に置き換えEVP_ripemd160()EVP_sha256()、入力メッセージを 1 つまたは複数の で更新 (EVP_MD への入力) します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);

または、より簡単な方法で、直接電話sha256()してください。ただし、ハッシュ関数またはripemd160()を呼び出す前に、入力メッセージを準備する必要があります。sha256()ripemd160()

25 バイトのバイナリ アドレスは、32 バイトのチェックサムの最初の 4 バイトと一緒に、ripemd160 の結果です。Base 256 から Base 58 に変換する方法を見つける必要があります。OpenSSL はそれをサポートしていないと思います。

于 2013-07-17T02:56:06.343 に答える