© agsandrew/Shutterstock.com
Block Cipher erklärt – Teil 2

Authenticated Encryption in Ruby


Die Standardbibliothek von Ruby bietet neben Stream Ciphern auch Block Cipher an. Diese bilden allerdings unter Umständen nachvollziehbare Muster, wenn man nicht ein wenig Zusatzarbeit investiert. Wie man echte Authenticated Encryption erreicht, erklärt dieser Teil der Artikelserie.

Im ersten Teil dieser Serie haben wir den Block Cipher TEA [1] implementiert und ähnlich wie bei den Stream Ciphern festgestellt, dass eine rein deterministische Verschlüsselung nicht ausreichend ist, um zeitgemäß zu verschlüsseln. Bei den Stream Ciphern stellte die Einführung eines zufälligen Elements die Lösung dar, einer sogenannten Nonce. Dieses Zufallselement wird genutzt, um eine ansonsten strikt deterministische Berechnung zu einer nichtdeterministischen zu machen, sodass das Ergebnis in nicht vorhersehbarer Weise von diesem Zufallselement beeinflusst wird [2].

Auch bei Block Ciphern wird dieser Trick genutzt, um eine nichtdeterministische Verschlüsselung zu realisieren. Im Unterschied zu Stream Ciphern muss man zusätzlich darauf achten, dass sich keine nachvollziehbaren Muster innerhalb der einzelnen verschlüsselten Blöcke ergeben. Wie wir im letzten Teil gesehen haben, führt der naive Ansatz, die Plaintext-Blöcke der Reihe nach mit dem Block Cipher zu verschlüsseln, zu eben solchen Mustern. Um das zu unterbinden, muss man also zusätzliche Arbeit leisten.

Betriebsmodi eines Block Cipher

Indem wir den naheliegenden Ansatz verfolgt haben, die Blöcke des Plaintexts einfach der Reihe nach zu verschlüsseln, haben wir unbewusst bereits einen Betriebsmodus verwendet. Ein Betriebsmodus, auch Betriebsart genannt, beschreibt grundsätzlich den Vorgang, wie die Plaintext-Blöcke in Ciphertext-Blöcke verwandelt und die resultierenden Ciphertext-Blöcke untereinander weiterverarbeitet werden. Der eigentliche Block-Cipher-Algorithmus, also z. B. AES oder TEA, dient lediglich dazu, einen einzelnen Block zu verschlüsseln. Der Betriebsmodus legt fest, wie dieser Block aus dem Plaintext gewonnen wird und darüber hinaus, wie der verschlüsselte Ciphertext-Block – wenn überhaupt – noch zusätzlich weiterverarbeitet wird.

ECB – Electronic Code Book Mode

Der Betriebsmodus, den wir bereits unbewusst verwendet haben, ist der sogenannte Electronic Code Book Mode, kurz ECB [3]. Dieser Modus ist ziemlich unspektakulär. Er bildet die einfachste Art und Weise ab, wie man eine Reihe von Plaintext-Blöcken verschlüsselt. Die dabei entstandenen Ciphertext-Blöcke werden ohne weitere Verarbeitung wieder aneinandergereiht und ergeben so den finalen Ciphertext.

bosslet_rubycrypt_1.tif_fmt1.jpgAbb. 1: Der finale Ciphertext im ECB

In Abbildung 1 ist erkennbar, dass sich die einzelnen Verschlüsselungen der Blöcke streng voneinander isoliert abspielen. Es gibt keine zufälligen Elemente, selbst der Verschlüsselungsalgorithmus an sich ist – wenn auch komplex – letztlich nur eine deterministische Rechenvorschrift. Somit ist auch das Endergebnis ein deterministisches, was aufgrund einer fehlenden Zufallskomponente auch nicht überrascht. Die zugehörige Entschlüsselung gestaltet sich wie in Abbildung 2 dargestellt.

bosslet_rubycrypt_2.tif_fmt1.jpgAbb. 2: Entschlüsselungsvorgang des ECB

Auch das ist wieder der naheliegendste Ansatz. Der Ciphertext wird seinerseits wieder in Ciphertext-Blöcke unterteilt, diese werden der Reihe nach entschlüsselt und die so resultierenden Plaintexte ebenfalls wieder aneinandergereiht. Die so entstandene Kette aus Plaintext-Blöcken ergibt wieder den ursprünglichen Plaintext.

Wir haben uns bereits ausführlich über die Nachteile dieser Methode ausgelassen. Wieso gibt es sie überhaupt, wenn sie doch so unsicher ist? Die Frage ist berechtigt. Es gibt Ausnahmefälle, in denen ECB eingesetzt wird, aber im Normalfall sollte man ECB tunlichst vermeiden. Darüber hinaus erlaubt ECB es, den „puren“ Algorithmus zu benutzen, der als Baustein für andere Betriebsmodi genutzt werden kann – wir werden das in einem Beispiel ausnutzen, um den rohen AES-Algorithmus verwenden zu können.

CBC – Cipher Block Chaining Mode

Was also tun, um den Teufelskreis der deterministischen Verschlüsselung zu durchbrechen? Es wurde bereits angedeutet, dass es ähnlich wie bei den Stream Ciphern möglich ist, ein zufälliges Element in die Berechnungen einzubringen, um so am Ende zu einem nichtdeterministischen Ciphertext zu gelangen. Eine seit langer Zeit sehr populäre Methode, das zu tun, ist der Cipher Block Chaining Mode (CBC) [4]. Abbildung 3 zeigt das Diagramm der Verschlüsselung.

bosslet_rubycrypt_3.tif_fmt1.jpgAbb. 3: Verschlüsselungsdiagramm für den CBC

Es ist direkt ersichtlich, dass sich das grundlegend von ECB unterscheidet. Bei näherer Betrachtung erkennen wir ein Muster. Es lässt sich in Worten etwa so beschreiben: „Der nächste Plaintext-Block wird mit dem vorangehenden Ciphertext-Block mittels XOR verknüpft. Das Ergebnis des XOR wird mit dem Block Cipher verschlüsselt und das verschlüsselte Resultat ergibt den nächsten Ciphertext-Block.“

Mathematischer formuliert lässt sich diese Vorschrift für CBC-Verschlüsselung zusammenfassen als rekursive Definition:

C_i = E(P_i ⊕ C_i-1)

E bezeichnet die Verschlüsselungsfunktion des Block Ciphers, C_i den i-ten Ciphertext-Block und P_i den i-ten Plaintext-Block. Es stellt sich unmittelbar die Frage: Was, wenn es noch keinen vorangehenden Ciphertext-Block gibt? Das ist nämlich bei der Berechnung des allerersten Ciphertext-Blocks der Fall.

C_1 = E(P_1 ⊕ C_0)

Wir haben an dieser Stelle kein C_0 zur Hand. Da man sich nur einmalig zu Beginn in dieser misslichen Lage befindet, hat man eine pragmatische Lösung gewählt. Wenn es keinen vorangehenden Ciphertext-Block gibt, dann lassen wir ihn einfach aus heiterem Himmel erscheinen – wir legen C_0 willkürlich fest und definieren:

C_0 = IV

IV ist hierbei der sogenannte Initialisierungsvektor – ein Wert, den wir einmalig zu Beginn des Verschlüsselungsvorgangs festlegen. Man könnte sich das Leben an dieser Stelle einfach machen und schlicht eine globale Konstante als IV festlegen. Das wäre aber eine denkbar schlechte Wahl, weil dann unsere CBC-Verschlüsselung trotz aller zusätzlichen Komplexität nach wie vor deterministisch wäre. Man kann zeigen, dass die CBC-Verschlüsselung an Sicherheit einbüßt, solange der Wert des IV vorhersehbar ist. Die einzig sichere Methode, den IV festzulegen, ist daher, ihn mit Hilfe eines kryptografisch sicheren Pseudozufallszahlengenerators wie z. B. Rubys SecureRandom generieren zu lassen. CBC-Verschlüsselung mit einem kryptografisch sicher generierten IV genügt dem Sicherheitsmodell IND-CPA [5], das wir bereits bei den Stream Ciphern kennengelernt haben. Wie sieht die Entschlüsselung bei CBC aus? Abbildung 4 zeigt es.

bosslet_rubycrypt_4.tif_fmt1.jpgAbb. 4: Entschlüsselungsvorgang CBC

Schaut man genau hin, erkennt man, dass in der Tat die Schritte der Verschlüsselung in umgekehrter Reihenfolge ausgeführt werden. Als Rezept in Worten: „Der nächste Ciphertext-Block wird zuerst mit dem Bl...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang