Programmierpraktikum SoSe 2024, Bachelor Informatik, FU Berlin
ProPra2024 > Bibliotheken > Python-Standardbibliothek > m_hashlib

Hashlib - Hashes und Prüfsummen erzeugen

Idea

Ziel

Ich weiß, wozu man Hashes und Prüfsummen verwendet und kann diese in Python erzeugen.

Hintergrund

Eine Hashfunktion erzeugt aus beliebig großen Eingabedaten (z.B. einer Datei) einen Wert in einer festen Größe (genannt hash oder digest) so, dass verschiedene Eingabedaten möglichst verschiedene Hashwerte ergeben; man sagt auf Deutsch deshalb auch Streufunktion. Damit lassen sich diverse nützliche Datenstrukturen und Algorithmen bauen.

Eine kryptografische Hashfunktion erledigt diesen Job so, dass es praktisch unmöglich ist, andere Eingabedaten zu finden, die zum selben Hashwert führen. Das erlaubt den Hashwert als eine Art Stellvertreter für den Inhalt der Datei anzusehen, was für viele Zwecke in der Computersicherheit wertvoll ist und auch von git benutzt wird.

Das Python-Modul hashlib stellt einige häufig verwendete und standardisierte kryptografische Hashfunktionen zur Verfügung, die für verschiedene kryptografische Zwecke und zur Integritätsprüfung durch Generierung von Prüfsummen verwendet werden können.

Detailed

Arbeitsschritte

  • 1 Machen Sie sich mit der Dokumentation von hashlib vertraut.
  • 2 Legen Sie die Datei m_hashlib.py an und benutzen Sie diese Datei für den Rest der Aufgabe. Fügen Sie ihre Python-Kommandos skript-artig hintereinander in die Datei ein, mit Leerzeile getrennt.

Hashfunktionen Überblick

  • 3 Geben Sie eine Liste aller auf ihrem System über hashlib zur Verfügung stehenden Hashfunktionen aus.

Kryptografische Hashfunktionen gelten als sicher, solange kein Weg gefunden wurde, für beliebige unterschiedliche Eingaben Kollisionen zu erzeugen (Kollisionsresistenz).

  • 1 In ihrer Liste sollten under anderem folgende Funktionen enthalten sein: MD5, SHA-1 und SHA-256. Recherchieren Sie, inwieweit diese drei Funktionen aktuell noch als sicher gelten.

Hashes erzeugen

  • 4 Erzeugen Sie ein neues Hash-Objekt hash mithilfe eines Konstruktors. Dieses soll die Hash-Funktion SHA-256 verwenden.
  • 5 Erzeugen Sie den Hash für den String ProPra und geben Sie ihn als Hexadezimalwert aus:
    print("1. ProPra SHA-256:\t", ...)
Hinweis (nur bei Bedarf): Wie kann man Strings an ein Hash-Objekt übergeben?

Hash-Funktionen verarbeiten nur Binärdaten und können daher nicht direkt mit Strings umgehen, denn die haben ja je nach Encoding verschiedene Binärdarstellungen. Lesen Sie über die Python-Datentypen zur Darstellung von Binärdaten nach: https://docs.python.org/3/library/stdtypes.html#binary-sequence-types-bytes-bytearray-memoryview

  • 6 Hashfunktionen besitzen die Eigenschaft, dass nur minimale Änderungen am Input komplett verschiedenen Output erzeugen. Testen Sie das aus, indem Sie nur ein Leerzeichen hinzufügen:
    print("2. added a space:\t", ...)
  • 7 Schreiben Sie Code, der nachzählt, an wie vielen Stellen die Ausgabe 2 mit Ausgabe 1 übereinstimmt. Vergleichen Sie das Ergebnis mit der statistisch zu erwartenden Anzahl an Übereinstimmungen: print("3. identical digits: expected: ", ..., "; found: ", ...)

Über die update() Funktion wird die gehashte Eingabe nicht überschrieben, sondern die neue an die alte angefügt. hash.update(a); hash.update(b) ist also identisch zu hash.update(a + b).

  • 8 Zeigen Sie dies, indem Sie ein neues Hash-Objekt für ProPra FU Berlin anlegen, sowie den alten Hash entsprechend aktualisieren. Vergleichen Sie beide Hashes miteinander und geben Sie entsprechend True oder False aus, je nachdem ob die Werte übereinstimmen: print("4. u(a); u(b) = u(a + b):\t", ...)

Hashes aus Dateien erzeugen

Hashes können aus jeder Art von Datenströmen erstellt werden. Häufiger Anwendungsfall ist das Erstellen von Prüfsummen für Dateien.

  • 9 Legen Sie eine Textdatei mit dem Inhalt ProPra im selben Verzeichnis an.
  • 10 Erzeugen Sie für diese Datei die SHA-256 Prüfsumme. Geben Sie dies als Hexadezimalwert aus: print("5. file checksum:\t", ...)
Bemerkung:

Seit Python 3.11 geht das direkt über hashlib, was für uns die bevorzugte Variante ist. Wenn man trotzdem die Variante über with open() ... wählt, sollte man die Datei blockweise einlesen (z.B. in Happen von 1 MB), um Speicherüberläufe durch sehr große Dateien zu vermeiden.

Wenn der Wert nicht mit dem von Ausgabe 1 übereinstimmt, haben Sie etwas falsch gemacht. Korrigieren Sie dies.

Hinweis (nur bei Bedarf): Was habe ich falschgemacht?

Enthält ihre Datei ein Zeilenende-Zeichen? Das gehört nicht hinein.

Programmlauf für die Abgabe

  • 1 Führen Sie das gesamte so erzeugte Programm m_hashlib.py einmal aus.
Trace

Abgabe

Geben Sie ein Kommandoprotokoll ab, das genau nur die Eingaben und Ausgaben der obigen Kommandos 1, 2, … enthält. Entfernen Sie vor Abgabe eventuelle Fehlversuche und sonstige zusätzliche Kommandos aus dem Protokoll.

Geben Sie den Quellcode ab, wie er am Ende der Aufgabe vorliegt.

Geben Sie ein Markdown-Dokument ab mit knappen Antworten zu den oben gestellten Fragen 1, 2, … Geben Sie diese Marker mit an.
Geben Sie ggf. Beispiele oder benutzte Quellen an.