Kolumne: Olis bunte Welt der IT

Olis bunte Welt der IT: Nebensachen
Keine Kommentare

Man ist ja nicht nur Programmierer. Klar, Programmierer ist ohnehin eine stark verkürzte Darstellung. Was sagt man, wenn jemand fragt, was man beruflich so macht? Software? Entwickler? Ich selbst sage meist, dass ich mich mit der Programmierung von Computern beschäftige und einen großen Teil meiner Zeit damit verbringe, anderen beizubringen, wie man Computersoftware erstellt. Egal was man sagt, es ist immer nur eine kurze Zusammenfassung mit großen Lücken. Schließlich möchte man auf so eine Frage nicht mit einer Abhandlung antworten, die fünf Minuten dauert.

In Wirklichkeit sind wir ja nicht nur Entwickler oder Programmierer, sondern auch Architekten, Tester, Schreiber von Dokumentation, Anleitungen, Webseiten, Blogs, vielleicht auch Hacker – und ganz allgemein technologieinteressierte Menschen. In anderen Bereichen des alltäglichen Lebens gibt es das in diesem Ausmaß nicht oft. Vielleicht ist jemand auch Mitglied im Dackelclub, betreibt Gymnastik nach Wettbewerbsstandard oder sammelt alte Kaffeemühlen. Diese Hobbys lassen sich allerdings jeweils relativ einfach in ein paar Worten beschreiben. Für mich ist jedoch die Grenze zwischen Hobby und Arbeit fließend, und es liegt zum Teil daran, dass mir eine gute Antwort auf die Frage nach meiner Tätigkeit schwerfällt.

Nun sind es gerade die Nebensachen, die für mich den Umgang mit Computern nach all den Jahren noch immer interessant erscheinen lassen. Mit Nebensachen meine ich solche Aufgaben und Themen, mit denen ich mich außerhalb meiner beruflichen Tätigkeit beschäftige, ohne geschäftliche Gedanken. Da findet sich immer etwas, und ich möchte ein paar Ideen hier weitergeben. Bitte schreiben Sie mir doch eine E-Mail, wenn Sie Vorschläge haben!

Im Schnelldurchgang gehackt

Neulich habe ich ein paar Tools ausprobiert, mit denen man Passwörter hacken kann. Da gibt es verschiedene Ansätze: Wortlisten, allgemeine Brute-Force-Angriffe, solche mit Rainbow Tables – und vermutlich einige mehr. Insgesamt ein komplexes und interessantes Themengebiet. Ich wusste natürlich, dass Brute Force lang dauern kann, aber ich hatte mir noch nie genau angesehen, was für Datenmengen dabei verarbeitet werden. Im Prinzip ist ein Brute-Force-Verfahren ganz einfach: Alle möglichen Kombinationen eines Schlüssels oder Passworts werden ausprobiert. Moderne Verschlüsselungstechnik ist dagegen weitgehend gewappnet. Erstens, weil die Menge der Möglichkeiten groß ist, und zweitens, weil jedes Ausprobieren ziemlich viel Rechenzeit braucht.

Nun habe ich ein Tool gefunden (crunch), das eine Liste von Möglichkeiten erzeugen kann [1]. Das habe ich gleich optimistisch für alle Passwörter mit bis zu acht Stellen aufgerufen, die aus Klein- und Großbuchstaben, Ziffern und einigen Sonderzeichen bestehen können. Das Tool war von meiner Anfrage nicht beeindruckt und machte sich daran, die Liste zu erzeugen. Glücklicherweise informierte es mich aber zuerst, was für eine Aufgabe zu erledigen sei: 53 Petabyte an Daten würden jetzt erzeugt. Ja, Petabyte. Ich habe das dann mal abgebrochen. Unglaublich, was für eine Menge von Daten das ist. Kein Wunder, dass das lange dauert … und dabei sind manche Passwörter bestimmt länger als acht Zeichen.

Nun hatte ich acht Zeichen ausgewählt, weil ich zuvor mit airodump-ng [2] ein Protokoll einer Session meines WLANs erzeugt hatte. Dieses WLAN verwendet WPA2, und nach einer Session über Nacht mit einem WLAN-Lauscher hatte ich erfolgreich einen 4-Way Handshake aufgezeichnet. Mit diesen Informationen sollte ein anderes Tool (hashcat [3]) theoretisch das Passwort für das WLAN knacken können, und ich weiß, dass dieses Passwort acht Zeichen enthält. Nach einem ersten Start von hashcat in einer der VMs auf meinem Laptop stellte sich heraus, dass es auch tatsächlich funktioniert – aber der Laptop wollte dafür mehrere Tage Zeit. Nun unterstützt hashcat auch GPU-basierte Methoden, solange man dafür die richtigen Treiber installiert hat und der Computer über eine Grafik- oder andere Karte mit ausreichend Leistung verfügt (CUDA, OpenCL oder gar FPGA).

Einfacher geht es, indem man einen Cloudrechner verwendet. Ich habe also bei AWS eine P2-Instanz mit Kali Linux in Betrieb genommen, meine Dateien darauf kopiert und hashcat angeworfen – das dauert, pessimistisch geschätzt, fünf Minuten. Mit einer GPU kostet die Instanz etwas unter einem Dollar pro Stunde und der gesamte Vorgang läuft dann etwa acht bis neun Stunden. Statistisch sollte das Passwort nach etwa der halben Zeit gefunden werden. Es gibt auch Instanzen mit 8 oder 16 GPUs, die anscheinend von hashcat auch effizient genutzt werden können – an den Kosten ändert das nichts, aber das Passwort dürfte so innerhalb von 30 bzw. 15 Minuten gefunden werden.

Das gibt mir zu denken. So kann also der Nachbar im WLAN mitlauschen und dann für etwa 4,50 Dollar mein WPA2-Passwort herausfinden. Irgendwie sind 53 Petabyte plötzlich viel zu wenig. Es müsste nicht einmal der Nachbar sein, denn auch in einem vor der Tür parkenden Auto könnte ein Hacker mit einem Laptop sitzen. Für meinen Test habe ich mein Gerät einfach zuhören lassen, aber es gibt auch Tricks, mit denen man den notwendigen Handshake auslösen kann, sodass der Lauschangriff selbst recht kurz sein kann. Vermutlich kann man mit einiger Erfahrung die ganze Sache in 20 Minuten erledigen. Wenn das WLAN gleich mit WEP oder WPS läuft oder das Passwort nichts taugt, gehts auch noch deutlich schneller. Vielleicht nicht ganz so schnell wie in „Mr. Robot“, aber viel schneller als ich es gerne hätte.

Hilfe beim Sudoku

Zu effizienten Algorithmen fällt mir noch etwas anderes ein. Neulich hat mein Kollege Julian Bucknall einen Artikel über einen Sudoku-Algorithmus geschrieben [4]. Die implementierte Methode verwendet einen Brute-Force-Ansatz, probierte also einfach alle Möglichkeiten aus. Ich fand das Thema interessant und Julians Lösung nicht perfekt, da ich für das Backtracking lieber Rekursion verwenden wollte. In ein paar freien Minuten habe ich also meine eigene Lösung implementiert [5]. Julian hatte in seinem Artikel bereits die Tatsache angesprochen, dass manche Sudoku-Puzzles absichtlich oder zufällig gegen Brute Force optimiert sind. Das ist z. B. dann der Fall, wenn der Lösungsalgorithmus oben links mit der Sequenz 1, 2 ,3 … beginnt, die Lösung letztlich aber 9, 8, 7 … lautet. Insgesamt hat ein Sudoku-Feld natürlich 981 Kombinationen, das sind etwas unter 200 Dodezilliarden, eine 2 mit 78 Nullen, also auf Deutsch: echt viele.

Der Lösungsmechanismus funktioniert dementsprechend nur dann gut, wenn die Anzahl der Möglichkeiten, die geprüft werden müssen, beschränkt werden kann. Das geschieht automatisch dadurch, dass im Puzzle Felder vorgegeben werden – aber unglücklich gesetzte Felder können auch negative Konsequenzen haben. Ich hatte in solchen Fällen Erfolg damit, den Algorithmus an anderer Stelle beginnen zu lassen, im einfachsten Fall von hinten. Dazu muss nur die intern geführte Liste der offenen Felder umgekehrt werden; aber natürlich sind auch andere Modifikationen der Ausführungsreihenfolge mit geringem Aufwand erreichbar.

Eine Erkenntnis erschloss sich mir allerdings erst nach mehreren Tests: Es ist wichtig, dass sich das Spielfeld bei einer sequenziellen Vorgehensweise des Algorithmus kontinuierlich füllt. Das führt nämlich dazu, dass Reihen sowie Blöcke des Feldes sich frühzeitig füllen und somit die Auswahl von Ziffern in tieferen Stufen der Rekursion einschränken. Für eine Weile hatte ich die Idee verfolgt, die Prüfungsreihenfolge zufällig erstellen zu lassen, um die Auswirkungen von ungünstigen Strukturen der Feldvorgaben auszuhebeln. Es stellte sich jedoch heraus, dass in diesem Fall auch die Lösung eigentlich einfacher Puzzles mit vielen Vorgaben oft sehr lange dauerte, weil der Effekt der sequenziellen Füllung ausblieb.

Echt effizient?

Neulich habe ich mich auch noch mit einigen Tests zum Thema Datenmengen beschäftigt. gRPC ist derzeit ein großer Hype, besonders im Microsoft-Umfeld. Natürlich gibt es dafür auch gute Gründe, etwa die Unterstützung für effiziente HTTP-2.0-Mechanismen, verschiedene Channeltypen usw. Das ist alles nicht ganz so positiv, wie man nach der Lektüre mancher Artikel meinen könnte – oft wird etwa die Tatsache nicht bedacht, dass Browserclients nur mit besonderer Anbindung bedient werden können, bei der die ganze schöne neue Effizienz auf der Strecke bleibt. Allerdings wunderte ich mich im Laufe der Zeit vor allem darüber, dass viele Anhänger von gRPC vollmundige Versprechungen zur fantastischen Effizienz der übertragenen Daten machten, ohne dabei jemals zu erklären, woher diese Effizienz im Vergleich etwa mit typischer JSON-Codierung rühren sollte.

Ich bin der Sache nachgegangen und habe festgestellt, dass die großartigen Resultate für effiziente Datenübertragung mit gRPC bzw. dem Datenformat „Protocol Buffers“ drei Gründe haben. Erstens: Viele Vergleiche sind unfair. Zweitens: Die Ergebnisse hängen unter anderem von Struktur und Art der Daten ab, weshalb sie nicht immer gleichermaßen deutlich für Protocol Buffers sprechen. Drittens: Protocol Buffers erreicht einen unbestreitbaren Vorteil durch Typisierung der Datenstrukturen.

Zum ersten Punkt: In manchen Tests wird das Datenvolumen einer gRPC-Übertragung gemessen, etwa mit einem Netzwerkmonitor, und dann mit einem REST-Dienst verglichen. Dabei habe ich mehrfach gesehen, dass der Dienst, der JSON ausgab, nicht richtig konfiguriert war, da ohne Kompression gearbeitet wurde. Normalerweise sind Protocol-Buffers-Inhalte komprimiert, und auch ein JSON-Server kann sehr einfach seine Inhalte mit gzip packen. Fairerweise sollte auf diese Weise verglichen werden, und dann sind die Ergebnisse gleich deutlich weniger beeindruckend.

Meine anderen beiden Punkte beziehen sich gleichermaßen auf die Tatsache, dass Protocol Buffers mit typisierten Daten arbeitet. In Schemadateien mit der Endung .proto legt der Programmierer fest, welche Datentypen bestimmte Felder der übertragenen Nachrichten haben und wie die Felder heißen. Diese Tatsache macht sich die Codierung der Daten später zunutze, da die Namen von Feldern nicht wiederholt werden müssen und bestimmte Datentypen effizienter dargestellt werden können als in JSON, wo alle Daten als Text repräsentiert werden. Wenn JSON komprimiert wird, sind auch in diesem Resultat weitgehend keine sich wiederholenden Zeichenketten mehr enthalten. In unkomprimiertem JSON nehmen die Feldnamen sonst gern einen großen Anteil der Daten ein, wenn sie nicht bereits optimiert – also verkürzt – worden sind.

Es bleibt also dabei, dass bestimmte Datentypen und ihre effiziente binäre Darstellung in Protocol Buffers einen Vorteil ausmachen. Von den übermittelten Daten hängt es ab, wie groß dieser Vorteil tatsächlich ist. Wenn die Daten anteilig große Mengen von langen Fließkommazahlen oder Datumswerten enthalten, können Protocol Buffers wesentlich effizienter sein. Wenn die Daten hingegen größere Mengen Text enthalten, schrumpft der Vorteil entsprechend. In jedem Fall, den ich getestet habe, hatten Protocol Buffers die Nase vorn. Allerdings ist der Gewinn oft nicht größer als etwa zehn Prozent, besonders für Payload-Größen von einigen KB, die für Webanwendungen typisch sind.

Einfach geht vor

Besonders interessant fand ich an meinen Ergebnissen, dass die angesprochenen Vorteile allein auf Typisierung zurückzuführen sind. Vermutlich ist das auch der Grund, warum Entwickler aus der Microsoft-Welt den Ideen von gRPC besonders aufgeschlossen gegenüberstehen, denn in diesem Bereich ist Typisierung mit Programmiersprachen wie C# oder TypeScript üblich, verbreitet und sehr beliebt. Wer hingegen etwa JavaScript oder eine andere dynamische Sprache programmiert, sieht Typisierung als einen zusätzlichen Aufwand an, wenn nicht sogar als ein konzeptionelles Problem, da die Umstellung dynamischer Daten zur Übertragung notwendig ist und eventuell wiederum zu Performancenachteilen führt.

Abgesehen von technischen Aspekten bin ich persönlich auch nicht von der großen allgemeinen Bedeutsamkeit eines Effizienzvorteils von um die zehn Prozent überzeugt. Ich arbeite seit mehr als 20 Jahren mit verschiedenen Technologien für RPC (Remote Procedure Calls), und ich habe viele unterschiedliche Codierungsformate kommen und gehen sehen. Spätestens seit dem Hype um XML und der weiteren Entwicklung in Richtung JSON war für mich deutlich erkennbar, dass die Einfachheit von Übertragungsformaten Vorrang vor deren Effizienz hat. Binäre Alternativen für besondere Einsatzfälle gab es schon immer, und JSON oder XML wurden niemals verwendet, weil sie besonders kleine Datenpakete erzeugen konnten. Bitte verstehen Sie mich nicht falsch – gRPC ist eine gute Lösung für manches Problem. Aber diese Lösung kommt nicht umsonst, und in vielen Anwendungen werden Sie vergeblich nach einem passenden Problem suchen.

 

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -