diff --git a/20230622/ad-20230622.txt b/20230622/ad-20230622.txt
index fb190fbacceeb6193e3e858f620bdb15a48bc596..b21b376629071905e6d8017c5983b066b8e11f71 100644
--- a/20230622/ad-20230622.txt
+++ b/20230622/ad-20230622.txt
@@ -66,6 +66,11 @@ Beispiel:
   1234513247519832645912938749631409478172389649182351 * 123406123785012784618723058163
     = 152346494637670594525194299058889621869556846777469948747518602026934923166081213
 
+Dasselbe Beispiel, hexadezimal:
+
+  34CB03092F31959B6E7AD210A9A9FA6599F8A946E8F * 18EBF272F494AC4A21017A1F3
+   = 523B0A443912908FD5D8D15AA87F9591614F7BF892D63356178422C9554C345E0BD
+
 Stattdessen: schriftlich.
 
 --> O(log b)
@@ -84,6 +89,19 @@ Beispiel:
   ----------
      1010100
 
+Das war BigEndian für den zweiten Operanden.
+Übersichtlicher: LittleEndian.
+
+  14 * 6 = 84
+
+  1110 * 110
+  ----------
+           0    Vorteil: Ich muß den ersten Operanden
+       1110     immer nur um 1 Bit weiter nach links schieben
+      1110      (anstatt jedesmal von 0 um i Bits nach links)
+  ---111----    (In Assembler gibt es Bit-Shift um 1 mit Carry.)
+     1010100
+
 Speicherplatzbedarf: log c = log a + log b
 
 --> Ich benötige für c höchstens so viele Ziffern, wie a und b gemeinsam haben.
@@ -100,3 +118,133 @@ https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Bit-Shifting
   For both << and >>, if the second operand is greater than the bit-width
   of the first operand, or the second operand is negative, the behavior is
   undefined. 
+
+Kryptographische Hash-Funktionen, 22.06.2023, 17:08:52
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Was ist das?
+ - gegeben: Daten, z.B. ein Text
+ - gesucht: eine "Prüfsumme", der Hash-Wert, die den Text eindeutig identifiziert
+   --> Es soll in der Praxis unmöglich sein, einen Text zu konstruieren,
+       der eine gegebenen Hash-Wert hat (z.B. den eines anderen Textes).
+       Wenn ich z.B. nur 1 Bit ändere, soll der Hash-Wert völlig anders sein.
+ - Anwendung: Authentisierung des Textes, insbesondere: kryptographische Signatur
+
+Wie funktioniert eine kryptographische Signatur?
+ - gegeben: Daten, z.B. ein Text
+ - gesucht: eine "Unterschrift", die klarstellt, von wem der Text stammt
+Verfahren:
+ 1. Erstelle einen Hash-Wert des Textes.
+    Nun haben wir z.B. 256 Bit anstelle von 5 MB.
+ 2. Diesen Hash-Wert verschlüssele ich mit RSA
+    unter Verwendung des geheimen(!) Schlüssels.
+    ("Normal" wäre: _Ver_schlüsselung mit dem öffentlichen Schlüssel.)
+ 3. Überprüfung der Signatur: Entschlüsselung unter
+    Verwendung des öffenlichen(!) Schlüssels.
+    ("Normal" wäre: _Ent_schlüsselung mit dem geheimen Schlüssel.)
+--> Alle können entschlüsseln, aber nur, wer den geheimen Schlüssel besitzt,
+    kann verschlüsseln.
+ 4. Wir erstellen selbst den Hash-Wert des Textes und vergleichen ihn
+    mit dem entschlüsselten. Bei Übereinstimmung: gültige Unterschrift
+    durch die Person, die den geheimen Schlüssel besitzt.
+
+Weitere Anwendung: Passwort-Authentifikation
+ - Wir speichern nicht das Passwort, sondern den Hash-Wert.
+ - Nach Eingabe eines Passworts bilden wir dessen Hash-Wert
+   und prüfen auf Übereinstimmung.
+ - Bei Übereinstimmung war das Passwort richtig.
+--> Passwörter prüfen, ohne die Passwörter zu kennen.
+
+Damit das funktioniert, muß die Hash-Funktion "gut" sein:
+ - Unterschiedliche Texte müssen unterschiedliche Hash-Werte liefern.
+   Das ist mathematisch nicht möglich, aber:
+   Es sollte sehr unwahrscheinlich sein, durch Zufall oder Absicht
+   mehrere Texte mit demselben Hash-Wert zu bekommen.
+ - Es darf außerdem nicht möglich sein, aus dem Hash-Wert auf den Text zu schließen.
+
+Wie baut man eine Hash-Funktion?
+Merkle-Damgård-Konstruktion:
+ - Blockgröße a (z.B. 256 Bit = 32 Bytes)
+ - Nachricht länger machen ("Padding") bis zu einem Vielfachen von a
+ - Nachricht in Blöcke m_i der Länge a aufteilen
+ - Wir verwenden eine Verschlüsselungsfunktion ("Kompressionsfunktion") f.
+   Dadurch soll die Ausgabe kleiner werden als die Eingabe.
+ - Wir starten mit einem Startvektor H_0, der irgendwelche Zufallszahlen enthält
+   (z.B.: Nachkommastellen von pi, Werte des Sinus für ganze Zahlen, ...)
+ - Wir iterieren:
+
+     H_i := f (H_{i-1} || m_i)   ("||" = "verkettet mit")
+
+   Das bedeutet:
+    - Komprimiere den Startvektor. Dadurch wird er kürzer.
+    - Hänge den ersten Block der Nachricht an.
+    - Komprimiere das Ergebnis. Dadurch wird es wieder kürzer.
+    - Hänge den zweiten Block der Nachricht an.
+    - Komprimiere das Ergebnis. Dadurch wird es wieder kürzer.
+    - ...
+    - ... bis zum Ende der Nachricht.
+   --> Ergebnis: eine undefinierbare Matsche, die eindeutig dem Text zugeordnet werden kann.
+       (Alles ist deterministisch.)
+
+ - Parallele: Mischen von Zutaten für die Zubereitung von Lebensmitteln
+    - Zutat 1 in die Schüssel.
+    - Umrühren.
+    - Zutat 2 dazu.
+    - Umrühren.
+    - Zutat 3 dazu.
+    - Umrühren.
+    - ...
+    - ... bis alle Zutaten in der Schüssel sind.
+   --> Ergebnis: eine undefinierbare, aber hoffentlich genießbare Matsche.
+       (Kenner können evtl. noch die Zutaten herausschmecken.)
+
+ - Kompressionsalgorithmus:
+   Wir haben einen Ergebnisblock, eine Nachricht und ein (Block-)Verschlüsselungsverfahren.
+    - Ergebnisblock verschlüsseln, Nachrichtenblock als Schlüssel verwenden:
+      Davies-Meyer-Kompressionsfunktion
+    - Nachrichtenblock verschlüsseln, Ergebnisblock als Schlüssel verwenden:
+      Matyas–Meyer–Oseas-Kompressionsfunktion
+    - ...
+
+Was sind (Block-)Verschlüsselungsverfahren?
+ - deterministischer Pseudozufallszahlengenerator
+   (liefert für denselben Startwert dieselben Pseudozufallszahlen)
+ - Startwert = Schlüssel
+
+Einfaches Beispiel: (Stream-)Verschlüsselungsverfahren RC4
+
+  char S[256]: Tabelle mit 256 Zufallszahlen ("S-Box")
+
+  char i;
+  char j;
+
+  i++;
+  j += S[i];
+  char k = S[j] + S[i];     // alles modulo 256
+  Verschlüssele mit S[k];   // S[k] ist eine Pseudozufallszahl. Damit kann ich z.B. xodern.
+  vertausche S[i] mit S[j];
+  nächster Buchstabe der Nachricht
+
+--> Die Nachricht wird schön durchmischt.
+
+Der Schlüssel ist gewissermaßen die S-Box.
+(Genauer: Die S-Box wird mit Hilfe des Schlüssels initialisiert.)
+
+Achtung: Es ist sehr aufwendig, die Sicherheit eines Algorithmus' zu prüfen!
+Bitte keine neuen ("noch sichereren, weil niemand sie kennt") Algorithmen ausdenken!
+Nur seit vielen Jahren geprüfte Algorithmen sind sicher.
+
+Beispiel: Angriff auf AES
+https://de.wikipedia.org/wiki/Advanced_Encryption_Standard#Schwächen_und_Angriffe
+
+  Die Forscher Alex Biryukov und Dmitry Khovratovich veröffentlichten Mitte des
+  Jahres 2009 einen Angriff mit verwandtem Schlüssel[11] auf die AES-Varianten
+  mit 192 und 256 Bit Schlüssellänge. Dabei nutzten sie Schwächen in der
+  Schlüsselexpansion aus und konnten eine Komplexität von 2119 erreichen. Damit
+  ist die AES-Variante mit 256 Bit Schlüssellänge formal schwächer als die
+  Variante mit 128 Bit Schlüssellänge.[12] Ende 2009 wurde mit einer
+  Verbesserung des Angriffs eine Komplexität von nur noch 299,5 erreicht.[13]
+  Für die Praxis hat dieser Angriff jedoch wenig Relevanz, denn AES bleibt
+  weiterhin praktisch berechnungssicher.[13]
+
+  --> AES-128 ist demnach sicherer als AES-256
+      (mit effektiv nur 99.5 Bit Schlüssellänge)!