Wie kann ich mit der OpenSSL- Bibliothek SHA1- oder SHA2-Hashes generieren?
Ich habe bei Google gesucht und konnte keinen Funktions- oder Beispielcode finden.
c++
cryptography
Uli Köhler
quelle
quelle
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
md
enthält die binäre SHA-256 Message Digest. Ein ähnlicher Code kann für die anderen Mitglieder der SHA-Familie verwendet werden. Ersetzen Sie einfach "256" im Code.Wenn Sie größere Daten haben, sollten Sie natürlich Datenblöcke bei ihrem Eintreffen füttern (mehrere
SHA256_Update
Anrufe).quelle
Die korrekte Syntax in der Befehlszeile sollte lauten
echo -n "compute sha1" | openssl sha1
Andernfalls wird auch das nachfolgende Zeilenumbruchzeichen gehasht.
quelle
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(); }
quelle
Hier ist ein OpenSSL- Beispiel für die Berechnung des sha-1- Digests 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 das Aufrufen von
SHA1
Funktionen aus OpenSSL , aber es ist universeller und kann für die Verwendung mit Dateistreams überarbeitet werden (wodurch Daten beliebiger Länge verarbeitet werden).quelle
C-Version des @ Nofe-Codes, die SHA1-Hash aus der Datei generiert:
#include <stdio.h> #include <openssl/sha.h> static const int K_READ_BUF_SIZE = { 1024 * 16 }; unsigned char* calculateSHA1(char *filename) { if (!filename) { return NULL; } FILE *fp = fopen(filename, "rb"); if (fp == NULL) { return NULL; } unsigned char* sha1_digest = malloc(sizeof(char)*SHA_DIGEST_LENGTH); SHA_CTX context; if(!SHA1_Init(&context)) return NULL; unsigned char buf[K_READ_BUF_SIZE]; while (!feof(fp)) { size_t total_read = fread(buf, 1, sizeof(buf), fp); if(!SHA1_Update(&context, buf, total_read)) { return NULL; } } fclose(fp); if(!SHA1_Final(sha1_digest, &context)) return NULL; return sha1_digest; }
Es kann wie folgt verwendet werden:
unsigned char *sha1digest = calculateSHA1("/tmp/file1");
Die Variable res enthält den sha1-Hash.
Sie können es mit der folgenden for-Schleife auf dem Bildschirm drucken:
char *sha1hash = (char *)malloc(sizeof(char) * 41); sha1hash[41] = '\0'; int i; for (i = 0; i < SHA_DIGEST_LENGTH; i++) { sprintf(&sha1hash[i*2], "%02x", sha1digest[i]); } printf("SHA1 HASH: %s\n", sha1hash);
quelle