如何在 C++ 中生成十六进制二进制数据的 sha256 哈希值?

How to generate sha256 hashes of hexadecimal binary data in c++?

我需要一个 C++ 函数来生成与此命令在 linux 中生成的结果相似的结果。

echo -n "616161616161616" | xxd -r -p | sha256sum -b | awk '{print }'

此命令的作用是:给定一个 hexadump,将其转换为二进制文件格式,并显示二进制文件的 sha256 哈希 file.xxd -r 将 hexadump 转换为二进制文件

有人能帮帮我吗?

实际算法取决于您要执行的操作 - 您可以将十六进制转换为字符串。我在下面的示例中这样做了。

您首先要做的是将字符串转换为二进制,这可以通过以下方式完成:

std::string toBin(std::string str){
    int s = str.length();
    std::string bin = ""
    for (int i = 0; i <= n; i++){
        int v = int(s[i]);
        while (val > 0){
            (val % 2)? bin.push_back('1') : bin.push_back('0');
            val /= 2;
        }
    }
    std::reverse(bin.begin(), bin.end());
}

但是,代码的下一部分太长了,很遗憾我无法将其包含在这个答案中。但我会 link 你到一个包含(希望)你需要的所有代码的网站。 http://www.zedwood.com/article/cpp-sha256-function

祝福。

首先你应该知道你的命令行版本少了一个半字节。即,如果您通过 xxd -r -p 发送 '616161616161616'`,然后通过 xxd 返回,您将看到:

echo -n "616161616161616" | xxd -r -p | xxd
00000000: 6161 6161 6161 61                        aaaaaaa

请注意缺少最后一个半字节 6。 xxd 实用程序消耗 位的十六进制。一旦不再有 它就会停止并发出最终输出。您可能 期望 前导 半字节视为单个八位字节的行为,因此像这样:

echo -n "0616161616161616" | xxd -r -p | xxd
00000000: 0616 1616 1616 1616                      ........

无论哪种情况,无论您想如何处理,您都应该意识到这个问题。

关于您的实际问题,OpenSSL 库具有一组相当丰富的功能,可让您轻松完成大部分您所要求的工作。从输入字符串计算摘要非常简单:

#include <iostream>
#include <vector>
#include <string>

#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>

int main()
{
    std::string strHex = "616161616161616"; // get this from wherever

    // prepend zero-nibble for odd character counts.
    if (strHex.length() % 2)
        strHex.insert(strHex.begin(), '0');

    // convert to blob. returns dynamic memory allocated with
    //  OPENSSL_malloc. Use OPENSSL_free to destroy it.
    long len = 0;
    unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);

    // digest the blob
    const EVP_MD *md_algo = EVP_sha256();
    unsigned int md_len = EVP_MD_size(md_algo);
    std::vector<unsigned char> md( md_len );
    EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);

    // free the input data.
    OPENSSL_free(bin);

    // print the buffer to stdout in hex.
    char *hexOut = OPENSSL_buf2hexstr(md.data(), md_len);
    std::cout << hexOut << '\n';
    OPENSSL_free(hexOut);

    return 0;
}

注意上面的代码在奇数输入长度的情况下采用了前置零半字节的方法。如果这不是您想要的行为(即,如果您想要与问题文本完全相同的忽略尾随奇数半字节行为),另一种方法是 trim 最后一个半字节(我是认真的怀疑是你想要的是它删除了相关位并且是摘要冲突的秘诀,但是你的电话)。

#include <iostream>
#include <vector>
#include <string>

#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>

int main()
{
    std::string strHex = "616161616161616"; // get this from wherever

    // prepend zero-nibble for odd character counts.
    if (strHex.length() % 2)
        strHex.pop_back();

    // convert to blob. returns dynamic memory allocated with
    //  OPENSSL_malloc. Use OPENSSL_free to destroy it.
    long len = 0;
    unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);

    // digest the blob
    const EVP_MD *md_algo = EVP_sha256();
    unsigned int md_len = EVP_MD_size(md_algo);
    std::vector<unsigned char> md( md_len );
    EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);

    // free the input data.
    OPENSSL_free(bin);

    // print the buffer to stdout in hex.
    char *hexOut = OPENSSL_buf2hexstr(md.data(), md_len);
    std::cout << hexOut << '\n';
    OPENSSL_free(hexOut);

    return 0;
}

在上述两种情况下,结果输出被预先配置为以冒号分隔的八位字节。 IE。后一个示例输出如下所示:

E4:62:40:71:4B:5D:B3:A2:3E:EE:60:47:9A:62:3E:FB:A4:D6:33:D2:7F:E4:F0:3C:90:4B:9E:21:9A:7F:BE:60

这是由于 OPENSSL_buf2hexstr 的功能相当有限。如果这不是您想要的(可能不是),您始终可以使用简单的查找 table 自己手动打印它,将每个八位字节处理为两个半字节:

#include <iostream>
#include <vector>
#include <string>

#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>

int main()
{
    std::string strHex = "616161616161616";

    // prepend zero-nibble for odd character counts.
    if (strHex.length() % 2)
        strHex.pop_back();

    // convert to blob. returns dynamic memory allocated with
    //  OPENSSL_malloc. Use OPENSSL_free to destroy it.
    long len = 0;
    unsigned char *bin = OPENSSL_hexstr2buf(strHex.c_str(), &len);

    // digest the blob
    const EVP_MD *md_algo = EVP_sha256();
    unsigned int md_len = EVP_MD_size(md_algo);
    std::vector<unsigned char> md( md_len );
    EVP_Digest(bin, len, md.data(), &md_len, md_algo, nullptr);

    // free the input data.
    OPENSSL_free(bin);

    // dump as continuous hex string
    static const char alpha[] = "0123456789abcdef";
    for (auto c : md)
    {
        std::cout << alpha[ (c >> 4) & 0xF];
        std::cout << alpha[ c & 0xF];
    }
    std::cout.put('\n');

    return 0;
}

输出

e46240714b5db3a23eee60479a623efba4d633d27fe4f03c904b9e219a7fbe60

总之,比我预期的要长,但希望这是您要找的。