使用OpenSSL库在c++中生成SHA哈希

时间:2021-11-02 15:26:57

How can I generate SHA1 or SHA2 hashes using the OpenSSL libarary?

如何使用OpenSSL libarary生成SHA1或SHA2散列?

I searched google and could not find any function or example code.

我搜索了谷歌,没有找到任何函数或示例代码。

4 个解决方案

#1


72  

From the command line, it's simply:

从命令行,它很简单:

printf "compute sha1" | openssl sha1

You can invoke the library like this:

您可以这样调用库:

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>

int main()
{
    unsigned char ibuf[] = "compute sha1";
    unsigned char obuf[20];

    SHA1(ibuf, strlen(ibuf), obuf);

    int i;
    for (i = 0; i < 20; i++) {
        printf("%02x ", obuf[i]);
    }
    printf("\n");

    return 0;
}

#2


49  

OpenSSL has a horrible documentation with no code examples, but here you are:

OpenSSL有一个糟糕的文档,没有代码示例,但这里有:

#include <openssl/sha.h>

bool simpleSHA256(void* input, unsigned long length, unsigned char* md)
{
    SHA256_CTX context;
    if(!SHA256_Init(&context))
        return false;

    if(!SHA256_Update(&context, (unsigned char*)input, length))
        return false;

    if(!SHA256_Final(md, &context))
        return false;

    return true;
}

Usage:

用法:

unsigned char md[SHA256_DIGEST_LENGTH]; // 32 bytes
if(!simpleSHA256(<data buffer>, <data length>, md))
{
    // handle error
}

Afterwards, md will contain the binary SHA-256 message digest. Similar code can be used for the other SHA family members, just replace "256" in the code.

之后,md将包含二进制SHA-256消息摘要。类似的代码可以用于其他SHA家族成员,只需替换代码中的“256”。

If you have larger data, you of course should feed data chunks as they arrive (multiple SHA256_Update calls).

如果您有较大的数据,当然应该在数据块到达时提供数据块(多个SHA256_Update调用)。

#3


2  

correct syntax at command line should be

命令行中的语法应该是正确的。

echo -n "compute sha1" | openssl sha1

otherwise you'll hash the trailing newline character as well.

否则,您也将散列尾换行字符。

#4


1  

Here is OpenSSL example of calculating sha-1 digest using BIO:

下面是使用BIO计算sha-1摘要的OpenSSL示例:

#include <openssl/bio.h>
#include <openssl/evp.h>

std::string sha1(const std::string &input)
{
    BIO * p_bio_md  = nullptr;
    BIO * p_bio_mem = nullptr;

    try
    {
        // make chain: p_bio_md <-> p_bio_mem
        p_bio_md = BIO_new(BIO_f_md());
        if (!p_bio_md) throw std::bad_alloc();
        BIO_set_md(p_bio_md, EVP_sha1());

        p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length());
        if (!p_bio_mem) throw std::bad_alloc();
        BIO_push(p_bio_md, p_bio_mem);

        // read through p_bio_md
        // read sequence: buf <<-- p_bio_md <<-- p_bio_mem
        std::vector<char> buf(input.size());
        for (;;)
        {
            auto nread = BIO_read(p_bio_md, buf.data(), buf.size());
            if (nread  < 0) { throw std::runtime_error("BIO_read failed"); }
            if (nread == 0) { break; } // eof
        }

        // get result
        char md_buf[EVP_MAX_MD_SIZE];
        auto md_len = BIO_gets(p_bio_md, md_buf, sizeof(md_buf));
        if (md_len <= 0) { throw std::runtime_error("BIO_gets failed"); }

        std::string result(md_buf, md_len);

        // clean
        BIO_free_all(p_bio_md);

        return result;
    }
    catch (...)
    {
        if (p_bio_md) { BIO_free_all(p_bio_md); }
        throw;
    }
}

Though it's longer than just calling SHA1 function from OpenSSL, but it's more universal and can be reworked for using with file streams (thus processing data of any length).

虽然它比仅仅从OpenSSL调用SHA1函数要长,但是它更通用,并且可以在使用文件流时进行修改(因此可以处理任何长度的数据)。

#1


72  

From the command line, it's simply:

从命令行,它很简单:

printf "compute sha1" | openssl sha1

You can invoke the library like this:

您可以这样调用库:

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>

int main()
{
    unsigned char ibuf[] = "compute sha1";
    unsigned char obuf[20];

    SHA1(ibuf, strlen(ibuf), obuf);

    int i;
    for (i = 0; i < 20; i++) {
        printf("%02x ", obuf[i]);
    }
    printf("\n");

    return 0;
}

#2


49  

OpenSSL has a horrible documentation with no code examples, but here you are:

OpenSSL有一个糟糕的文档,没有代码示例,但这里有:

#include <openssl/sha.h>

bool simpleSHA256(void* input, unsigned long length, unsigned char* md)
{
    SHA256_CTX context;
    if(!SHA256_Init(&context))
        return false;

    if(!SHA256_Update(&context, (unsigned char*)input, length))
        return false;

    if(!SHA256_Final(md, &context))
        return false;

    return true;
}

Usage:

用法:

unsigned char md[SHA256_DIGEST_LENGTH]; // 32 bytes
if(!simpleSHA256(<data buffer>, <data length>, md))
{
    // handle error
}

Afterwards, md will contain the binary SHA-256 message digest. Similar code can be used for the other SHA family members, just replace "256" in the code.

之后,md将包含二进制SHA-256消息摘要。类似的代码可以用于其他SHA家族成员,只需替换代码中的“256”。

If you have larger data, you of course should feed data chunks as they arrive (multiple SHA256_Update calls).

如果您有较大的数据,当然应该在数据块到达时提供数据块(多个SHA256_Update调用)。

#3


2  

correct syntax at command line should be

命令行中的语法应该是正确的。

echo -n "compute sha1" | openssl sha1

otherwise you'll hash the trailing newline character as well.

否则,您也将散列尾换行字符。

#4


1  

Here is OpenSSL example of calculating sha-1 digest using BIO:

下面是使用BIO计算sha-1摘要的OpenSSL示例:

#include <openssl/bio.h>
#include <openssl/evp.h>

std::string sha1(const std::string &input)
{
    BIO * p_bio_md  = nullptr;
    BIO * p_bio_mem = nullptr;

    try
    {
        // make chain: p_bio_md <-> p_bio_mem
        p_bio_md = BIO_new(BIO_f_md());
        if (!p_bio_md) throw std::bad_alloc();
        BIO_set_md(p_bio_md, EVP_sha1());

        p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length());
        if (!p_bio_mem) throw std::bad_alloc();
        BIO_push(p_bio_md, p_bio_mem);

        // read through p_bio_md
        // read sequence: buf <<-- p_bio_md <<-- p_bio_mem
        std::vector<char> buf(input.size());
        for (;;)
        {
            auto nread = BIO_read(p_bio_md, buf.data(), buf.size());
            if (nread  < 0) { throw std::runtime_error("BIO_read failed"); }
            if (nread == 0) { break; } // eof
        }

        // get result
        char md_buf[EVP_MAX_MD_SIZE];
        auto md_len = BIO_gets(p_bio_md, md_buf, sizeof(md_buf));
        if (md_len <= 0) { throw std::runtime_error("BIO_gets failed"); }

        std::string result(md_buf, md_len);

        // clean
        BIO_free_all(p_bio_md);

        return result;
    }
    catch (...)
    {
        if (p_bio_md) { BIO_free_all(p_bio_md); }
        throw;
    }
}

Though it's longer than just calling SHA1 function from OpenSSL, but it's more universal and can be reworked for using with file streams (thus processing data of any length).

虽然它比仅仅从OpenSSL调用SHA1函数要长,但是它更通用,并且可以在使用文件流时进行修改(因此可以处理任何长度的数据)。