Category: arduino

16 LEDs mit einem einzigen Output-Pin ansprechen

31.05.2013 yahe arduino hardware legacy

Endlich sind die ersten Vorbereitungen für das Auslesen einer echten Computertastatur abgeschlossen. Das Problem, das ich nun gelöst habe, ist, dass der Controller und die Tastenmatrix solch einer Tastatur über sehr viele Anschlüsse verfügen, sogar über so viele, dass sie den Rahmen dessen sprengen, was der Arduino zur Verfügung stellt. Um trotzdem alles anschließen zu können, habe ich mir eine Kleinigkeit überlegt. Mit Hilfe eines Demultiplexers bin ich in der Lage, den Input eines Pins auf mehrere Ausgänge zu verteilen. Bei einem NXP 74HCT4051 kann ich mit Hilfe von 3 Steuerleitungen ganze 8 LEDs ansprechen. Die Anzahl der Leitungen hat sich also schon mal um 5 reduziert.

Das war mir jedoch noch nicht genug. Deshalb habe ich zusätzlich einen Synchronzähler verwendet. Solch ein Binärzähler wie der NXP 74HCT193 hat im Grunde einen Eingang, über den man ihm einen Takt geben kann. Bei jedem Takt zählt er einen internen Counter um eins höher oder niedriger. Die aktuelle Zahl gibt er binär aus, im Falle des 74HCT193 mit vier Stellen. Die niedrigsten drei Bit kann man nun verwenden, um den Demultiplexer zu steuern. Doch ein Bit des Binärzählers bleibt noch übrig. Dank dieses höchsten Bits kann man nun einen zweiten Demultiplexer nehmen und mit dem Bit entweder den ersten Demultiplexer aktivieren oder den zweiten. Auf diese Weise kann man mit einem einzigen Vier-Bit-Zähler und zwei Demultiplexern dank nur 1 Taktleitung ganze 16 LEDs ansteuern.

16 LEDs dank ein paar ICs

Das Anschalten/Abschalten der ersten Demultiplexers erreichen wir, indem wir den Enable-Input (E) des Demultiplexers direkt mit dem höchsten Bit des Zählers verbinden. Ist das Bit auf 0 gesetzt, ist der Demultiplexer aktiv, ist das Bit auf 1 gesetzt, ist der Demultiplexer deaktiviert. Zum Anschalten/Abschalten des zweiten Multiplexers müssen wir jedoch ein wenig tricksen. Wir verwenden ein NXP 74HCT02 NOR-Gatter (oder wahlweise ein NXP 74HCT00 NAND-Gatter). Einen Input des NOR-Gatters verbinden mir Ground, den anderen Input hingegen mit dem höchsten Bit des Zählers. Erst den Output-Pin des NOT-Gatters verbinden wir mit dem Enable-Input (E) des zweiten Demultiplexers. Ist das Bit auf 0 gesetzt, liefert das NOR-Gatter den Output 1 und der zweite Multiplexer ist deaktiviert, ist das Bit auf 1 gesetzt, liefert das NOR-Gatter den Output 0 und der zweite Multiplexer ist aktiv.

Alle ICs in einer Reihe

Bei Vine habe ich mal ein ultrakurzes Video hochgeladen, bei dem einfach durch die einzelnen LEDs durchgeschaltet wird.

Als nächstes heißt es nun, Anschlüsse an die Tastaturmatrix und an den Controller zu basteln. Den notwendigen Kleber habe ich inzwischen erhalten. Ich werde zwei verschiedene Leitkleber ausprobieren, zum einen Polytec PU 1000 aus Deutschland (Kostenpunkt ca. 70€ inkl. MwSt und Versand) und zum anderen Wire Glue aus den USA (Kostenpunkt ca. 15€ inkl. MwSt und Versand).


calc.pw: Der Open-Source Hardware-Passwortberechner

22.05.2013 yahe arduino calcpw code hardware legacy security

Es ist vollbracht! In den letzten Wochen und Monaten habe ich einige Zeit mit der Arduino-Plattform verbracht und mich Stück für Stück in unterschiedliche Themenbereiche eingearbeitet. Ziel war es, calc.pw zu entwickeln.

calc.pw Aufbauschema

calc.pw ist ein Passwortberechner. Man gibt ein Masterpasswort ein und kann mit diesem und einer dienstabhängigen Information ein Passwort für diesen Dienst erzeugen. Das gleiche Masterpasswort kombiniert mit der gleichen dienstabhängigen Information führt wieder zum gleichen Passwort. Damit entfällt die schwierige Aufgabe, sich kryptische Passworte merken zu müssen.

calc.pw Verwendung calc.pw Verwendung calc.pw Verwendung calc.pw Verwendung

Im Gegensatz zu Passworttresoren bietet calc.pw den Vorteil, dass das Masterpasswort ausschließlich in einer externen Hardware vorgehalten wird und damit nicht durch Schadsoftware auf dem PC abgefangen werden kann. Zudem besteht nicht das Risiko, sämtliche Passwörter zu verlieren, weil die Datenbank mit den Passwörtern abhanden kommt. Das einzige, was man sich merken muss, ist das Masterpasswort. Die dienstabhängigen Informationen kann man einfach direkt aus dem Namen des jeweiligen Dienstes ableiten.

Um die Verwendung von calc.pw möglichst einfach zu machen, wird es zwischen Tastatur und Computer gesteckt. Während der normalen Verwendung leitet calc.pw die Tastenanschläge an den Computer durch. Erst durch Drücken der Tastenkombination STRG+ESC wechselt man in den Modus zur Passwortberechnung. Nach Eingabe der Information und Drücken von ENTER oder STRG+ESC wird das Passwort erzeugt und man gelangt automatisch wieder in den Passthrough-Modus, in dem die Tastenanschläge durchgeleitet werden.

calc.pw Passthrough-Modus


Arduino: Spaß mit Sensoren

08.05.2013 yahe arduino code hardware legacy

Nachdem ich ganz am Anfang meiner Arduino-Reise mal ein paar lustige Experimente gemacht hatte, habe ich mich in letzter Zeit sehr auf mein ernstes Projekt konzentriert. Das habe ich heute mal ein wenig aufgelockert. Im Zuge meines Besuches bei der AfRA Berlin hatten wir diskutiert, wie man die Anwesenheit von Personen in einem Raum ermitteln könne. Hierbei sind wir einige theoretische Möglichkeiten durchgegangen. Die Idee war, mit einem Bewegungssensor zu ermitteln, ob jemand im Raum ist und mit einem Ultraschallsensor zu messen, wo er sich ungefähr befindet. Diese wollte ich nun einmal gerne testen.

Arduino-Alarmanlage und -Ultraschall-Theremin

Ausgestattet mit besagtem Bewegungsmelder, Ultraschallsensor und einem Piezoelement war ich in der Lage, eine relativ simple Alarmanlage zu basteln. Diese prüft per Bewegungssensor, ob sich etwas in der Nähe bewegt und misst anschließend mit dem Ultraschallsensor, ob sich die Entfernung des Gegenstandes geändert hat. Falls ja, wird über das Piezo-Element ein Alarmton ausgegeben.

Der ein oder andere wird sich evtl. noch an das Lichttheremin erinnern. Dieses verwendete einen Photoresistor und ein Piezoelement, um anhand der Helligkeit einen Ton wiederzugeben. Dieses konnte man mit der Hand steuern. Je näher sie am Photoresistor war, umso dunkler wurde es und desto tiefer wurde der Ton. Wurde die Hand weggenommen, wurde es heller und der Ton somit höher. Hierfür benötigte man jedoch eine eine möglichst gleichmäßige Lichtquelle von oben. Dank des Ultraschallsensors können wir das Theremin nochmal ohne Lichtquelle als Ultraschall-Theremin UltraTheremine implementieren.


Arduino und x86: Crosskompilation trotz PROGMEM

07.05.2013 yahe arduino code hardware legacy

Bei meinem derzeitigen Projekt lege ich viel Wert darauf, dass die eigentliche Codebasis nicht nur auf dem Arduino, sondern auch auf normalen PCs mit x86- und x64-Architektur läuft. Bisher war das relativ einfach, da ich Plattformspezifika vermeide. Dieses Mal war das jedoch nicht möglich und eine Zwischenschicht musste her.

Was genau ist PROGMEM?

Ein großes Problem der Arduino-Plattform ist ihr begrenzter Hauptspeicher von 2kb. Dinge wie längere statische Strings werden normalerweise als Array definiert. Diese Arrays werden beim Starten des Programms in den Hauptspeicher geladen und verbrauchen dort Platz. Um diese unnötige Platzverschwendung zu umgehen, gibt es bei AVR-Plattformen PROGMEM. Statische Variablen, die damit markiert werden, werden nicht in den Haupt-, sondern in den Programmspeicher gepackt und von dort aus gelesen. Der Programmspeicher bietet immerhin satte 32kb Platz. Über spezielle Funktionen kann die Variable dann wieder ausgegeben werden.

Und wo ist jetzt das Problem?

Wie schon angesprochen, möchte ich meinen Code sowohl auf dem Arduino als auch auf dem PC verwenden. Dieser unterstützt PROGMEM jedoch nicht. Daher muss eine Möglichkeit gefunden werden, um Code, der das Schlagwort "PROGMEM" sowie die speziellen PROGMEM-Funktionsaufrufe enthält, trotzdem kompilieren zu können.

Und wie sieht die Lösung aus?

Um die PROGMEM-Funktionalität nutzen zu können, benötigt man sowohl die PROGMEM-Direktive als auch die speziellen Funktionen zum Auslesen des Speichers. Diese stehen auf dem PC natürlich nicht zur Verfügung. Aus diesem Grund habe ich mir einen kleinen Wrapper geschrieben. Dieser definiert "pm_*(x,y)" Funktionen, die anstelle der normalen Pgmspace-Funktionen verwendet werden sollen. Zudem werden die für PROGMEM verwendeten Datentypen definiert. Wenn man nun folgenden Code in eine Headerdatei packt, diese neue Headerdatei anstelle von "<avr/pgmspace.h>" inkludiert und die "pm_*(x,y)"-Funktionen nutzt, dann funktioniert der Code plattformübergreifend.

Wie sieht das in der Praxis aus?

Ich habe eine kleine Bibliothek namens Progmemuino geschrieben, die man einfach in sein Programm einbinden kann. Schon hat man die notwendige Abstraktionsschicht, um den speziell angepassten Arduino-Code auch plattformübergreifend auf dem PC nutzen zu können.


Kryptographie für Arduino

17.04.2013 yahe arduino code hardware legacy security

Nachdem ich letztens meinen kleinen Arduino-Speichermanager fertig gestellt habe, geht es nun darum, etwas produktives damit anzufangen. In meinem Fall lag das erste Hauptaugenmerk auf kryptographischen Algorithmen, sprich das Verschlüsseln und Hashen. Dabei muss ich natürlich immer den Speicher im Auge behalten. Herausgekommen ist die Bibliothek Cryptuino.

Um mit etwas einfacherem zu beginnen, habe ich zuerst einmal eine Base64-Encodierung, da mit dieser bereits ein bisschen mehr Erfahrung habe. Normalerweise kann ein Computer nur eine begrenzte Menge an Zeichen, die sogenannten druckbaren Zeichen, ordentlich darstellen. Im Fall vom ASCII-Standard, den so gut wie alle Computer in abgewandelter Form beherrschen, sagt Wikipedia folgendes:

Die Zeichenkodierung definiert 128 Zeichen, bestehend aus 33 nicht druckbaren sowie 95 druckbaren.

Das Problem beim Hashen und Verschlüsseln ist jedoch, dass die Ausgabe im gesamten Bytebereich von 0 bis 255 verstreut ist. Computer können das in der Regel nicht ordentlich darstellen. Das Ergebnis sind Fehldarstellungen. Aus diesem Grund sorgt Base64 dafür, dass der nicht-druckbare Text in druckbaren Text umgewandelt wird. Statt aller 256 Werte, die mit einem Byte dargestellt werden können, werden nur 64 Zeichen verwendet. Damit wird das Ergebnis (um 33%) länger, aber dafür lesbar.

CHUNK encode_base64(CHUNK input);
CHUNK decode_base64(CHUNK input);

Die Anwendung ist relativ einfach. Mit "encode_base64()" enthält man den Base64-encodierten Text und mit "decode_base64()" erhält man wieder den Ursprungstext. Base64 wird übrigens zum Beispiel verwendet, um die Anhänge in E-Mails zu encodieren. Da es sich bei den Protokollen IMAP, POP3 und SMTP um Textprotokolle handelt, kann man dort nicht einfach irgendwelche Binärdaten hineinkippen. Aus diesem Grund enstand MIME, das u.a. Base64 als Datenencodierung vorsieht.

Gut, als nächstes brauchte ich einen Hashalgorithmus. Ich habe lange überlegt, welchen ich genau benutzen soll, habe mich dann aber schlussendlich für SHA-1 entschieden. Es gibt mit der SHA-2-Familie zwar inzwischen eine bessere Alternative, diese benötigen jedoch auch wesentlich mehr Speicher. Bei so einem Hashalgorithmus geht es darum, eine Eingabe mit belieber Länge in eine Ausgabe mit fixer Länge zu überführen. Dabei legt man besonderen Wert darauf, dass diese Überführung bestimmte Kriterien erfüllt. Eine der Anforderungen ist, dass man aus dem Ergebnis der Funktion keinen Rückschluss darauf ziehen kann, was die Eingabe oder Teile davon gewesen ist. Es soll sehr schwer sein, zwei Eingaben zu finden, die zur gleichen Ausgabe führen, die sogenannte Kollisionsresistenz. Und bei der kleinsten Änderung der Eingabe soll sich diese Änderung sehr deutlich in der Ausgabe widerspiegeln, der sogenannte Avalance-Effekt.

CHUNK hash_sha1(CHUNK input);
CHUNK hmac_sha1(CHUNK input, CHUNK password);

Die Verwendung der Hashfunktion ist recht einfach. Man übergibt der Funktion "hash_sha1()" seinen Input und erhält als Output die Hashsumme, die bei SHA-1 immer genau 20 Zeichen lang ist. Darüber hinaus habe ich mit "hmac_sha1()" noch den zugehörigen HMAC-Algorithmus implementiert. Bei einem MAC (Message Authentication Code) handelt es sich um eine Möglichkeit, die Korrektheit einer Nachricht zu überprüfen. Ein HMAC (Hash-based Message Authentication Code) macht dies, indem die Nachricht und ein geheimer Schlüssel genommen und beides zusammen gehasht wird. Jemand, der die Nachricht erhält und den geheimen Schlüssel kennt, kann so überprüfen, ob der HMAC zur erhaltenen Nachricht passt.

Auf Basis von HMACs werden zum Beispiel sehr gerne Challenge-Response-Verfahren realisiert. Dabei wird bei der Passwortabfrage nicht einfach das Passwort an den Server geschickt, sondern der Server schickt eine Challenge (eine zufällige Zahl). Derjenige, der sich einloggen will, erzeugt nun einen HMAC aus dieser zufälligen Zahl und seinem Passwort und schickt dem Server das Ergebnis zu. Da auch der Server das Passwort kennt, kann er aus der Zufallszahl und dem Passwort ebenfalls den HMAC bilden. Stimmen sein Ergebnis und das zugesandte Ergebnis des Nutzers überein, ist sichergestellt, dass dieser das richtige Passwort kennt, ohne, dass das eigentliche Passwort zwischen beiden Parteien übertragen werden musste.

Bleibt noch das Thema Verschlüsselung übrig. Hier habe ich mich nach langem hin und her für ARC4 (Alleged RC4) entschieden. Dabei handelt es sich um einen eigentlich proprietären Algorithmus, dessen Struktur jedoch Mitte der 90er Jahre im Usenet veröffentlicht wurde und seitdem unter dem Namen "ARC4" oder "ARCFOUR" weite Verbreitung gefunden hat. Dieser Algorithmus hat einen Nachteil, den ich gleich näher erläutere.

CHUNK encrypt_arc4(CHUNK input, CHUNK password);
CHUNK decrypt_arc4(CHUNK input, CHUNK password);

Auch hier sollte die Verwendung klar sein. "encrypt_arc4()" übergibt man seine Nachricht und sein Passwort und erhält anschließend seine verschlüsselte Nachricht. "decrypt_arc4()" überreicht man die verschlüsselte Nachricht und dasselbe Passwort und erhält wieder den Klartext. Wie jedoch schon gesagt, hat ARC4 ein Problem, das durch seine einfache Struktur zu erklären ist. Als Stromchiffre ist ARC4 im Grunde ein Pseudo-Zufallsgenerator, der anhand des Passworts einen endlosen Strom an "zufälligen" Bytes erzeugt. Diese Bytes werden mit den Bytes der zu verschlüsselnden Nachricht geXORt. Das Verfahren selbst ist nicht unsicher, weist jedoch eine Besonderheit auf: Verschlüsselt man zwei Nachrichten mit demselben Passwort und XORt die beiden verschlüsselten Nachrichten, so erhält man als Ergebnis das XOR-Ergebnis der beiden unverschlüsselten Nachrichten:

c1_i = m1_i XOR k_i
c2_i = m2_i XOR k_i

c1_i XOR c2_i = (m1_i XOR k_i) XOR (m2_i XOR k_i)
              = m1_i XOR k_i XOR m2_i XOR k_i
              = (m1_i XOR m2_i) XOR (k_i XOR k_i)
              = (m1_i XOR m2_i) XOR 0
              = m1_i XOR m2_i

Wenn man nun also eine verschlüsselte Nachricht "c1_i = m1_i XOR k_i" und eine verschlüsselte Nachricht "c2_i = m2_i XOR k_i" abgefangenhat und diese beiden XORt, dann folgt daraus "c1_i XOR c2_i = m1_i XOR m2_i". Der Schlüsselstrom k_i kürzt sich also einfach raus und übrig bleiben die beiden Ursprungsnachrichten. Das ist erstmal eine unerfreuliche Information. Das positive ist, dass man dieses Problem relativ einfach umgehen kann, indem man dafür sorgt, dass ein einmal verwendetes Passwörter nie ein zweites Mal verwendet wird. Das geht zum Beispiel über einen sogenannten Nonce ("number used once"), also eine zufällige Zahl, die nur ein einziges Mal verwendet werden darf. Wenn ihr nun ARC4 nicht direkt mit eurem Passwort verwendet, sondern erst per "hmac_sha1(Nonce, Passwort)" das eigentliche Passwort für ARC4 ermittelt, seid ihr auf der sicheren Seite.

Kryptographie in Aktion Kryptographie in Aktion


Search

Links

RSS feed

Categories

administration (40)
arduino (12)
calcpw (2)
code (33)
hardware (16)
java (2)
legacy (113)
linux (27)
publicity (6)
review (2)
security (58)
thoughts (21)
windows (17)
wordpress (19)