 Und zwar möchte ich heute über Axolotl reden, das ist das Instant-Messaging-Protokoll, das Signal und WhatsApp für ihre Ende-zu-Ende-Verlösung verwenden. Und gleich vorweg, wenn spontan irgendwelche Fragen auftreten, bitte gleich. Ich habe relativ viel Zeit zwischendrin, das heißt, man muss sich das nicht bis zum Ende aufheben. Und es ist ausgegeben im Anlass häufig hilfreicher, wenn die Fragen direkt beantwortet werden, weil man dann den Zusammenhang besser versteht. So, erst mal kurz über mich. Ich studiere Elektrotechnik am KIT, bin relativ viel geistert für freie Software und GNU-Linux, relativ viel auf GitHub aktiv. Und momentan implementiere ich Axolotl, das mittlerweile übrigens auch umbenannt wurde zu Double-Ratchet, habe ich so das Gefühl, da habe ich noch nicht so ganz durchgeblickt, in einer freien Library-Namens-Molch für das Unternehmen 1984.not GmbH, das ein Krypto-Messenger machen möchte. Kleine Disclaimer, ich bin kein Kryptologe und ich war auch nicht an der Entwicklung von Axolotl beteiligt. Erst alle meine Informationen habe ich aus öffentlich verfügbaren Quellen. So, warum braucht man überhaupt Axolotl? Also ich habe ja mal Auflistungen von beispielsweise PGP, das man seit Ewigkeiten schon für E-Mailverschlüsselung benutzt. OTR, das bei Instant Messaging sehr gebräuchlich ist. Und jetzt mal Axolotl und dann verschiedene Eigenschaften und ob sie erfüllt werden oder nicht. Natürlich gibt es noch jede Menge andere Protokolle, die jeweils ein Subset dieser Eigenschaften erfüllen, aber im Großen und Ganzen hilft das um zu verdeutlichen, warum man Axolotl eigentlich braucht. Und zwar mit PGP kann man nicht besonders gut Synchroen kommunizieren. Also Synchroen im Sinne von beide Leute sind gleichzeitig online und tauschen Nachrichten aus. Ist ein bisschen Definitionssache, aber es ist zumindest nicht direkt ins Protokoll eingebaut mit Message Numbering und ähnlichem. OTR ist extra dafür gebaut worden, dass man Synchroen kommuniziert. Und Axolotl kann uns halt auch Asynchroen wiederum, kriegt OTR so gut wie überhaupt nicht hin. Also man kann es schon machen, aber nur, wenn man die Sicherheit dafür aufs Spiel setzt. Und PGP wurde dafür geschaffen, aber Axolotl ist dafür auch gedacht. Forward Secrecy hat man bei PGP keine. Auf die einzelnen Begriffe gehe ich noch einmal ein. Bei OTR war es eines von den Hauptzielen bei der Entwicklung, dass Forward Secrecy umgesetzt ist. Axolotl kann auch das. Und plausible Deniability, erkläre ich auch später noch mal genauer, hat man bei PGP nicht. Es sei denn man fängt an seine Nachrichten nicht zu signieren, in dem Fall kann man es sogar gleich wegschmeißen. OTR hat das und Axolotl auch. Es gibt natürlich viele andere Protokolle, aber die meisten davon vereinen nicht das alles, was Axolotl vereinen kann. Das ist das Axolotl-Protokoll. Als ich angefangen habe, das zu implementieren, saß ich so für diesen Text. Ich habe mir das durchgelesen und mir gedacht, okay, gut. Aber ich führe vielleicht erstmal ein paar Grundlagen ein. Und zwar erstmal eine Hash Funktion. Was ist eine Hash Funktion? Ich habe irgendein Datensatz, eine Datei, ein String, sonst irgendwas. Steckt das in eine Hash Funktion und bekomme einen sogenannten Hash raus. Das ist eine Zeichenkette fest, also eine Byte-Kette fester Länge mit bestimmten Eigenschaften. Nämlich, wenn ich diese Kette von Bytes habe, komme ich nicht einfach zurück auf den Input, den ich in die Hash Funktion gesteckt habe. Also nur durchprobieren und letztendlich über eine Byte-Attack sozusagen. Wenn ich die Daten, die ich reingebe, nur ein bisschen verändere, dann hat die Hash Funktion die Eigenschaft, dass das, was rauskommt, komplett anders ist und da kein großer Zusammenhang besteht. Jetzt zu Message Authentication Codes. Erstes Szenario. Wir haben Alice und Bob und Alice hat eine Nachricht. Die möchte sie gerne Bob schicken. Was macht sie jetzt? Aber es gibt auch noch Eve. Und Eve liest mit und kann den Datenstrom zwischen Alice und Bob beeinflussen. Was macht Eve jetzt? Er schickt aus durch eine andere und schickt das weiter an Bob. Und Eve freut sich, weil das hat perfekt funktioniert. Als Lesung für dieses Problem gibt es Message Authentication Codes. Es gibt auch noch andere Lösungen, aber ich möchte jetzt auf Message Authentication Codes eingehen. Wir haben eine Nachricht und ein Schlüssel und eine Mac Funktion, in dem Fall eine Hash Mac Funktion. Und daraus bekommen wir einen sogenannten Message Authentication Code, ein Mac. So, was kann man damit anfangen? Wir haben wieder Alice und Bob, beide haben einen gemeinsamen Schlüssel und Alice hat wieder eine Nachricht, die sie schicken möchte. Aber als Erstes benutzt sie ihren Schlüssel, um einen Message Authentication Code zu generieren. Schickt das Ganze los. Eve bekommt das natürlich wieder mit. Tauscht die Nachricht aus, es wird an Bob weitergeleitet. Okay. Bob nimmt jetzt seinen Schlüssel. Bestimmt auch den Message Authentication Code von der Nachricht. Merkt aber, der ist anders als der, den Alice gemacht hat. Und dementsprechend weiß er, die Nachricht kann nicht korrekt angekommen sein und löscht sie einfach. Und Eve ist natürlich traurig, weil das hat nicht funktioniert. Ja, andere Lösungen für das Problem sind Signaturen mit Public Key, Cryptography. Wir haben ein Private Key, den hier, und ein Public Key und eine Nachricht. Wir nehmen die Nachricht und den Private Key, stopfen das in irgendeine Funktion, die signieren kann und bekommen eine Signature daraus. Auf der anderen Seite, wenn wir das verifizieren wollen, nehmen wir eine Verifizierung Funktion, die Nachricht, dann die Signature und den öffentlichen Schlüssel. Und das sagt uns dann, okay, die Signature ist gültig oder nein, die Signature war nicht gültig. Wie sieht das jetzt aus? Selbes Szenario wieder, nur dass Alice und Bob in dem Fall, Alice hat ein Private Key und ein Public Key. Und Bob hat den Public Key Anteil davon. Jetzt macht Alice eine Signature, schickt es los, Eve tauscht wieder die Nachricht aus und Bob kann jetzt mit der Verifizierung Funktion feststellen, Signature ist falsch, kann die Nachricht löschen, alle sind glücklich, bis auf Eve. So, wenn man über Signaturen spricht, dann kann man auch anfangen über plausible Denialbility zu sprechen. Sagen wir, Alice hat eine Nachricht signiert mit ihrem privaten Schlüssel und Eve hat das abgefangen. Jetzt kann Eve sagen, du, Alice, hast diese Nachricht geschrieben, weil du bist die einzige Person, die diesen Schlüssel hat. Alice kann jetzt sagen, nein, das war ich nicht, aber sie wird trotzdem verhaftet dafür, dass sie diese Nachricht geschrieben hat, weil es wurde darüber, dass sie die einzige im Besitz dieses Schlüssel ist, nachgewiesen, dass sie diese Nachricht geschrieben hat. Plausible Denialbility sagt einfach nur, es gibt keine Signature, die nur von der Person erstellt worden sein kann, die diese Identität oder diesen privaten Schlüssel hat. Das heißt, vor Gericht gäbe es genauso viel Beweislast gegen jemanden, wie wenn man ein Klartextmitschnitt hat. Zugegeben, Klartextmitschnitte reichen in der Regel auch aus, um Leute zu verhaften, aber die Situation ist zumindest ein bisschen besser. Symmetrische Verschlüsselung. Wir haben wieder Alice und Bob. Alice hat eine Nachricht, die sie schicken möchte. Ein Schlüssel und irgendwie hat Bob auch den selben Schlüssel. Sie verschlüsselt das und Bob entschlüsselt das wieder mit dem selben Schlüssel. Wie kommt jetzt der Schlüssel eigentlich von A nach B? Und da kommt jetzt Diffie Hermann ins Spiel. Ich habe jetzt nicht den ganzen kompletten Diffie-Hermann-Key-Exchange genommen, sondern einen mit hart codierten Parametern, weil das auch das ist, was in Axolotl eingesetzt wird. Wir haben Alice und Bob. Sie haben beide ein Private und ein Public Key. Das sind jetzt jeweils unterschiedliche. Und den Public Key tauschen sie aus. Das heißt, Alice hat jetzt Bob's Public Key und Bob hat Alice's Public Key. Alice macht jetzt Folgendes. Sie hat diese Diffie-Hermann-Funktion mit ganz zahlen Eigenschaften, die man gleich sehen wird. Sie nimmt ihren eigenen Private Key und Bob's Public Key, den sie bekommen hat und bekommt daraus ein Shared Secret. Shared Secret, weil sehen wir gleich. Bob hat dieselbe Diffie-Hermann-Funktion, nimmt aber seinen eigenen Private Key und Alice Public Key. Und hier passiert jetzt die Magie aufgrund der Eigenschaften der Diffie-Hermann-Funktion, kommt dabei derselbe Shared Key raus. Das heißt, somit ist das Einzige, das ausgetauscht wurde, dieser Public Key. Und trotzdem, den ja alle wissen dürfen. Und trotzdem haben beide ein gemeinsames Shared Secret, das Sie nur kennen. Dann zum Prinzip der Forward Secrecy und warum man das vielleicht haben möchte. Erstmal das Szenario ohne. Wir haben wieder Alice und Bob. Beide haben Schlüssel, haben sie zum Beispiel über Diffie-Hermann ausgetauscht, wer weiß. Jetzt gibt es die erste Nachricht. Die wird von Alice mit dem Schlüssel verschlüsselt und an Bob geschickt. Aber unser alter bekannter Eve ist auch wieder mit dem Spiel und schneidet die verschlüsselte Nachricht mit einfach mal so Vorratsdatenspeicherungen, so nach dem Motto. Das selbe mit der nächsten Nachricht. Selber Schlüssel, selbe Nachricht. Nein, nicht selbe Nachricht, neue Nachricht. Neuer Ciphertext wird auch mitgeschnitten. Jetzt haben wir vielleicht ein paar Jahre später, keine Ahnung, Gerichtsprozess oder ähnliches. Und jetzt wird das Handy beschlagnahmt oder der Computer oder sonst was. Und wir haben immer noch die mitgeschnittenen Daten hier. Und wir gehen jetzt davon aus, dass die hier nicht mehr verfügbar sind, weil sonst wäre das Szenario irgendwie sinnlos. Aber wir haben immer noch diese zwei verschlüsselten Nachrichten. Jetzt holt sich Eve den Schlüssel und kann die einfach beide entschlüsseln, ohne diesen Klartext hier jemals gesehen zu haben. Den will man natürlich nicht haben. Ich meine, Eve freut sich, aber Alice und Bob eher weniger. So, wie kann man das Ganze besser machen? Alice und Bob haben jetzt einen Schlüssel, der mit 1 nummeriert ist und benutzen den, um die erste Nachricht auszutauschen. Eve schneidet das natürlich wieder mit, wie im vorherigen Szenario. Aber jetzt passiert was Besonderes, nämlich Alice und Bob machen einen zweiten Schlüssel und löschen den ersten. Wie der zweite Schlüssel zustande kommt, das hängt davon ab, was man tut. Aber in dem Fall nehmen wir das einfach mal hin. Genauso die nächste Nachricht. Nachrichten nummer zwei wird mit dem zweiten Schlüssel verschlüsselt, wird verschickt, wird von Eve mitgeschnitten. Und jetzt werden die Schlüssel auch von Alice und Bob gelöscht. Die Schlüssel gibt es nicht mehr, mit denen die Nachrichten verschlüsselt wurden. Weil die Nachrichten sind ja bei Bob angekommen, also braucht er den Schlüssel auch nicht mehr. Wenn jetzt einige Zeit später Eve versucht, an die Schlüssel reinzukommen, um den Cyphertext wieder zu entschlüsseln, dann wird ihm das nicht gelingen. Und, ja, freut sich nicht unbedingt darüber. Ja, dann müsstest du sie halt selber speichern. Man speichert sowieso nie den Cyphertext, sondern man kann auch den Cyphertext speichern, aber in der Regel speichert man an dem Ende, an dem die verschlüsselte Nachricht empfangen wurde, schon die entschlüsselte Nachricht und nicht den Cyphertext. Aber falls du nicht möchtest, dass gelesen wird, was du geschrieben hast, dann kannst du ja einfach deinen Cyphertext löschen und brauchst dich nicht darum, nicht deine Cyphertext-Türigung, deine Nachricht, die du empfangen hast oder geschrieben hast, löschen und musst dich nicht um diese zwei Cyphertext hier kümmern. So, Keyderivation. Wir haben ja schon gemerkt, dass es hier diese zwei Schlüssel gab, die dann plötzlich erschienen sind. Wir haben einen alten Schlüssel und wir haben eine sogenannte Keyderivation-Funktion mit einem Subkey-Counter. Wenn wir diesen alten Schlüssel und die Zahl in die Keyderivation-Funktion reinstecken, dann kommt da ein neuer Schlüssel raus, ein Subkey-1. Dasselbe kann man mit einem neuen Subkey-Counter machen und haben wir Subkey-2. Jetzt ist es folgendermaßen, wenn wir die beiden Subkeys 1 und 2 haben, haben wir keine Möglichkeit, also ähnlich wie bei der Hash-Funktion, keine einfache Möglichkeit, auf den Ursprungskey zurückzuschließen. Genauso sind die beiden Subkeys nicht irgendwie auf eine Art und Weise zusammenhängend, dass man herausfinden könnte, wenn man nur die Schlüssel hat, dass sie von demselben Key abgeleitet wurden. So, jetzt sind wir mit den Grundlagen durch und sind bei Axolotl selbst angekommen. Wir haben Alice und Bob. Die wollen eine Nachricht austauschen und schaffen es irgendwie, ein Masterkey auszutauschen. Irgendwie, weil es im Axolotl-Protokoll nicht spezifiziert. Daraus leiten sie ein Rootkey ab und Anfang mit diesem Rootkey beginnt Alice eine sogenannte Message Chain. Verschickt die erste Nachricht, die zweite Nachricht usw. Bis irgendwann Bob antwortet und dafür entsteht ein neuer Rootkey und eine neue Message Chain. Mit der ersten, zweiten Nachricht dann antwortet Alice wieder, sagt auch dafür, dass es wieder neuen Rootkeys gibt. Zum Verständnis, diese Rootkeys sind gleich auf beiden Seiten, die kennen beide. Das ist ein Erz-Secret, um das nochmal klarzustellen. So, jetzt mal mehr zu den Details. Wie passiert das mit diesen Rootkeys? Ja, Frage? Ach so, ich soll die Frage wiederholen, ja. Die Frage war, ob Eve, wenn sie oder er den Masterkey bekommt, dadurch alle Rootkeys herleiten kann und nein, das geht nicht so einfach, dafür gibt es noch mal weitere Maßnahmen. Aber es ist trotzdem sehr schlecht, weil als aktiver Angreifer kann man das dann letztendlich schon unter bestimmten Bedingungen. So, wie kommen diese Rootkeys zustande? Und zwar, wir haben den Eden-Rootkey und ein Kurzzeitschlüsselpaar, ein privaten und öffentlichen Kurzzeitschlüssel. Wo die herkommen, dazu später. Wir nehmen den privaten Kurzzeitschlüssel und den öffentlichen und machen damit wieder unser Defi-Helmen. Das hängen wir zusammen mit dem Rootkey, dem Eden und machen damit die Keyderivation-Function mit Subkey Counter 1. Also es steht ein bisschen anders im Protokoll drin, da wird das mit einer Kombination aus HMAC, HASH und dann Keyderivation-Function gemacht, aber das Prinzip ist eigentlich das Gleiche, wie hier dargestellt. Und daraus entsteht dann eben der nächste Rootkey. Das heißt, um den nächsten Rootkey zu bekommen, braucht man den vorherigen Rootkey und eben ein paar von Kurzzeitkeys und das wird gleich noch genauer erklärt. So. Wie funktioniert das jetzt genau? Ausgangssituationen. Wir haben einen Rootkey, in dem Fall Nummer 1. Bob hat ein ephemeral Keypaar, also Kurzzeitkeypaar und Alice hat auf irgendeine Weise, auch dazu später, den Public-Part von diesem Keypaar bekommen. Jetzt möchte Alice in Nachricht schreiben und erstellt dafür ein neues eigenes Kurzzeitkeypaar. Das davon schickt sie den öffentlichen Part an Bob. Das heißt, Bob hat jetzt sein eigenes Keypaar und den öffentlichen Part von Alice. Und Alice hatte Bob's öffentlichen Part und das eigene Keypaar. Bob macht jetzt Folgendes. Bob nimmt den vorherigen Rootkey, seinen eigenen privaten Kurzzeitkey und Alice öffentlichen und benutzt die Keyderivation-Function von der vorherigen Folie, um den nächsten Rootkey daraus abzuleiten. Aufgrund der Eigenschaften von Diffie Hellmann kann Alice das Gleiche auf der anderen Seite machen, indem sie denselben Rootkey nimmt, den Rootkey Nummer 1, den eigenen Private Key und Bob's Public Key. Und damit hat man den Rootkey ausgewechselt durch einen neuen. Genauso geht es dann weiter, wenn Bob jetzt antwortet. Ach ja, und das Einzige, was dabei übertragen wurde, um das möglich zu machen, war dieser Public Key. Bob macht jetzt dasselbe, macht sein eigenes neues Kurzzeitkeypaar, sein altes wird dadurch obsoliert, schickt den öffentlichen Part davon an Alice. Alice macht wieder die Rootkeyderivation, um den nächsten Rootkey zu machen. Diesmal mit dem neuen Public Key von Bob, aber immer noch ihrem selben Private Key von vorher. Und hat damit den Rootkey. Bob macht dasselbe mit seinem neuen Private Key, aber dem gleichen Public Key, den sie auch vorher schon von Alice hatte. Den er von Alice hatte vorher. Ja, Frage? Lauter bitte. Die Frage war, welche Stärke haben die ephemeral keys? Das Axolotl-Protokoll selbst spezifiziert nicht, welche Kryptopremative man verwendet, sondern nur, man hat ein Public Private Key-System mit einem Diffy-Helmen. Und man hat eine Möglichkeit, authentifizierte symmetrisch verschlüsselte Nachrichten zu schicken. Außerdem eine HMAC-Hash Function und eine Keyderivation Function. Und aus diesen Primitiven wird dann das Axolotl-Protokoll zusammengebaut. Welche man dafür nimmt, ist nicht im Protokoll selbst spezifiziert. Später gehe ich noch darauf ein, welche primitive Signal und WhatsApp verwenden. So, dann macht Alice wieder ein neues Key-Pair. Und es schickt davon den öffentlichen Part an Bob und so weiter, um eine neue Fahrt, wieder ein neuer Road-Key, und so weit so gut. Ja, Frage? Wie geht man mit Race-Conditions um? Wenn ich was im Protokoll kies verwerfe, dann habe ich jetzt einen neuen Baubau, habe ich jetzt meinen, habe ich noch eine Weltkontakte nachzudrücken. Man behält die Keys schon so lange, bis man alles abgeleitet hat, was man braucht. Also, ich wollte hier nur erst mal einen Überblick machen. Wenn man genauer Details wissen möchte, dann kann man mit dem Überblick, den ich vermittelt habe, auch das Protokoll selbst durchlesen, und hat vielleicht ein Verständnis dafür, wie das alles zusammenhängt. So, jetzt das Ganze nochmal. Wir haben den Eaton-Root-Key. Und Alice macht neuen Key. Dadurch gibt es und versendet Nachrichten. Dadurch gibt es einen neuen Road-Key. Bob macht das neue Ephemeral-Key per, macht damit eine Message Chain, und es gibt einen neuen und so weiter. Also immer so abwechselnd. Dadurch wird der Schlüssel, also das Schlüsselpaar, auf dem diese Road-Key basieren, immer neu generiert und durchgewechselt. Und damit erreicht man auch eine Eigenschaft, die sich Future-Secretion nennt. Also, es gibt das kein offizieller Begriff, aber wird gerne in dem Kontext verwendet. Wenn jemand es schafft, einen von diesen Road-Key rauszufinden, und dann aber dieses Ratchet weiterläuft, und Bob ein neues Key per macht, und es schafft, dass das bei Alice ankommt, dann hat man schon verloren und kann mit diesem Road-Key gar nichts mehr anfangen. Natürlich, wenn man ein aktiver Angreifer ist, dann kann man selber die Rolle von Bob übernehmen mithilfe von dem Road-Key hier, und kann damit das Gespräch hijacken. Aber wenn man den Zeitpunkt verpasst, an dem der ausgetauscht wurde, dann muss man wieder von vorne anfangen und den neuen Road-Key raushinden und so weiter. Gut. Aus dem Road-Key wird nicht nur der nächste Road-Key hergeleitet, sondern es gibt noch mehr symmetrische Schlüssel, die hergeleitet werden, die für Axolotl gebraucht werden. Und zwar erinnern wir uns, das war die Methode, wie man auf den nächsten Road-Key kommt. Wir machen Diffie-Helmen aus unseren Ephemeral-Key-Pairs. Das eine ist immer von einem selbst, das andere ist immer von der anderen Person. Und wir nehmen den vorherigen Road-Key. Mit Sub-Key-Counter-1 bekommen wir den nächsten Road-Key. Genauso, wenn man Sub-Key-Counter-2 benutzt, bekommt man den nächsten Header-Key. Damit verschlüsselt man den Header mit Nachrichtennummern und so weiter. Dazu auch später mehr. Das ist übrigens nicht verpflichtend. In Axolotl kann man sich aussuchen, ob man Header-Key benutzen möchte oder nicht. Und wichtiger, ein sogenannter Chain-Key mit Sub-Key-Counter-3. So, wofür braucht man diesen Chain-Key für die sogenannte Message Chain? Message Chain, weil es aneinander verkettet ist sozusagen. Wenn wir den Eaton-Message-Key haben und stecken das in die Key-Drivation-Funktion mit Sub-Key-Counter-1, bekommen wir daraus den Eaton-Message-Key. Message-Key, weil damit werden dann die Nachrichten verschlüsselt, die tatsächlich verschickt werden. Genauso mit Sub-Key-Counter-2 bekommen wir den nächsten Chain-Key, also den nächsten in der Message Chain. Das sieht dann folgendermaßen aus. Ich habe einen Chain-Key 0, leite daraus mit Sub-Key-Counter-1 mein Message-Key ab und kann damit eine Nachricht verschlüsseln und verschicken oder auf der Gegenseite entschlüsseln. Wenn ich das gemacht habe, lösche ich das. Und genauso leite ich danach den nächsten Chain-Key ab mit Sub-Key-Counter-2 und lösche den vorherigen Chain-Key. Und da sieht man schon, wo diese Forward Secrecy steckt. Erstens in dem Austausch von diesen Loot-Key. Und zweitens darin, dass sowohl der Chain-Key, mit dem man hier weitere folgende Sachen verschlüsseln kann, als auch der Message-Key, die werden gelöscht, also kann man sie auch nicht mehr nachträglich knauen, um die verschlüsselten Nachrichten zu bekommen. Man hätte jetzt auch nur einen Schlüssel verwenden können. Also man hätte direkt mit dem Chain-Key die Nachricht verschlüsseln können. Aber das macht man nicht, damit man Langzeitaufbewahrung von Keys machen kann. Dazu auch noch mal später mehr. Weil wenn man diese Chain-Key speichern würde und man kriegt die raus, dann kann man nicht nur eine Nachricht damit entschlüsseln, sondern alle, die hier danach gekommen sind. Und man kann sie deutlich wichtiger zu beschützen, als diese Message-Key, weil wenn man einen solchen Key rausfindet, kann man damit nur eine einzige Nachricht entschlüsseln. Hier wieder dasselbe. Wir leiten aus dem Chain-Key den nächsten Message-Key ab, verschlüsseln damit die Nachricht, löschen den wieder. Nächster Chain-Key, löschen den alten Chain-Key. Nächster Message-Key, Nachricht verschlüsseln, löschen, löschen und so weiter. Noch mal alles zusammen. Wie passen diese ganzen Puzzleteile zusammen? Wir haben die Ausgangssituation. Alice hat Bob's öffentlichen Schlüssel, also den ersten Kurzzeitschlüssel, den öffentlichen Part, des ersten Kurzzeitschlüssel, der Family-Key. Und Bob hat ein Family-Key per, also selber öffentlicher Schlüssel und der zugehörige Private Key. Und beide haben diesen Dubiosen-Master-Key. Damit betreiben sie dieses Ratchet und machen den ersten, und Alice fängt eben an, ein Family-Key per zu machen und damit haben wir den ersten Root-Key. Und angefangen damit mit diesem Root-Key, kann man ja den ersten Chain-Key ableiten und damit diese Message-Chain durchlaufen lassen. Aus dem Chain-Key leitet man den Message-Key ab und die Nachricht wird verschlüsselt. Und dann machen wir den nächsten Chain-Key und so weiter. Eine Message-Chain. Das geht so lange, wie Alice hintereinander Nachrichten schickt, ohne eine Antwort bekommen zu haben von Bob. Sobald Bob antworten möchte, macht er wieder ein neues Schlüsselpaar und damit einen neuen Root-Key und startet seine eigene Message-Chain, die dann durchläuft und so weiter. Wenn Alice wieder antworten möchte, macht sie ein neues Key per. Dadurch gibt es einen neuen Root-Key, neue Message-Chain und so weiter. Wie sieht jetzt so eine Nachricht aus, die verschickt wird? Das ist nur beispielhaft, weil wie man das in der Praxis dann wirklich umsetzt, ist noch mal ein bisschen anders. Aber das ist das Minimum an Sachen, die man übertragen muss, damit das Ganze funktioniert. Also wir haben ein Header-Key, der ist optional, wie gesagt, nur wenn man die Metadaten im Header verschüsseln möchte. Und wir haben ein Message-Key. Der Header-Key, wenn wir uns erinnern, der wird aus dem aktuellen Root-Key abgeleitet und der Message-Key kommt aus dieser Message-Chain. Das heißt, alle Nachrichten aus einer Message-Chain haben alle denselben Header-Key. Das wird auch im Protokoll benutzt, um den Austausch des Root-Keyes zu signalisieren. Wenn der Header-Key sich geändert hat, weiß man, man muss einen neuen Root-Key machen und das Ratchet weiterlaufen lassen. In dem Fall, dass man Header-Keyes benutzt. Wenn man keine benutzt, kann man auch das anders signalisieren. Müsste ich jetzt nochmal nachlesen, um ehrlich zu sein. Der Header sieht folgendermaßen aus. Der enthält eine Message-Number. Das ist die Nummer der Nachricht in der aktuellen Message-Chain und eine previous Message-Number. Das ist die Anzahl der Nachrichten. Wenn ich jetzt gerade eine Nachricht schicke, schicke ich, welche Nummer in der aktuellen Message-Chain die Nachricht ist. Das war das hier. Aber ich schicke auch, was die vorherige Anzahl meiner eigenen vorherigen Message-Chain waren. Da wird man später noch sehen, warum man das braucht. Es ist damit die letzte Message-Number, entweder die Anzahl oder die Anzahl minus 1. Die Frage war, ob ich die Nummer meine, nicht die Anzahl. Das ist dieser Public Family Key, der vorher ausgetauscht wurde, den man vorher gesehen hat, der bei dem Ratchet ausgetauscht wird. Zwar ist er wirklich in jedem Header drin von jeder Nachricht, weil die erste Nachricht kann verloren gehen. Das heißt, man schickt ihn einfach immer mit. Damit wäre auch dieser Austausch geklärt, wie der zustande kommt. Der Header wird dann mit dem Header-Key verschlüsselt, die Nachricht mit dem Message-Key und das Ganze zu einem Paket zusammengebaut. Da kann man dann noch mehr drum machen, je nachdem, wie man das in der Praxis dann machen möchte. Aber das ist nicht Teil von dem Protokoll selbst. Die Frage war, wenn die Nachricht verloren geht, gibt es dann, ich hoffe, ich habe es richtig verstanden, gibt es dann eine Möglichkeit, im Protokoll festgelegt, um sicherzustellen, dass die neu versendet wird oder man da neu dran kommt. Nein, gibt es nicht. Man kann nur feststellen, dass die Nachricht fehlt. Es sei denn, jemand blockt einfach die ganze Kommunikation, dann kann man gar nichts mehr feststellen. Aber dazu jetzt genau hier übersprungenen Nachrichten. Und zwar, wir haben folgendes Szenario. Alice schickt nacheinander vier Nachrichten in ihrer Message-Chain. Dann antwortet Bob, sendet eine Nachricht und Alice antwortet mit einer Nachricht. Wie sieht das Ganze jetzt in dem Fall aus Bob's Perspektive aus? Wir wissen ja, das Internet ist manchmal nicht ganz so zuverlässig oder auch andere Netzwerke. Wir haben vielleicht auch einen Angreifer, der sich entscheidet, einzigen einzelnen Nachrichten unter den Tisch zu kehren. Schauen wir uns mal an, was passiert. Bob empfängt die erste Nachricht, soweit so gut. Bob empfängt noch eine Nachricht, aber nachdem Bob den Header entschlüsselt hat, sieht er, oh, das ist ja die dritte, nicht die zweite. Da mit der Information, dass es die dritte Nachricht ist, kann man jetzt die Message-Chain zwei Schritte weiterlaufen lassen. Dabei wird ja auch der Message-Key für die zweite Nachricht hergeleitet. Den nimmt man einfach und speichert ihn ab, zusammen mit dem aktuellen Header-Key in der Liste. So, jetzt schickt Bob seine Nachricht. Wer aufgepasst hat, hat vielleicht mitbekommen, dass Nachricht Nummer vier noch nicht angekommen ist. Aber Bob weiß ja nichts davon. Also, Bob macht ein neues Schlüsselpaar, leitet sich einen neuen Hut-Key ab, fängt eine neue Message-Chain an und schickt die erste Nachricht weg. Und jetzt bekommt er auch noch eine Nachricht von Alice. Okay, soweit so gut. Jetzt schaut er aber in den Header von der Nachricht, die er von Alice bekommen hat und sieht, aha, die previous Message-Number ist vier. Er hat aber nur bis zur dritten Nachricht gesehen, dass Nachrichten angekommen sind. Also macht er Folgendes. Er lässt die Message-Chain so lange weiterlaufen, bis diese Nummer hier erreicht ist und alle Schlüssel, die er dabei findet, nicht zu einer Nachricht passen, speichert er einfach hier in diese Liste ab. Danach kann er alle Schlüssel, die zu dieser Chain gehören, löschen, weil er weiß, da kommt nichts mehr. Einige Zeit später, die Verbindung hat sich wieder eingefangen. Bob erhält zwei Pakete. Bob weiß überhaupt nicht, was da drin ist, kann nicht mal den Header lesen, weil es sehr auch verschlüsselt. Also, wenn man Axolotl mit Headerverschlüsselung benutzt. Also fängt er einfach mal an. Probiert diesen Schlüssel aus, also dieses Schlüssel Paar aus, um es zu entschlüsseln. Funktioniert nicht. Okay, nächstes. Hat geklappt. Das war die vierte Nachricht von Alice. Kann er den Schlüssel löschen. Jetzt hat er ja nur noch einen Schlüssel zum Durchprobieren. Probiert den aus und merkt, ja, das war die zweite Nachricht. Perfekt entschlüsselt, kann gelöscht werden. Ein bisschen muss man da aufpassen, wenn man das implementiert, weil angenommen, Alice ist böse. Und entscheidet sich dazu, sagen wir die Message Number ist ein 32-bit Integer. Wir schreiben einfach mal als previous Message Number hier den maximalen 32-bit Integer rein. Wenn man dann nicht aufgepasst hat bei der Implementierung, dann wird Bob's Handy plötzlich total warm und meldet sich erst mal nicht mehr, bis es diese ganzen Keys berechnet hat. Und dazu muss Alice natürlich überhaupt gar keine, gar nicht so viele Nachrichten verschickt haben. Es reicht ja einfach nur, diese Zahl da reinzuschreiben. Genauso sollte man gucken, also wenn man wirklich eine schlechte Verbindung hat, kann es ja auch vorkommen, dass die Teams ganz viele Nachrichten verloren gehen. Und in dem Fall sollte man auch die Größe von seiner, was heißt ich, Staging Area, oder wie sich das nennt, begrenzen. Entweder gibt man den Messages ein Timestamp und löscht sie, wenn sie ein bestimmtes Alter erreicht haben, also den Keys ein Timestamp, Entschuldigung. Oder man limitiert einfach die Größe von diesem Zwischenspeicher und löscht dann, wenn es zu viel wird. Also Dinge, die stehen nicht im Protokoll drin, die sollte man aber beachten, wenn man es umsetzt. So. Gut, soweit so gut. Das war das komplette Axolotl-Protokoll. Aber es reicht noch nicht ganz aus, um es in der Praxis wirklich einzusetzen. Nämlich erst mal, wo kommt überhaupt dieser Master Key her? In dem Fall nehme ich die Variante, die Signal und WhatsApp benutzen und die auch ich benutzt habe in meiner Library-Molch, um den Master Key zu bekommen. Und zwar nehmen wir jetzt einfach mal hin. Alice hat ein Identity Keypair und Bob hat ein Identity Keypair. Und das sind wirklich Langzeitschlüssel. Also es ist ein bisschen vereinfacht. WhatsApp hat letztendlich 2 und signiert den einen mit dem anderen, aber das lasse ich mal unter den Teppich fallen. Unter den Tisch fallen. Das kann auch ein Schlüssel sein, der mehrere Jahre verwendet wird. So. Außerdem haben Sie, wir wissen immer noch nicht, wo die herkommen, ganz am Anfang, irgendwie muss das noch passieren, aber darauf gehe ich gleich ein, beide haben ein Kurzzeit Keypair, das Sie generiert haben. Das wird für jede neue Konversation, die man anfängt, werden die hier neu generiert, z.B. Details dazu später. Jetzt macht Alice auf der eigenen Seite folgendes. Erst mal ein Diffy Hellman von dem privaten Identity Key und Bob's Public Family Key. Also wir sehen schon, es sind nicht beides Identity Key, es ist ein bisschen durchgemischt. Das Sabre macht Bob auf der anderen Seite andersrum, mit dem eigenen privaten Family Key und Alice Public Identity Key. Wir sehen wieder dieses klassische Prinzip bei Diffy Hellman. Davon die Private Variante landet hier als Public Key und hier der Public Key von dem Keypair landet hier als Private Key und jetzt sind die beiden hier gleich. Das Sabre mit Alice Family Key und Bob's Public Identity Key und auf der anderen Seite mit Bob's Private Identity Key und Alice Public Family Key. Wieder beides gleich, das wird aneinander gehängt, also dieser Strich heißt Verkettung in dem Fall. Das Ganze macht man auch nochmal mit den beiden Family Keypairs. Und stopft das dann in der Keyderivation Funktion. Das ist jetzt nicht wirklich Subkey Counter 1, aber ich habe das einfach mal genommen, weil ich meine Keyderivation Funktion mit Subkey Counter definiert habe. Und daraus bekommen wir dann den Master Key und haben das Share Secret. Also so weit so gut, wir haben den Master Key. Die Identity Keys, die werden halt über irgendeine Art von Public Key Infrastructure oder einfach über den zentralen Server im Fall von Signal und WhatsApp ausgetauscht. Und den möchte man auch gerne nochmal verifizieren, wenn sich die beiden treffen. Irgendwas werde ich gerade noch... Ah, verdammt. Wo kommen diese Family Keys her? Und zwar gibt es dafür so genannte Pre Keys. Bob, wenn er sich bei Signal oder WhatsApp anmeldet, generiert erstmal Pauschal so N-Family Keys. Und es gibt einen zentralen Server. Es kann auch was verteiltes sein. Er kann das Ganze mit seinem Identity Key signieren. Dann kann er es lagern, wo er möchte. Dann aber den Timestamp nicht vergessen, weil sonst bringt das Ganze nicht so viel. Also dann bringt es schon was. Aber wenn man dann eine alte Variante davon hat, es bringt nicht, die Keys auszutauschen, wenn man den Timestamp vergisst. Jetzt sind auf dem Server die Public Key Anteile von diesen ganzen Kurzzeitkeys gespeichert. So. Jetzt kommt Alice. Und möchte gerne eine Verbindung mit Bob aufnehmen. Alice kennt den Identity Key von Bob. Kann dadurch verifizieren, dass die Pre Keys auch wirklich von Bob kommen. Wobei in diese Herleitung von dem Master Key sowieso die Identity Keys eingehen. Das heißt, da ist man schon mal abgesichert. Alice sieht jetzt, es gibt N Public Pre Keys auf dem Server und schmeißt den Zufallsgenerator an und generiert eine Nummer i. Da muss man auch aufpassen, dass man gleich verteilt Zufallszahlen nimmt, nicht einfach irgendwas mit Zufallszahlen füllen und was abschneiden oder mit Modulo arbeiten. Dann kommt nämlich nichts gleichverteiltes bei raus. Diese Zahl und Bob's Identität schickt Alice jetzt an den Server, um dem Server zu sagen, hey, ich hätte gerne Bob's Eatn Pre Key. Jetzt kommt der Server und schickt Bob's Eatn Pre Key zurück. Und danach, also das Minus i ist jetzt nicht mathematisch zu verstehen, sondern der It Key wird auf dem Server gelöscht. Der wurde verwendet. Damit ist er verbrannte Erde und soll nicht mehr verwendet werden. Also wird er einfach gelöscht. Das war's eigentlich schon, weil damit ist die Frage geklärt, wo kommt eigentlich dieser fmware key her? Die Frage war, was passiert, wenn der Server mehrfach dieselben fmware keys rausgibt und die nicht löscht? Hab ich das richtig verstanden? In dem Fall ist es so, dass Bob, wenn der Key verwendet wurde, den Private Key part davon auch löscht, also funktioniert es einfach nicht. Also klar, wenn man den Identity geknackt hat und den fmware key auch, dann ist das schlecht, dann hat man sowieso verloren. Da hinten war noch eine Frage. Die Frage war, kann man einfach viele Keys anfordern, bis das leer ist. Also über die Implementierung, die Signal und WhatsApp haben, ich habe es so implementiert, dass der Server immer die Liste von allen Keys runtergibt und das komplett auf dem Klein verwaltet wird, welche Keys gelöscht werden und welche nicht. Und die Liste ist dann immer komplett signiert mit Timestamp. Ich muss mir über die Implikationen, die das hat, aus Sicherheitssicht noch ein bisschen mehr Gedanken machen. Aber klar, wenn das so ist, wie ich es verstanden habe bei Signal und WhatsApp, kann man von dem Server wirklich alle Prekeys anfordern, dann sind da keine mehr und dann kann keiner mehr eine Verbindung aufbauen. Aber ich glaube, dass die Off-and-Transport Layer oder so, dass sie einfach eine authentifizierung mit dem zentralen Server haben, auf dem die Prekeys gespeichert werden, sodass man so ein Unsinn gar nicht erstreiben kann. Das ist dann aber nochmal eine Protokollebene oben drüber. So, dann mal zu Signal und WhatsApp. Als Identity-Key verwenden beide KERV255019 von Daniel Bernstein oder Bernstein oder was auch immer. Und für die FM-Mail-Keys genauso. Für die Message-Keys wird AES256 und für die Authentifizierung HMAC SHA256 verwendet. Also HMAC ist dieses Hash-Mac, das wir vorher gesehen haben. Und das ist das HMAC, das wir vorher gesehen haben. Das ist das HMAC, das wir vorher gesehen haben. In dem Fall ein Message-Authenticator basierend auf Hash-Funktionen. Man kann mit beliebigen Hash-Funktionen mehr oder weniger, also in Anführungszeichen, kann man solche H-Macs bauen. Das ist einfach eine allgemeine Art und Weise, wie man aus einer Hash-Funktion ein Message-Authenticator macht. Und Hedder-Keys haben beide keine. Das machen sie vermutlich deswegen nicht, weil das braucht mehr Bandbreite, weil man noch noncesoft verwendet, die man übertragen muss und noch mehr overhead hat. Insofern, da sie Transportverschlüsselung haben und man sowieso mehr oder weniger rauskriegt, welche Nachrichten, welche Reihenfolge abgeschickt wurden, macht es dann auch keinen Sinn, die Messagen an was zu verstecken im Hedder. Wie funktioniert Gruppenchat? Die Frage war, ist spezifiziert, dass Protokoll welche Krypto-Primitiven verwendet werden? Die Antwort ist nein. In Protokoll steht überhaupt nicht drin, welche Primitiven man verwenden soll, sondern nur, was die für Eigenschaften erfüllen soll. Das meine ich nicht. In Signal und WhatsApp? Die Frage war, wenn man merkt, dass ein Primitiv komprimitiert wird, ist dann in dem Protokoll eine Möglichkeit verankert, um auf ein neues umzusteigen. In Axolotl selber nicht. Bei Signal und WhatsApp, ich denke, die updaten einfach die Clients, fertig. Weil sie, die gesagt haben, das ganze System kontrollieren und keine verschiedenen Server haben, die betrieben werden und miteinander reden. Insofern kann man den Server austauschen, die Clients austauschen und man ist umgestiegen mit einer Übergangsphase. So wie WhatsApp das auch gemacht hat von kein Axolotl auf Axolotl. Ja, Frage? Ja, die Frage war, wie kann man dann die Übergangsphase machen, wenn man ein Protokoll braucht, um die Übergangsphase zu machen. Aber letztendlich ist das eine Frage der Implementierung und wie Signal und WhatsApp das genau machen. Weiß ich nicht und ich habe es noch nicht implementiert, weil meine Library noch nicht so weit ist. Okay, ich gucke mal auf die Zeit. Stimmt, ich erinnere mich gerade. Es war ein Einwurf bei Signal, es gibt eine Protokollversion. Und ja, ich erinnere mich, ich habe mir das nämlich auch schon angeschaut, offensichtlich, die schicken in jedem Header mit, was die aktuelle Protokollversion ist und welche, die gerade verwendet wird und was der Client maximal unterstützt. Ja, die Protokollversion ist mitauthentifiziert. Ja, die ist in dem Header mit drin. Wie ist es, wenn ich mehrere Clients auf einem Nutzer kaufen habe? Mehrere Clients auf einem... Meistens kann ich ja mehrere Clients auf einem Nutzer laufen lassen. Ich glaube, ich kann... Die Frage war, es gibt verschiedene... Es können mehrere Clients mit dem selben Benutzer existieren bei Signal. Wie macht man das damit der Protokollversion? Ich wusste vorher gar nicht, dass es verschiedene Clients mit dem selben Benutzer geben kann. Insofern müsste ich mich da selber noch mal einlesen. Es gibt den Get Desktop Client und den Nerd Client und den Nerd Client. Bevor die Zeit ausgeht, mache ich jetzt erstmal noch das Fertig und danach kann ich noch mal weitere Fragen beantworten. Wie funktioniert der Gruppen Chat? Bei Signal ist das ganz einfach umgesetzt. Jeder Gruppenteilnehmer startet mit jedem anderen Gruppenteilnehmer eine neue Verbindung über dieses Ratchet und damit gibt es in über zwei gleichzeitig Verbindungen zwischen verschiedenen Gruppenteilnehmern. Wenn ich eine Gruppennachricht in die Gruppe schicke, muss ich bei einer Gruppengröße N Nachrichten verschicken. Dadurch kann es auch N mal unabhängig voneinander passieren, dass das Ratchet dabei kaputt geht oder eine Nachricht nicht ankommt und sonst was. WhatsApp hat sich da was anderes zu überlegt bzw. wahrscheinlich war es auch der selbe Moximal in Spike, der es auch bei Signal gemacht hat. Vielleicht steigt auch Signal darauf um, dass ich davon abwasche, die Security Implications sind. Wir haben Alice und eine Gruppe. Alice möchte der Gruppe beitreten und generiert dafür ein Chanky und ein Schlüsselpaar zum Signieren. Die werden beide an jedes Gruppenmitglied geschickt, also über Standard Axolotl, eine ganz normale Axolotl-Verbindung mit jedem anderen Gruppenmitglied sowie die Gruppennachrichten in Signal implementiert sind. Jetzt haben alle Gruppenmitglieder Alice Chanky und Alice Signier-Ky. Jetzt startet Alice einfach damit, eine Message Chain weiterzuführen und Nachrichten an die Gruppe zu schicken und mit ihrem Schlüsselpaar zu signieren. Damit können alle ... Das wird dann an den Server geschickt, einmal. Der Server verteilt es dann an die einzelnen Teilnehmer der Gruppe. Die einzelnen Teilnehmer der Gruppe führen einfach die selbe Message Chain mit diesem Key durch und überprüfen, ob es wirklich von Alice stammt mit dieser Signatur. Was das für Implicationen hat aus kryptografischer Sicht, da hatte ich noch nicht genügend Zeit mit drüber Gedanken zu machen oder drüber zu lesen. Das habe ich auch nicht allzu viel gefunden. Das ist nur aus dem Security-Wide-Paper von WhatsApp. Genau, wenn jemand die Gruppe verlässt, dann generieren alle Gruppenmitglieder neuen Chain-Key. Damit die Person, die die Gruppe verlassen hat, nicht mehr weiter die Nachrichten entschlüsseln kann. Ja, genau. Das sind meine Quellen. Ich gehe die noch einmal einzeln durch. Das ist das Axolotl-Ratchet, die Protokoll-Speziferation, die auf den Folien vorher auch zu sehen war. Es wurde unbenannt zu Double-Ratchet. Ich weiß nicht, ob das alles noch Axolotl heißt oder Double-Ratchet oder Signal-Protokoll, keine Ahnung. Außerdem ist die Protokoll-Beschreibung dafür, wie Signal Axolotl einsetzt, also wie sie den Master-Key herleiten und lauter solche Geschichten und wie die Nachrichten aufgebaut sind. Das wurde leider gelöscht. Ich weiß nicht, warum. Maximaliens Spike hat das, ich glaube, im Februar oder so gelöscht oder mehr. Man findet es aber noch in der Git-History von dem Wiki-Repository. Dann verschiedene Blockposts von Open Whisper Systems. Die sind sehr interessant. Die kann man sich einfach mal durchlesen. Man sieht sich ganz gut durch. Und das Security-Wide-Paper von WhatsApp, da steht dran, wie die diese Gruppenchats machen und so weiter. Und dasselbe nochmal für Open Whisper Systems und Signal. Ja, das war das Ende. Folien findet man hier auf meiner Webseite unter maxbrückner.de slash gpn16. Man braucht aber ein Unicode-Fond dafür, der Emoji kann. Ja, ist noch Zeit für Fragen? Also, wenn mich keiner stoppt, dann nehme ich auch noch Fragen an. Nimm ich mal hier. Ist es mit Axolotl möglich, mehrere Clients das gleiche Nutzer zu betreiben? Wenn man kann den Identity-Key auf mehrere Clients draufmachen, ist nicht unbedingt eine gute Idee, aber kann man machen. Und dann neue Ratchets starten mit jedem einzelnen Client. Aber eine Möglichkeit, wie man das selbe Ratchet über mehrere Clients betreiben kann, dann wüsste nicht, wie das gehen soll. Vielleicht über Shared Memory, über Devices hinweg. Da hinten. Lauter, bitte. Der Einwurf war, dass die Zusatz-Clients bei WhatsApp die eigentliche App mit dem Schlüssel mehr oder weniger als Proxy benutzen. Dass das Einzige ist, was das eigentliche Ratchet betreibt, alle anderen holen sich das von diesem Handy. Das muss dann auch online sein, würde ich annehmen. Oder irgendwie verbunden sein mit den anderen Clients. Ja, okay. Okay, Frage. Ist es ein Problem genügend Zufall für neue Schlüssel zu bekommen? Wenn der Zufallszahlen-Generator von Linux mal einigermaßen gut gesiedet ist, also ich weiß jetzt nicht, wie Apple das macht, aber ich hoffe, die wissen auch, was sie tun. Das ist ein Problem. Das ist ein Problem. Das ist ein Problem. Das ist ein Problem. Das ist ein Problem. Das muss man doch tun. Man kann nur hoffen. Ich bin wahrscheinlich stets auch in der iOS-Security-Wide-Paper drin, aber das habe ich nicht gelesen. Ich gehe davon aus, dass Def you Random unter Linux oder eben der Get Random System Call ausreicht, um genügend Sicherheit zu bekommen. Das sind ja nur ephemeral Keys, die kurz verwendet werden. Die Identity Keys, da kann man dann vielleicht mehr Aufwand betreiben. Aufwand betreiben. Aber ich glaube, auf dem letzten Kongress gab es auch noch mal ein Talk zu dem Thema. Reicht das eigentlich aus und braucht man Def Random unbedingt zu verwenden oder kann man auch Def You Random verwenden? Ich vertraue einfach darauf, dass es funktioniert, weil genügend Leute der Meinung sind, dass es ausreicht. Ja, hat da jemand gefragt wegen der verschwundenen Spezifikationsseite. Also ich habe nichts gefunden, keine neue Version davon irgendwo gefunden und ich habe auch keine Informationen darüber gefunden, warum es gelöscht wurde. Ich habe aber auch nichts selber nachgefragt. Also bei Open Whisper Systems. Okay, sonst noch irgendwelche Fragen? Gut, keine mehr. Ach so, ja eine noch. Ach so, du meinst jetzt, die Frage war, was steht in dem Header noch so drin? Du meinst bei WhatsApp und Signal? Ach so, nee, das ist im Vergleich zu E-Mail-Header. Das ist kein großer Haufen Text mit allem Möglichen, sondern das sind ein paar Felder, die gefüllt sind, also im Fall von zumindest Signal, ob es eine Pre-Key-Message ist, also die erste Nachricht, die die neue Konversation startet oder nicht, die Protokoll-Version und dann die ganzen, also der DFM-Mail-Key, die beiden Message-Numbers und mehr braucht man eigentlich nicht, dann vielleicht noch irgendwelche Nonces, also diese Number-Use-Once für die Kryptopremative, aber sonst stand nichts. Ja, die Frage ist, was ist, wenn die Pre-Key-Liste mal leer ist? Die Frage kam eigentlich vorher schon mal. Ja, dann hat man Pech gehabt, dann kann man keine Nachricht verschicken. Ja, woher weiß der Kleint, dass er neue Pre-Keyes auf dem Server laden soll? Ich weiß nicht, wie es in Signal und WhatsApp gemacht ist. Bei mir ist es so in Mulch, dass die ganze Pre-Key-Liste sowieso auf dem Kleint verwaltet wird und ausgetauscht werden die dann, wenn sie verwendet wurden. Also man merkt ja, dass der Pre-Key in einem Header drin stand und danach kann man ihn austauschen, aber ich denke, dass es da dann auf der Protokoll-Ebene irgendwas geben wird, also auf der Protokoll-Ebene oben drüber, die Kommunikation zwischen dem Server, der die Pre-Keyes speichert und dem Kleint, die dann dem Kleint sagt, bitte mach mal ein paar neue Pre-Keyes. Alles Spekulationen. Bei Mulch habe ich jetzt momentan 100 genommen, bei WhatsApp und Signal weiß ich es nicht. Ich glaube, also ich verwende eine feste Anzahl, aber von dem, was ich im Security White Paper von WhatsApp gelesen habe, ist die Anzahl dort, glaube ich, dynamisch und wie viele weiß ich nicht. Also ich habe mir auch den Queuequot von Signal nicht, ich habe ihn mir angeschaut, aber ich bin schreiend weggelaufen. Nicht, weil das schlecht ist, sondern weil ich nicht, ich tue mir manchmal schwer, bei großen objektorientierten Anwendungen da den Durchblick zu behalten. Ich habe nicht die Stelle gefunden, an der das AxolotlRatid eigentlich passiert. Es war irgendwo verteilt und dann zu viel Code, um sich das kurz mal anschauen. Gut, warst du das mit Fragen? Okay, dann sind wir hiermit fertig.