77 Stimmen

SHA-Hash in C++ mit der OpenSSL-Bibliothek generieren

Wie kann ich SHA1- oder SHA2-Hashes mit dem OpenSSL libarary?

Ich habe Google durchsucht und konnte keine Funktion oder einen Beispielcode finden.

86voto

brianegge Punkte 28043

Von der Kommandozeile aus ist es ganz einfach:

printf "compute sha1" | openssl sha1

Sie können die Bibliothek wie folgt 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;
}

68voto

AndiDog Punkte 65445

OpenSSL hat eine schreckliche Dokumentation ohne Code-Beispiele, 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, md enthält den binären SHA-256 Message Digest. Ein ähnlicher Code kann auch für die anderen Mitglieder der SHA-Familie verwendet werden, indem man einfach "256" im Code ersetzt.

Wenn Sie größere Datenmengen haben, sollten Sie natürlich Datenpakete einspeisen, sobald sie ankommen (mehrere SHA256_Update Anrufe).

5voto

Nayfe Punkte 1905

Anpassung der Version von @AndiDog 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();
}

3voto

mecano Punkte 59

Die korrekte Syntax in der Befehlszeile sollte lauten

echo -n "compute sha1" | openssl sha1

andernfalls wird das nachfolgende Zeilenumbruchzeichen ebenfalls zerhackt.

1voto

anton_rh Punkte 6967

Hier ist OpenSSL Berechnungsbeispiel sha-1 Verdauung 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;
    }
}

Auch wenn es länger dauert als nur ein Anruf SHA1 Funktion von OpenSSL aber es ist universeller und kann für die Verwendung mit Dateiströmen (also die Verarbeitung von Daten beliebiger Länge) überarbeitet werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X