C/C++: Kryptografische Hashes mit libtomcrypt berechnen
Problem:
Du möchtest einen Hash eines beliebigen Strings in C/C++ berechnen. LibTomCrypt ist unter der WTFPL-Lizenz verfügbar und daher eine gute Wahl für kommerzielle und nicht-kommerzielle Projekte.
Lösung
Dieser Beitrag beschreibt eine minimalistische Lösung. Weitere Informationen findest du in der offiziellen Dokumentation.
Hier ist ein minimales C-Beispiel zum Hashen eines C-Strings.
#include <tomcrypt.h>
/**
* Hasht eine gegebene Byte-Sequenz mit dem SHA1-Algorithmus
* @param input Zeiger auf die Eingabesequenz
* @param inputSize Größe der Eingabesequenz
* @return Ein per malloc reservierter Zeiger auf die resultierenden Daten. 20 Bytes lang.
*/
unsigned char* hashSHA1(const char* input, unsigned long inputSize) {
//Initialisierung
unsigned char* hashResult = (unsigned char*)malloc(sha1_desc.hashsize);
//Zustandsvariable für den Hash initialisieren
hash_state md;
sha1_init(&md);
//Text verarbeiten - daran erinnern, dass process() mehrfach aufgerufen werden kann
sha1_process(&md, (const unsigned char*) input, inputSize);
//Hash-Berechnung abschließen
sha1_done(&md, hashResult);
// Ergebnis zurückgeben
return hashResult;
}Nach der Verwendung dieser Funktion musst du den von ihr reservierten und zurückgegebenen Speicher mit free() freigeben.
Andere Hash-Algorithmen
Um einen anderen Algorithmus zu verwenden (z.B. SHA256 oder MD5), müssen zwei Dinge ersetzt werden: 1. Der Hash-Name (in diesem Fall sha1_) durch sein Gegenstück (jedes Vorkommen ersetzen!) 2. Die Hash-Größe für SHA1 beträgt 20 Bytes, für andere Hashes kann sie abweichen, z.B. 32 für SHA256
Siehe die Dokumentation, Abbildung 4.1 „Built-In Software Hashes“ für eine Liste gültiger Hash-Deskriptoren und der zugehörigen Hash-Größen.
C++
Auch wenn man den obigen C-Code in C++ ohne Modifikation verwenden kann, möchte man möglicherweise std::string-Instanzen hashen.
/**
* Hasht einen gegebenen Eingabe-String mit dem SHA1-Algorithmus
* @param input Zeiger auf die Eingabesequenz
* @param inputSize Größe der Eingabesequenz
* @return Ein per new[] reservierter Zeiger auf die resultierenden Daten. 20 Bytes lang.
*/
unsigned char* hashSHA1(const std::string& input) {
//Initialisierung
unsigned char* hashResult = new unsigned char[sha1_desc.hashsize];
//Zustandsvariable für den Hash initialisieren
hash_state md;
sha1_init(&md);
//Text verarbeiten - daran erinnern, dass process() mehrfach aufgerufen werden kann
sha1_process(&md, (const unsigned char*) input.c_str(), input.size());
//Hash-Berechnung abschließen
sha1_done(&md, hashResult);
// Ergebnis zurückgeben
return hashResult;
}Verwendung der Funktionen
In den meisten Fällen möchte man den resultierenden Hash als Hexadezimal-String auf stdout ausgeben. Hier ist ein Beispiel für die Verwendung des C++-Codes.
#include <string>
int main(int argc, char** argv) {
std::string text = "abcdef";
unsigned char* hashResult = hashSHA1(text);
//Als Hex-String auf stdout ausgeben
for (int x = 0; x < 20; x++) {
printf("%x", hashResult[x]); //Hex-Format
}
printf("\n");
//Hash-Ergebniszeiger löschen
delete[] hashResult;
return 0;
}Dieser Codeausschnitt gibt 1f8ac1f23c5b5bc1167bda84b833e5c57a77d2 aus.