C++ OpenSSL Ripemd-160 给出了错误的输出

标签 c++ openssl bitcoin ripemd

我正在尝试构建一个小应用程序来生成比特币地址(为了理解)。
我使用 OpenSSL 库。
我设法将私钥转换为公钥,用 sha256 散列公钥,结果很好。但是,当我尝试通过 ripemd160 运行 sha256 结果时,问题出现了。
- 我用纯字符串测试了 ripemd160 函数,它工作正常
- 我确实将 sha256 结果转换为字符串
- 我仍然得到错误的结果

这是我的主要内容:

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

这是我的 ripemd160 函数:

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

这是我的十六进制字符串函数:

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

我使用的示例来自
https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses

这是我想得到的 Ripemd-160:
010966776006953D5567439E5E39F86A0D273BEE

这是我实际得到的 Ripemd-160:
6c9814cf2a93131c8d3263158896e786de7a3f21

最佳答案

您应该将 SHA-256 哈希的原始字节传递给 RIPEMD-160 函数,而不是首先转换 SHA-256 散列成十六进制字符串。

您可以使用 openssl 命令行工具验证这一点。

原始字节的

RIPEMD-160,与预期值匹配:

$ echo -n '600FFE422B4E00731A59557A5CCA46CC183944191006324A447BDB2D98D4B408' |
> xxd -p -r | openssl rmd160
(stdin)= 010966776006953d5567439e5e39f86a0d273bee
十六进制字符串的

RIPEMD-160,与预期值不匹配:

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

同样,您还应该将公钥的原始字节传递给 SHA-256 函数,而不是先将公钥转换为十六进制字符串。

公钥原始字节的

SHA-256,与预期值匹配:

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

SHA-256 作为十六进制字符串,与预期值不匹配:

$ echo -n '0450863AD64A87AE8A2FE83C1AF1A8403CB53F53E486D8511DAD8A04887E5B23522CD470243453A299FA9E77237716103ABC11A1DF38855ED6F2EE187E9C582BA6' |
> openssl sha256
(stdin)= 32511e82d56dcea68eb774094e25bab0f8bdd9bc1eca1ceeda38c7a43aceddce

关于C++ OpenSSL Ripemd-160 给出了错误的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37094367/

相关文章:

openssl - 如何使用 ECDSA 以编程方式创建自签名数字证书

bitcoin - 具有更高粒度的历史深度数据 MtGox

javascript - NodeJS 对 Intersango.com 的 HTTPS 请求

c# - 将通用代码从 C# 转换为模板 C++

c++ - 尝试/捕获崩溃 255

java - AES256 与 3DES 256 key 检测

java - 如何在 Bitcoinj (java) 中查看某个地址的交易?

c++ - 从函数返回数组

c++ - 如何使用 C++ 以编程方式检测 Windows 8 中是否启用了 UAC?

c++ - 是否可以从外部设置 ClientHello 随机数