Hashing mit SHA-256 in der Kryptographie

LinuxBeginner
Jetzt üben

Einführung

Willkommen in der Welt der Kryptographie! In diesem Lab sammeln Sie praktische Erfahrungen mit einem der fundamentalsten Konzepte der modernen Sicherheit: dem kryptographischen Hashing. Speziell werden wir mit dem SHA-256-Algorithmus arbeiten.

Eine kryptographische Hashfunktion ist ein mathematischer Algorithmus, der eine Eingabe (oder „Nachricht“) beliebiger Größe entgegennimmt und eine Zeichenfolge fester Größe von Bytes zurückgibt. Diese Ausgabe ist typischerweise ein „Digest“ oder „Hash“. SHA-256 erzeugt beispielsweise immer einen 256-Bit (32-Byte) langen Hash.

Diese Funktionen weisen mehrere wichtige Eigenschaften auf:

  • Deterministisch: Dieselbe Eingabe erzeugt immer dieselbe Ausgabe.
  • Einwegfunktion (One-way): Es ist rechnerisch unmöglich, die Funktion umzukehren und die ursprüngliche Eingabe aus ihrem Hash zu ermitteln.
  • Lawineneffekt (Avalanche Effect): Eine kleine Änderung der Eingabe (wie das Ändern eines einzelnen Zeichens) erzeugt einen drastisch unterschiedlichen Ausgabe-Hash.

Im Laufe dieses Labs werden Sie das Befehlszeilen-Tool openssl und ein einfaches Python-Skript verwenden, um diese Eigenschaften zu untersuchen und zu verstehen, wie Hashing in realen Szenarien wie der Überprüfung der Dateiintegrität und der Sicherung von Passwörtern eingesetzt wird.

Eigenschaften der Hash-Funktion

In diesem Schritt werden Sie das Befehlszeilen-Tool openssl verwenden, um zwei Kerneigenschaften von Hashfunktionen zu untersuchen: die Deterministik und den Lawineneffekt (Avalanche Effect). Eine Funktion ist deterministisch, wenn dieselbe Eingabe immer dieselbe Ausgabe erzeugt. Der Lawineneffekt bedeutet, dass eine winzige Änderung der Eingabe zu einem völlig anderen Ausgabe-Hash führt.

Zuerst generieren wir einen SHA-256-Hash für die Zeichenkette "hello". Wir verwenden den Befehl echo, um die Zeichenkette an openssl zu übergeben.

echo -n "hello" | openssl dgst -sha256

Die Option -n bei echo ist wichtig; sie verhindert, dass echo ein Zeilenumbruchzeichen (newline character) am Ende der Zeichenkette hinzufügt, was den resultierenden Hash verändern würde.

Sie sollten eine Ausgabe sehen, die wie folgt aussieht:

SHA2-256(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Nun führen wir exakt denselben Befehl erneut aus, um die deterministische Eigenschaft zu demonstrieren.

echo -n "hello" | openssl dgst -sha256

Beachten Sie, dass die Ausgabe identisch ist. Dies bestätigt, dass bei gleicher Eingabe der SHA-256-Hash immer derselbe ist.

SHA2-256(stdin)= 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Als Nächstes demonstrieren wir den Lawineneffekt. Wir nehmen eine sehr kleine Änderung an unserer Eingabezeichenkette vor – wir ändern "hello" in "Hello" (mit einem großgeschriebenen 'H').

echo -n "Hello" | openssl dgst -sha256

Beobachten Sie den neuen Hash:

SHA2-256(stdin)= 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969

Vergleichen Sie diesen Hash mit dem von "hello". Obwohl nur ein Bit der Eingabe geändert wurde (die Groß-/Kleinschreibung des ersten Buchstabens), ist der resultierende Hash völlig anders. Dies ist der Lawineneffekt in Aktion und ein entscheidendes Merkmal einer sicheren Hashfunktion.

Datei-Hash berechnen

In diesem Schritt berechnen Sie den SHA-256-Hash einer Textdatei. Dies ist eine gängige Praxis zur Überprüfung der Dateiintegrität. Wenn Sie eine Datei aus dem Internet herunterladen, stellen Websites oft eine Prüfsumme (einen Hash) bereit, damit Sie überprüfen können, ob die Datei während des Downloads nicht beschädigt wurde oder manipuliert wurde.

Das Setup-Skript für dieses Lab hat bereits eine Datei namens message.txt in Ihrem aktuellen Verzeichnis (~/project) erstellt. Sehen wir uns zunächst deren Inhalt mit dem Befehl cat an.

cat message.txt

Sie werden folgenden Inhalt sehen:

This is a secret message.

Nun berechnen wir den SHA-256-Hash dieser Datei. Die Syntax ähnelt der zuvor verwendeten, aber anstatt Eingaben per Pipe zu senden, übergeben Sie den Dateinamen als Argument an den Befehl openssl dgst.

openssl dgst -sha256 message.txt

Der Befehl verarbeitet die Datei und gibt deren SHA-256-Hash aus. Die Ausgabe wird wie folgt aussehen:

SHA2-256(message.txt)= 6432f513cfd40d47c8584494c0524468257e50dc1a0422f73becac85189543f8

Dieser Hash dient als eindeutiger digitaler Fingerabdruck für den aktuellen Inhalt von message.txt. Wenn jemand auch nur ein einziges Zeichen in der Datei ändert, ändert sich der Hash vollständig, wie Sie in einem späteren Schritt sehen werden.

Mehrere Hashes generieren

In diesem Schritt üben Sie weiter die Generierung von SHA-256-Hashes für verschiedene Zeichenketten-Eingaben. Dies soll Ihr Verständnis dafür vertiefen, wie jede eindeutige Eingabe einen eindeutigen Hash erzeugt. Wir verwenden weiterhin den Befehl echo -n, der an openssl weitergeleitet wird, um sicherzustellen, dass wir nur die Zeichenkette selbst hashen, ohne zusätzliche Zeichen.

Zuerst generieren wir den Hash für die Zeichenkette "labex".

echo -n "labex" | openssl dgst -sha256

Die Ausgabe wird der SHA-256-Hash für "labex" sein:

SHA2-256(stdin)= 679e75b679886c5eaf8aaab88ddfc0181e6dae14cff346db8ba398bd7b2e31fe

Als Nächstes versuchen wir eine andere Zeichenkette, "crypto", um deren eindeutigen Hash zu sehen.

echo -n "crypto" | openssl dgst -sha256

Wie erwartet, erzeugt dies einen völlig anderen Hash:

SHA2-256(stdin)= da2f073e06f78938166f247273729dfe465bf7e46105c13ce7cc651047bf0ca4

Diese Übung demonstriert, dass jede unterschiedliche Datenmenge, egal wie klein oder groß, ihren eigenen eindeutigen Hashwert besitzt. Diese Eigenschaft ist grundlegend dafür, wie Hashes zur Datenverifizierung, in Blockchain-Technologien und bei digitalen Signaturen verwendet werden.

Kollisionsresistenz demonstrieren

In diesem Schritt werden Sie den Lawineneffekt (Avalanche Effect) und das Konzept der Kollisionsresistenz direkt beobachten, indem Sie die Datei message.txt leicht modifizieren und sehen, wie sich ihr Hash ändert. Kollisionsresistenz bedeutet, dass es extrem schwierig ist, zwei unterschiedliche Eingaben zu finden, die denselben Hash erzeugen.

Zuerst berechnen wir den Hash der ursprünglichen Datei message.txt erneut, um ihn noch präsent zu haben.

openssl dgst -sha256 message.txt

Sie sollten erneut den ursprünglichen Hash sehen:

SHA2-256(message.txt)= 6432f513cfd40d47c8584494c0524468257e50dc1a0422f73becac85189543f8

Nun nehmen wir eine sehr kleine Änderung an der Datei vor. Wir fügen einen einzelnen Punkt (.) am Ende der Datei an. Dies können wir einfach mit dem Befehl echo und dem Umleitungsoperator >> tun, der die Ausgabe an eine Datei anhängt.

echo "." >> message.txt

Sie können die vorgenommene Änderung überprüfen, indem Sie sich erneut den Inhalt der Datei ansehen.

cat message.txt

Sie werden den Punkt am Ende sehen:

This is a secret message.
.

Nun hashen wir die modifizierte Datei erneut.

openssl dgst -sha256 message.txt

Der neue Hash lautet:

SHA2-256(message.txt)= 4106e1c985a4ee1754fff76b8bffda0c4844679885cb70758f24cd43e771daac

Vergleichen Sie diesen neuen Hash mit dem ursprünglichen. Sie sind völlig unterschiedlich. Diese eindrucksvolle Demonstration zeigt, dass selbst eine Änderung um ein einziges Zeichen in einer Datei zu einem radikal anderen Hash führt, wodurch jede Form der Manipulation leicht erkannt werden kann.

Passwort-Hash erstellen

In diesem Schritt verlassen Sie die Kommandozeile und schreiben ein einfaches Python-Skript, um ein Passwort zu hashen. Passwörter im Klartext zu speichern, stellt eine erhebliche Sicherheitslücke dar. Die Standardpraxis besteht darin, stattdessen einen Hash des Passworts zu speichern. Wenn sich ein Benutzer anmelden möchte, hasht das System das eingegebene Passwort und vergleicht es mit dem gespeicherten Hash.

Das Setup-Skript hat bereits eine leere Datei namens hash_password.py erstellt. Sie werden dieser nun mit dem Texteditor nano Code hinzufügen.

Öffnen Sie die Datei mit nano:

nano hash_password.py

Kopieren Sie nun den folgenden Python-Code und fügen Sie ihn in den nano-Editor ein:

import hashlib

## The password we want to hash
password = "mysecretpassword"

## Hash functions in Python work on bytes, not strings.
## We must encode the string into bytes first, using UTF-8.
password_bytes = password.encode('utf-8')

## Create a new SHA-256 hash object.
sha256_hash = hashlib.sha256(password_bytes)

## Get the hexadecimal representation of the hash.
hex_digest = sha256_hash.hexdigest()

print(f"The password is: {password}")
print(f"The SHA-256 hash is: {hex_digest}")

Dieses Skript führt folgende Schritte aus:

  1. Importiert die Bibliothek hashlib, die verschiedene Hashing-Algorithmen bereitstellt.
  2. Definiert eine Passwortzeichenkette.
  3. Kodiert die Zeichenkette mithilfe von .encode('utf-8') in Bytes. Dies ist ein entscheidender Schritt, da Hash-Funktionen auf Bytes arbeiten.
  4. Erstellt ein SHA-256-Hash-Objekt und aktualisiert es mit den Passwort-Bytes.
  5. Ruft den endgültigen Hash in einem lesbaren hexadezimalen Format mithilfe von .hexdigest() ab.

Nach dem Einfügen des Codes speichern Sie die Datei und beenden nano, indem Sie Ctrl+X, dann Y und anschließend Enter drücken.

Führen Sie abschließend Ihr Python-Skript im Terminal aus:

python3 hash_password.py

Das Skript wird ausgeführt und gibt das Passwort und seinen entsprechenden SHA-256-Hash aus:

The password is: mysecretpassword
The SHA-256 hash is: 94aefb8be78b2b7c344d11d1ba8a79ef087eceb19150881f69460b8772753263

Sie haben erfolgreich Python zur Durchführung kryptografischer Hash-Verfahren eingesetzt, eine Fähigkeit, die für die sichere Anwendungsentwicklung unerlässlich ist.

Zusammenfassung

Herzlichen Glückwunsch zum Abschluss dieses Labors! Sie haben praktische, direkte Erfahrungen mit der kryptografischen Hash-Funktion SHA-256 gesammelt.

In diesem Labor haben Sie gelernt:

  • Die Kerneigenschaften von Hash-Funktionen: Sie sind deterministisch, einwegig (one-way) und weisen den Lawineneffekt (avalanche effect) auf.
  • Wie man den Befehl openssl dgst -sha256 in einer Linux-Umgebung verwendet, um Hashes sowohl für Zeichenketten als auch für Dateien zu berechnen.
  • Die Bedeutung des Hashings zur Überprüfung der Dateintegrität und zur Erkennung von Manipulationen.
  • Wie man die Python-Bibliothek hashlib verwendet, um programmatisch SHA-256-Hashes zu generieren, eine gängige Aufgabe in der Passwortsicherheit.

Hashing ist ein Eckpfeiler der modernen Cybersicherheit. Die hier geübten Fähigkeiten sind grundlegend für das Verständnis fortgeschrittenerer Themen wie digitale Signaturen, Message Authentication Codes (MACs) und Blockchain-Technologie. Als nächsten Schritt könnten Sie sich über das "Salting" von Passwörtern informieren, was eine zusätzliche Sicherheitsebene über das Hashing hinaus hinzufügt.