it-swarm.com.de

Generiere SHA Hash in C ++ mit der OpenSSL Bibliothek

Wie kann ich SHA1- oder SHA2-Hashes mit der OpenSSL Bibliothek generieren?

Ich suchte bei Google und konnte keine Funktion oder Beispielcode finden.

68
Jon Duwok

Von der Kommandozeile aus ist es einfach:

printf "compute sha1" | openssl sha1

Sie können die Bibliothek folgendermaßen aufrufen:

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

OpenSSL hat eine schreckliche Dokumentation ohne Codebeispiele, aber hier sind Sie:

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

Verwendung:

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

Danach enthält md den binären SHA-256-Message-Digest. Ein ähnlicher Code kann für die anderen SHA Familienmitglieder verwendet werden. Ersetzen Sie einfach "256" im Code.

Wenn Sie größere Datenmengen haben, sollten Sie natürlich Datenblöcke beim Eintreffen füttern (mehrere SHA256_Update Anrufe).

53
AndiDog

die korrekte Syntax in der Befehlszeile sollte lauten

echo -n "compute sha1" | openssl sha1

andernfalls wird auch das nachfolgende Newline-Zeichen gehasht.

2
mecano

Hier ist OpenSSL Beispiel für die Berechnung von sha-1 Digest mit BIO :

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

Es ist zwar länger als nur der Aufruf der Funktion SHA1 Von OpenSSL, aber universeller und kann für die Verwendung mit Dateistreams überarbeitet werden (wodurch Daten beliebiger Länge verarbeitet werden).

1
anton_rh

Anpassung der @AndiDog-Version für große Dateien:

static const int K_READ_BUF_SIZE{ 1024 * 16 };

std::optional<std::string> CalcSha256(std::string filename)
{
    // Initialize openssl
    SHA256_CTX context;
    if(!SHA256_Init(&context))
    {
        return std::nullopt;
    }

    // Read file and update calculated SHA
    char buf[K_READ_BUF_SIZE];
    std::ifstream file(filename, std::ifstream::binary);
    while (file.good())
    {
        file.read(buf, sizeof(buf));
        if(!SHA256_Update(&context, buf, file.gcount()))
        {
            return std::nullopt;
        }
    }

    // Get Final SHA
    unsigned char result[SHA256_DIGEST_LENGTH];
    if(!SHA256_Final(result, &context))
    {
        return std::nullopt;
    }

    // Transform byte-array to string
    std::stringstream shastr;
    shastr << std::hex << std::setfill('0');
    for (const auto &byte: result)
    {
        shastr << std::setw(2) << (int)byte;
    }
    return shastr.str();
}
1
Nayfe