Verwendung von SHA1-Hashing in der C-Programmierung
Lesezeit: 7 Minuten
spassen
Ich versuche, ein C-Programm zu schreiben, das beweist, dass SHA1 nahezu kollisionsfrei ist, aber ich kann nicht herausfinden, wie ich den Hash für meine Eingabewerte tatsächlich erstellen soll. Ich muss nur den Hash erstellen und den Hex-Wert in einem Array speichern. Nach einigen Google-Suchen habe ich eine OpenSSL-Dokumentation gefunden, die mich anweist, Folgendes zu verwenden:
#include <openssl/sha.h>
unsigned char *SHA1(const unsigned char *d, unsigned long n,
unsigned char *md);
int SHA1_Init(SHA_CTX *c);
int SHA1_Update(SHA_CTX *c, const void *data,
unsigned long len);
int SHA1_Final(unsigned char *md, SHA_CTX *c);
Ich glaube, ich sollte entweder unsigned char *SHA1 oder SHA1_Init verwenden, aber ich bin mir nicht sicher, was die Argumente wären, da x meine zu hashende Eingabe ist. Würde das bitte jemand für mich klären? Vielen Dank.
Was sind Ihre Eingabewerte: In-Memory-Strings oder Dateiinhalte?
– Basile Starynkevitch
14. Februar 2012 um 21:31 Uhr
Ich schreibe einen Geburtstagsangriff, der einen neuen Hash erstellen und ihn jedes Mal am Ende hinzufügen soll, wenn ich das Array durchlaufe. Ich wollte es einfach halten und den Wert von i hashen. Schnelle Antwort, in Speicherzeichenfolgen.
– spassen
14. Februar 2012 um 21:34 Uhr
Was meinst du mit “beweisen, dass SHA1 nahezu kollisionsfrei ist”? SHA1 ist ein 160-Bit-Hash, also gibt es 2 ^ 160 mögliche Werte, aber es gibt weit mehr als 2 ^ 160 mögliche Zeichenfolgen (z. B. kürzer als 1 MB), also gibt es Tonnen von Kollisionen. Wenn Sie nur testen möchten, ob Sie Kollisionen von einer Reihe zufällig generierter Zeichenfolgen erhalten, ist die Anzahl der Zeichenfolgen, die für eine halbwegs zuverlässige Antwort benötigt werden, undurchführbar hoch (es sei denn, Sie finden zufällig früh eine Kollision, aber SHA1 ist gut genug getestet, um dies zuzuweisen eine vernachlässigbar kleine Wahrscheinlichkeit).
– Daniel Fischer
14. Februar 2012 um 21:41 Uhr
Mir ist klar, dass es viele mögliche Kollisionen gibt, aber das Ziel ist zu beweisen, dass es viel Zeit in Anspruch nehmen würde, eine Kollision zu finden (etwa 2 ^ 80) und noch mehr Zeit in Anspruch nehmen würde, um eine Kollision zu finden, die einem bestimmten Hash entspricht.
– spassen
14. Februar 2012 um 21:44 Uhr
Aber realistischerweise können Sie nicht mehr als 2 ^ 34 Saiten oder so testen. Selbst wenn SHA1 so verzerrt wäre, dass Sie nur 2 ^ 50-Strings für eine Kollision benötigen würden, werden Sie es mit ziemlicher Sicherheit nicht sehen.
– Daniel Fischer
14. Februar 2012 um 22:10 Uhr
Adam Rosenfield
Wenn Sie alle Ihre Daten auf einmal haben, verwenden Sie einfach die SHA1 Funktion:
// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash
Wenn Sie andererseits Ihre Daten nur Stück für Stück erhalten und den Hash berechnen möchten, während Sie diese Daten erhalten, verwenden Sie die anderen Funktionen:
// Error checking omitted for expository purposes
// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);
// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1_Final(hash, &ctx);
Ich habe versucht, die sha1-Funktion zu verwenden, aber wenn ich im Terminal kompiliere, heißt es Undefinierter Verweis auf SHA1. Über alles andere bekomme ich keine Beschwerden. Irgendeine Ahnung, was mir fehlt?
– spassen
14. Februar 2012 um 22:02 Uhr
Sie müssen mit der OpenSSL-Laufzeitbibliothek verknüpfen. Angenommen, Sie verwenden gcc, fügen Sie hinzu -lcrypto zu Ihrer Linker-Befehlszeile.
– Adam Rosenfield
14. Februar 2012 um 22:33 Uhr
wie würde man hmacsha1 generieren?
– Kmag
15. Mai 2013 um 14:31 Uhr
Keine Fehlerbehandlung erforderlich? Für mich stürzt SHA1_Final ab, habe aber keine Ahnung warum. Gibt es eine Möglichkeit den Fehler auszudrucken?
– BTR Naidu
6. Mai 2016 um 11:22 Uhr
Wie bekommt man die hash Wert? Ich bekomme �*���qE)DDF:� �4� mit printf("<<sha1=%s>>\n", hash);
– Kostjantyn
11. November 2017 um 6:57 Uhr
Es sind zwei verschiedene Wege, um dasselbe zu erreichen.
Genauer gesagt, Sie entweder verwenden SHA_Initdann SHA_Update so oft wie nötig, um Ihre Daten durchzugeben und dann SHA_Final um die Zusammenfassung zu bekommen, oder Sie SHA1.
Der Grund für zwei Modi ist, dass es beim Hashen großer Dateien üblich ist, die Datei in Blöcken zu lesen, da die Alternative viel Speicher verbrauchen würde. Behalten Sie daher den Überblick SHA_CTX – Der SHA-Kontext – as you go ermöglicht es Ihnen, dies zu umgehen. Der Algorithmus passt intern auch zu diesem Modell – das heißt, Daten werden blockweise übergeben.
Das SHA Methode sollte ziemlich einfach sein. Der andere funktioniert so:
unsigned char md[SHA_DIGEST_LENGTH];
SHA_CTX context;
int SHA1_Init(&context);
for ( i = 0; i < numblocks; i++ )
{
int SHA1_Update(&context, pointer_to_data, data_length);
}
int SHA1_Final(md, &context);
Entscheidend, am Ende md enthält den binären Digest, keine hexadezimale Darstellung – es ist keine Zeichenfolge und sollte nicht als solche verwendet werden.
wie würde man hmacsha1 generieren?
– Kmag
15. Mai 2013 um 14:47 Uhr
@Clustermagnet hmacsha1 ist ein HMAC-Algorithmus, der SHA1 als Hash verwendet. Es ist die gleiche Idee wie in meiner Antwort hier (siehe hier) sondern für die EVP_MD HMAC-spezifisches Argument, das Sie angeben EVP_sha1().
– Benutzer257111
15. Mai 2013 um 15:12 Uhr
@Cmag – siehe EVP Signieren und Verifizieren | HMAC im OpenSSL-Wiki. Siehe auch Verwenden von HMAC vs. EVP-Funktionen in OpenSSL auf Stack Overflow.
– jww
13. Juni 2016 um 0:11 Uhr
Die erste Funktion (SHA1()) die übergeordnete ist, ist es wahrscheinlich die, die Sie wollen. Das Dokument ist ziemlich klar in Bezug auf die Verwendung – d eingegeben wird, n ist seine Größe u md Hier wird das Ergebnis platziert (Sie weisen es zu).
Was die anderen 3 Funktionen betrifft – diese sind niedriger und ich bin mir ziemlich sicher, dass sie intern von der ersten verwendet werden. Sie eignen sich besser für größere Eingaben, die blockweise verarbeitet werden müssen.
Ich glaube, ich sollte beide verwenden unsigned char *SHA1 oder SHA1_Init …
Für spätere Versionen der OpenSSL-Bibliothek, wie 1.0.2 und 1.1.0, empfiehlt das Projekt die Verwendung der EVP-Schnittstelle. Ein Anwendungsbeispiel EVP-Nachrichtenzusammenfassungen mit SHA256 ist im OpenSSL-Wiki verfügbar:
Die Antwort von Adam Rosenfield ist in Ordnung, aber verwenden Sie strlen anstelle von sizeof, da sonst Hash einschließlich Nullterminator berechnet wird. Was in diesem Fall wahrscheinlich in Ordnung ist, aber nicht, wenn Sie Ihren Hash mit einem von einem anderen Tool generierten vergleichen müssen.
// The data to be hashed
char data[] = "Hello, world!";
size_t length = strlen(data);
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1(data, length, hash);
// hash now contains the 20-byte SHA-1 hash
linux_art
Berechnen Sie Hash wie folgt
// Object to hold the current state of the hash
SHA_CTX ctx;
SHA1_Init(&ctx);
// Hash each piece of data as it comes in:
SHA1_Update(&ctx, "Hello, ", 7);
...
SHA1_Update(&ctx, "world!", 6);
// etc.
...
// When you're done with the data, finalize it:
unsigned char tmphash[SHA_DIGEST_LENGTH];
SHA1_Final(tmphash, &ctx);
Schließlich können Sie Hash mit Code wie diesem in eine für Menschen lesbare Form decodieren.
unsigned char hash[SHA_DIGEST_LENGTH*2];
int i = 0;
for (i=0; i < SHA_DIGEST_LENGTH; i++) {
sprintf((char*)&(hash[i*2]), "%02x", tmphash[i]);
}
// And print to stdout
printf("Hash: %s\n", hash);
Koch Gladiator
Lassen Sie den Code sprechen
Der SQLite-Entwicklungsbaum enthält eine Quelle für das Tool DBHASH zum Anwenden von SHA1 auf ganze Datenbanken. Komplett mit SHA1-Implementierung.
Vielleicht finden Sie es machbar, diesen Code zu studieren.
Was sind Ihre Eingabewerte: In-Memory-Strings oder Dateiinhalte?
– Basile Starynkevitch
14. Februar 2012 um 21:31 Uhr
Ich schreibe einen Geburtstagsangriff, der einen neuen Hash erstellen und ihn jedes Mal am Ende hinzufügen soll, wenn ich das Array durchlaufe. Ich wollte es einfach halten und den Wert von i hashen. Schnelle Antwort, in Speicherzeichenfolgen.
– spassen
14. Februar 2012 um 21:34 Uhr
Was meinst du mit “beweisen, dass SHA1 nahezu kollisionsfrei ist”? SHA1 ist ein 160-Bit-Hash, also gibt es 2 ^ 160 mögliche Werte, aber es gibt weit mehr als 2 ^ 160 mögliche Zeichenfolgen (z. B. kürzer als 1 MB), also gibt es Tonnen von Kollisionen. Wenn Sie nur testen möchten, ob Sie Kollisionen von einer Reihe zufällig generierter Zeichenfolgen erhalten, ist die Anzahl der Zeichenfolgen, die für eine halbwegs zuverlässige Antwort benötigt werden, undurchführbar hoch (es sei denn, Sie finden zufällig früh eine Kollision, aber SHA1 ist gut genug getestet, um dies zuzuweisen eine vernachlässigbar kleine Wahrscheinlichkeit).
– Daniel Fischer
14. Februar 2012 um 21:41 Uhr
Mir ist klar, dass es viele mögliche Kollisionen gibt, aber das Ziel ist zu beweisen, dass es viel Zeit in Anspruch nehmen würde, eine Kollision zu finden (etwa 2 ^ 80) und noch mehr Zeit in Anspruch nehmen würde, um eine Kollision zu finden, die einem bestimmten Hash entspricht.
– spassen
14. Februar 2012 um 21:44 Uhr
Aber realistischerweise können Sie nicht mehr als 2 ^ 34 Saiten oder so testen. Selbst wenn SHA1 so verzerrt wäre, dass Sie nur 2 ^ 50-Strings für eine Kollision benötigen würden, werden Sie es mit ziemlicher Sicherheit nicht sehen.
– Daniel Fischer
14. Februar 2012 um 22:10 Uhr