Android-App für OTP Zwei-Faktor Authentifizierung: Tokens-TOTP

letzte Änderung: 04.08.2018

english version see here

Motivation

Da immer mehr Onlinedienste die sogenannte "OTP (One-time password) Zwei-Faktor Authentifizierung" unterstützen, sah ich mich nach einer App um, mit der ich meine Tokens für meine Accounts verwalten konnte. Manche Apps verfügen über eine (praktische ?) Online-Backup Funktion, bei der man seine Keys am besten gleich zusammen mit der E-Mail-Adresse hinterlegt, die man bei seinen zu schützenden Accounts angibt. Für mich ist das so, als gäbe der User den Zweitschlüssel seiner Wohnung mitsamt seiner Adresse bei jemand Unbekanntem ab und fährt dann drei Wochen in den Urlaub. Wieder andere Apps besitzen eine solche Backup-Funktion nicht, d. h. ist das Handy weg, müssen die Backup-Codes bemüht werden. Zum einen sollte für mich als Nutzer aber die Möglichkeit bestehen, ein Backup der Codes zu besitzen, ohne diese jemand Unbekanntem geben zu müssen, zum anderen sollten die Codes nicht im Klartext auf dem Handy, bzw. als exportierter Klartext auf dem Computer liegen. Zumindest ein Passwortschutz sollte sicherstellen, dass nur ich diese Tokens abrufen kann.

Ich entschloss mich also dazu, meine eigene Android-App zu schreiben, die meine Tokens möglichst sicher verwaltet und sie vor allem nicht per Cloud-Dienst sichert.

Download

** Wichtig: Ich übernehme keinerlei Garantie oder Gewähr, dass diese App stets fehlerfrei funktioniert und schließe jegliche Haftung für Schäden, die bei Gebrauch dieser App entstehen könnten, aus!**

Meine App war mal auf GitHub zu finden, ich habe das Repo dort allerdings gelöscht. In Zukunft werde ich die App nur noch auf meinem Server bereitstellen: Tokens-App (Warnung: Seite benutzt Cookies.)

tokens-04.apk
DownloadSize: 13.6M

MD5: 2f72a59f8d7679bd93f0a54c512b315f

------------------EXKURS------------------------

Zur Funktion der (Google) OTP Zwei-Faktor Tokens

Grundlage des TOTP(Time-Based One-Time Password Algorithm) ist der von der IETF verabschiedete RFC6238-Standard [1], sowie dessen Grundlage RFC4226 [2].

Voraussetzung für diesen Algorithmus ist, dass sowohl der "Prüfer", als auch der Nutzer die korrekte UNIX Zeit (also die Sekunden, die seit dem 1.1.1970 um Mitternacht vergangen sind), kennen. Im Anschluss werden diese vergangenen Sekunden in Intervalle X geteilt. Falls ein Offset T0 von dem UNIX "Nullpunkt" am 1.1.1970 gewünscht ist, so ist dieser von der aktuellen Zeit abzuziehen [1]:

$$ T = \frac{t_{UNIX-now} - T_0}{T_X}$$

Dieser Wert T wird mit dem (Master)-Key HMAC-SHA-1 verschlüsselt, sodass ein 160 Bit langes Chiffrat entsteht. Um dieses auf ein vom Nutzer leicht handhabbares Format zu reduzieren, findet ein "dynamisches Abschneiden" ("Dynamic Truncation" [2]) statt. Dieser abgeschnittene und gehashte Wert ergibt Modulo 10^{Anzahl Digits} den gesuchten einmal benutzbaren Token.

Der RFC Norm folgend sieht die Generierung eines solchen Tokens in Python implementiert in etwa so aus:

def get_token(offset, tx, key):
        T         = math.floor((time.time() - offset) // tx)
        hmac_hash = hmac.new(key, msg=struct.pack('>Q', T), digestmod='sha1').hexdigest()
        offset    = int(hmac_hash, 16) & 0xF
        rest      = int(hmac_hash[offset*2:(offset+4)*2], 16)
        token     = rest & 0x7FFFFFFF
        return token % 10**self._N

self._key ist dabei der Base32-dekodierte (Master)-Key, die "Dynamic Truncation" findet durch die [offset*2:(offset+4)*2] Verkürzung von hmac_hash statt. In der "Google" Variante des OTP wird zudem die Länge des Master-Keys auf 80 Bit reduziert, die Intervallzeit ist auf 30 Sekunden festgesetzt und ein Offset von der UNIX-Zeit ist ebenfalls nicht vorgesehen. [3]

In Python ist es (wie so vieles) also kein Hexenwerk, einen solchen Tokengenerator zu schreiben.

------------------EXKURS------------------------

Implementierung eines konfigurierbaren TOTP Generators als Android-App

Die Darstellung der Tokens

Um die Generierung der OTPs nachzuvollziehen, hatte ich mir zunächst in Python einen OTP Generator implementiert, bei dem sämtliche Parameter inklusive Offset-Zeit und Länge des OTP einstellbar sind. Dieser benutzt die im Exkurs gezeigte Implementierung zur Tokenberechnung.

Die Android-App "Tokens" selbst ist in Qt C++ und QML geschrieben. Der Tokengenerator TOTPGenerator unterscheidet sich geringfügig von der Python Implementierung, da einige Funktionalitäten erst mitgeliefert werden mussten. Glücklicherweise stellt Qt selbst den HMAC-SHA-1 Algorithmus schon zur Verfügung.

QR Codes scannen

Oftmals werden die Masterkeys für die Tokens mittels eines QR-Codes bereitgestellt. Gerade diese Funktionalität ist wichtig, da man sich den Inhalt des QR-Codes oftmals gar nicht mehr anzeigen lassen kann.

Um ein solches Einscannen zu ermöglichen, wurde QZXing benutzt. Ich habe diese Library allerdings gesondert kompilieren und die Library später dem Linker meines eigenen Projektes nennen müssen. Ein direktes Einbinden als Subprojekt führte dazu, dass die nötigen QML Typen nicht ordnungsgemäß registriert und benutzt werden konnten. Bei Gelegenheit muss ich das mit sowohl einer neueren Version von Qt, als auch mit der neuesten Version der Library nochmals versuchen.

Zukunftspläne

Verschlüsselung

Mit der Verschlüsselung bin ich noch nicht ganz zufrieden. Aktuell wird das eingegebene Passwort mehrmals gehasht und dann als Schlüssel für das AES-verschlüsselte Keyfile benutzt. Was ich noch gerne hätte ist ein Integritätsschutz, sowie eine bessere "Vorverarbeitung" des Passworts, bevor es als Schlüssel benutzt wird (evtl. die Zahl der Hashvorgänge erhöhen). Eine PGP-basierte Verschlüsselung wäre auch denkbar.

Für ein sicheres Passwort muss der Nutzer natürlich selbst sorgen, deshalb wurde auf eine PIN, oder Musterentsperrung verzichtet. Die letzten beiden Methoden fußen unter anderem darauf, dass niemand sonst das verschlüsselte Keyfile lesen kann. Bei einer vierstelligen PIN könnte die Verschlüsselung genauso gut weggelassen werden, wenn ein Angreifer unendlich viele Versuche unternehmen kann, die Datei zu entschlüsseln.

Des Weiteren:

Fragen, Anregungen an: afk @ daichronos.net

« Übersicht
Datenschutzerklärung Impressum