1

I am trying to build small app to generate Bitcoin Address (for sake of understanding).
I use OpenSSL library.
I managed to convert private key to public key, hashed public key with sha256, and result was fine. But, then, problem appears when I try to run sha256 result trough ripemd160.
- I tested ripemd160 function with plain string and it works fine
- I did converted sha256 result to string
- Still I get wrong result

Here's my main:

int _tmain(int argc, _TCHAR* argv[])
{
    char sha256_buffer[65];
    char ripemd160_buffer[41];
    char *pvt_key = "18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725";
    unsigned char *pub_hex = priv2pub((const unsigned char *)pvt_key, POINT_CONVERSION_UNCOMPRESSED );
    //printf("%s\n", pub_hex);
    std::string pub_key_string = hex_to_string(reinterpret_cast<char*>(pub_hex));
    sha256(&pub_key_string[0], sha256_buffer);
    printf("%s\n", sha256_buffer);
    std::string hash256_string = hex_to_string(reinterpret_cast<char*>(sha256_buffer));
    ripemd160(&hash256_string[0], ripemd160_buffer);
    printf("%s\n", ripemd160_buffer);
    return 0;
}

Here's my ripemd160 function:

void ripemd160(char *string, char outputBuffer[41])
{
    unsigned char hash[RIPEMD160_DIGEST_LENGTH];
    RIPEMD160_CTX ripemd160;
    RIPEMD160_Init(&ripemd160);
    RIPEMD160_Update(&ripemd160, string, strlen(string));
    RIPEMD160_Final(hash, &ripemd160);
    for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; i++)
    {
        sprintf_s(outputBuffer + (i * 2), sizeof(outputBuffer + (i * 2)), "%02x", hash[i]);
    }
    outputBuffer[40] = 0;
}

Here's my hex to string function:

string hex_to_string(const string& in) 
{
    string output;
    if ((in.length() % 2) != 0) {
        throw runtime_error("String is not valid length ...");
    }
    size_t cnt = in.length() / 2;
    for (size_t i = 0; cnt > i; ++i) {
        uint32_t s = 0;
        stringstream ss;
        ss << hex << in.substr(i * 2, 2);
        ss >> s;
        output.push_back(static_cast<unsigned char>(s));
    }
    return output;
}

I am using example from
https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses

This is the Ripemd-160 I suppose to get:
010966776006953D5567439E5E39F86A0D273BEE

This is the Ripemd-160 I am actually getting:
6c9814cf2a93131c8d3263158896e786de7a3f21

Warren Sergent
  • 2,542
  • 4
  • 36
  • 42
RogerT
  • 61
  • 1
  • 7

1 Answers1

1

You should be passing in the raw bytes of the SHA-256 hash to the RIPEMD-160 function, instead of first converting the SHA-256 hash into a hex string.

You can verify this using the openssl command-line tool.

RIPEMD-160 of the raw bytes, which matches the expected value:

$ echo -n '600FFE422B4E00731A59557A5CCA46CC183944191006324A447BDB2D98D4B408' |
> xxd -p -r | openssl rmd160
(stdin)= 010966776006953d5567439e5e39f86a0d273bee

RIPEMD-160 of the hex string, which doesn't match the expected value:

$ echo -n '600FFE422B4E00731A59557A5CCA46CC183944191006324A447BDB2D98D4B408' |
> openssl rmd160
(stdin)= 1435727e0369ab470035797c66215799f258188b

Similarly, you should also be passing in the raw bytes of the public key to the SHA-256 function, instead of first converting the public key into a hex string.

SHA-256 of the raw bytes of the public key, which matches the expected value:

$ echo -n '0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6' |
> xxd -p -r | openssl sha256
(stdin)= 600ffe422b4e00731a59557a5cca46cc183944191006324a447bdb2d98d4b408

SHA-256 of the public key as a hex string, which doesn't match the expected value:

$ echo -n '0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6' |
> openssl sha256
(stdin)= 32511e82d56dcea68eb774094e25bab0f8bdd9bc1eca1ceeda38c7a43aceddce
Binary Birch Tree
  • 15,140
  • 1
  • 17
  • 13
  • I tried that in this way (change in main):
    ripemd160(sha256_buffer, ripemd160_buffer);
    printf("%s\n", ripemd160_buffer);
    – RogerT May 08 '16 at 09:23
  • `sha256_buffer` contains raw bytes. But I get this output `4c15742656730a77232d1d67dba82f065bd72e67`. I am using Qt5.5. c++, can you please explain me in code. Thanks. – RogerT May 08 '16 at 09:31
  • You should also be passing in the raw bytes of the public key to the `SHA-256` function, instead of first converting the public key into a hex string. – Binary Birch Tree May 08 '16 at 15:55
  • If I pass raw bytes to SHA-256, I am getting wrong output. After hex_to_string conversion SHA-256 output is right. But this, for some reason doesn't work with RIPEMD-160 function. Do you have any other suggestions? – RogerT May 08 '16 at 17:23
  • You can use the `openssl` command-line tool to prove to yourself that passing in the raw bytes will produce the expected value, as shown in the answer. You should double-check that your code is receiving the correct inputs and producing the correct outputs at each step. – Binary Birch Tree May 08 '16 at 19:29