In­ter­net­nut­zer müssen re­gel­mä­ßig Pass­wör­ter eingeben – egal ob bei der Anmeldung auf einer Social-Media-Plattform, beim On­line­shop­ping oder dem Banking im Internet. Pass­wör­ter sichern sensible Daten vor dem Zugriff anderer. Dabei ver­nach­läs­si­gen viele Nutzer al­ler­dings die nötige Sorgfalt: Einfache Pass­wör­ter lassen sich von Profis innerhalb von Sekunden knacken. Andere bewahren ihre ei­gent­lich guten Kenn­wör­ter falsch auf und bieten Kri­mi­nel­len auf diese Weise ein Ein­falls­tor. Nicht zu verachten sind zudem Schwach­stel­len bei den Diensten, bei denen man sich als Nutzer anmeldet. Werden die Pass­wör­ter dort nicht or­dent­lich gesichert, sind mitunter die Daten von tausenden Nutzern gefährdet.

Eine Mög­lich­keit, das Risiko zu ver­klei­nern, ist die Zwei-Faktor-Au­then­ti­fi­zie­rung bzw. Multi-Faktor-Au­then­ti­fi­zie­rung. Statt nur ein Passwort zu verwenden, muss min­des­tens ein weiteres Au­then­ti­fi­ka­ti­ons­merk­mal angegeben werden. Dieses bekommen Nutzer der Technik entweder per Smart­phone oder über einen Hardware-Token. Die zu­sätz­li­chen Faktoren haben meist gemeinsam, dass sie einmalig erstellt werden und nur für kurze Zeit gültig sind – es wird ein so­ge­nann­tes Time-based One-time Password generiert. Wir erklären, wie das funk­tio­niert.

Wofür braucht man TOTP?

Ge­wöhn­li­che Pass­wör­ter – wie sicher sie auch immer gewählt werden – haben einen Nachteil: Kennt auch jemand anderes die Zei­chen­fol­ge, ist die Si­cher­heit nicht mehr gegeben. Eine Lösung wäre, das Kennwort häufig zu wechseln, aber selbst die vor­bild­lichs­ten Nutzer machen dies nicht stündlich. Die Lösung ist TOTP: ein Passwort, dass nur für einen kurzen Zeitraum gültig ist und dann wieder verfällt. Die Internet En­gi­nee­ring Task Force (IETF) hat den Time-based One-time Password Algorithm 2011 im RFC 6238 ver­öf­fent­licht, um für mehr Si­cher­heit im Internet zu sorgen.

Besonders beliebt sind solche Ein­mal­pass­wör­ter im Zuge von Multi-Faktor-Au­then­ti­fi­zie­rung. Dabei verwenden Nutzer zur Anmeldung bei einem Webdienst zunächst ihr per­sön­li­ches, fest­ste­hen­des Kennwort; zu­sätz­lich wird ein zeit­be­grenz­tes Passwort zu genau diesem An­mel­de­vor­gang erzeugt. Der Nutzer erhält dies z. B. per App oder durch ein extra dafür vor­ge­se­he­nes Gerät (Token).

Ist das Passwort einmal genutzt oder wird in einem be­stimm­ten Zeitraum nicht genutzt, verfällt es. Kri­mi­nel­len wird es somit sehr schwer gemacht, den zweiten Faktor zu bekommen. Auch wenn sie das ei­gent­li­che Passwort kennen, haben sie nur wenige Mög­lich­kei­ten, auch das TOTP zu erlangen, bzw. keine Zeit, dieses zu knacken.

Wie funk­tio­niert der Time-based One-time Password Algorithm?

Basis des TOTP ist eine Hash­funk­ti­on, also ein kryp­to­gra­fi­sches Verfahren. Man bildet aus einem geheimen Passwort und einem Zeit­stem­pel eine ver­schlüs­sel­te Zei­chen­fol­ge. Das Passwort ist sowohl dem Nutzer als auch dem Server bekannt. Die Zeit­an­ga­be findet in Unixzeit statt.

Fakt

Unixzeit ist ein Wert, der die Sekunden seit dem 1. Januar 1970 angibt.

TOTP ist ei­gent­lich eine Wei­ter­ent­wick­lung von HOTP, was für „HMAC-based One-time Password“ steht. Auch TOTP basiert auf dem HMAC-Verfahren – die Hash-Operation im Hin­ter­grund. Sowohl das Gerät des Nutzers als auch der Server erstellen aus dem geheimen Passwort in Kom­bi­na­ti­on mit einem Zähler einen Hashwert. Beide Werte sind identisch, weshalb die Au­then­ti­fi­zie­rung funk­tio­niert.

Die Hash­funk­ti­on an sich ist nicht fest­ge­legt; in der Praxis greift man z. B. zu SHA-1 (so auch der Google Au­then­ti­ca­tor), das einen Hashwert mit einer Länge von 160 Bit erzeugt. Der Ein­fach­heit halber wird dieser Wert noch über eine Kom­pres­si­ons­funk­ti­on gekürzt. Am Ende hat man bei­spiels­wei­se eine sechs­stel­li­ge Zahl, die Nutzer dann leicht bei der Anmeldung im Webdienst eingeben können.

Hinweis

Das geheime Passwort ist bei einem Token im Gerät verankert. Der Nutzer selbst weiß es daher oftmals nicht. Falls dies anders ist, sollte der SecretKey sicher auf­be­wahrt werden, bes­ten­falls offline und eventuell sogar aus­ge­druckt und an einem ge­si­cher­ten Ort gelagert. Verliert man dieses Passwort, ist die Anmeldung beim Dienst nicht mehr möglich.

HOTP setzt auf einen Zähler als zweiten Be­stand­teil der Funktion. Diesen teilen Server und Nutzer mit­ein­an­der. Das Problem dabei ist, dass das ge­ne­rier­te Passwort so lange gültig ist, bis es verwendet wurde. TOTP schränkt dies ein: Nur innerhalb eines fest­ge­leg­ten Zeit­rah­mens kann der so erstellte Code ein­ge­setzt werden. Wie funk­tio­niert das?

Für den Time-based-One-time-Al­go­rith­mus sind drei Formeln von Bedeutung:

TOTP = HOTP(SecretKey,Cur­rent­Ti­me)

Diese einfache Formel legt nur fest, dass TOTP ein HOTP-Verfahren mit den beiden Pa­ra­me­tern SecretKey und Cur­rent­Ti­me ist:

  • SecretKey: zufällig erzeugtes Passwort, das sowohl Server als auch Client bekannt ist
  • Cur­rent­Ti­me: aktueller Zeitpunkt in Unixzeit

Die Zeit­an­ga­be ändert sich al­ler­dings se­künd­lich. Das ist nicht genug Zeit, um den Code in die Anwendung zu über­tra­gen. Eine Sekunde später wäre das TOTP schon nicht mehr gültig: Der Server hat bereits einen neuen Hashwert erstellt. Deshalb greift man auf eine weitere Formel zurück:

Cur­rent­Ti­me = flo­or­unixt­i­me(now) – unixtime(T0/T1)

Der Parameter Cur­rent­Ti­me wird also definiert:

  • unixtime(now): aktueller Zeitpunkt in Unixzeit
  • unixtime(T0): Unixzeit zum Zeitpunkt T0, ab dem gezählt wird – also in den meisten Fällen der 1.1.1970 um Mit­ter­nacht (= 0)
  • T1: Intervall, in dem das TOTP gültig sein soll – üb­li­cher­wei­se 30 Sekunden
  • floor: Ab­run­dungs­funk­ti­on, um den er­rech­ne­ten Wert auf eine ganze Zahl zu runden
Hinweis

Es kann theo­re­tisch auch ein anderer Wert als 0 für T0 gewählt werden. Wichtig ist nur, dass Client und Server den gleichen Wert wählen.

Division und Abrundung erzeugen den Effekt, dass sich das Resultat in­ter­vall­mä­ßig ändert.

An­schlie­ßend wird der erzeugte Hashwert noch be­nut­zer­freund­lich verkürzt:

Result = TOTPmod10d

Mit der Modulo-Rechnung erzeugt man eine Prüfsumme:

  • mod 10: Modulo bei Divisor 10
  • d: Anzahl der Stellen, die das TOTP haben soll

Man po­ten­ziert also die Basis 10 zu den Stellen, die der Code haben soll, teilt das TOTP durch diesen Wert und ex­tra­hiert dann den Rest.

TOTP-Be­rech­nung an einem Beispiel

Nehmen wir an, man möchte ein TOTP erzeugen, das eine Gül­tig­keit von 30 Sekunden hat. Damit können wir nun schon die Cur­rent­Ti­me berechnen und erkennen so auch, wie die Gül­tig­keits­dau­er ga­ran­tiert wird. Als unixtime(now) nehmen wir 1548322860 an, den 24.01.2019 um 10:41 Uhr. Teilen wir diesen Wert durch 30, erhalten wir genau 51610762. Da es sich bereits um eine ganze Zahl handelt, gibt auch die Abrundung dieses Ergebnis aus. Setzen wir die aktuelle Zeit nun 15 Sekunden später an (also 1548322875), erhalten wir nach der Division das Ergebnis 51610762,5. Auch dies ist ab­ge­run­det 51610762. Die Cur­rent­Ti­me bleibt also gleich. In der folgenden Tabelle kann man sehen, dass erst nach 30 Sekunden ein anderer Wert entsteht:

unixtime(now) unixtime(now)/30 floor(unixtime(now)/30)
1548322857 51610761,9000 51610761
1548322858 51610761,9333 51610761
1548322859 51610761,9667 51610761
1548322860 51610762,0000 51610762
1548322861 51610762,0333 51610762
1548322862 51610762,0667 51610762
1548322863 51610762,1000 51610762
1548322864 51610762,1333 51610762
1548322865 51610762,1667 51610762
1548322866 51610762,2000 51610762
1548322867 51610762,2333 51610762
1548322868 51610762,2667 51610762
1548322869 51610762,3000 51610762
1548322870 51610762,3333 51610762
1548322871 51610762,3667 51610762
1548322872 51610762,4000 51610762
1548322873 51610762,4333 51610762
1548322874 51610762,4667 51610762
1548322875 51610762,5000 51610762
1548322876 51610762,5333 51610762
1548322877 51610762,5667 51610762
1548322878 51610762,6000 51610762
1548322879 51610762,6333 51610762
1548322880 51610762,6667 51610762
1548322881 51610762,7000 51610762
1548322882 51610762,7333 51610762
1548322883 51610762,7667 51610762
1548322884 51610762,8000 51610762
1548322885 51610762,8333 51610762
1548322886 51610762,8667 51610762
1548322887 51610762,9000 51610762
1548322888 51610762,9333 51610762
1548322889 51610762,9667 51610762
1548322890 51610763,0000 51610763
1548322891 51610763,0333 51610763

Cur­rent­Ti­me steht damit fest (51610762). Den SecretKey erzeugen wir durch einen Passwort-Generator: >cHSB_UQ#O5m;~b

HMAC mit SHA-1 formt aus Passwort und Uhrzeit einen Hashwert (in he­xa­de­zi­ma­ler Schreib­wei­se): c0 62 37 94 dd 37 7a 3a f0 91 22 08 1f 21 6f 9b 17 4b 17 45. Dieser 160 Bit bzw. 20 Byte lange Wert wird durch so­ge­nann­te Dynamic Trun­ca­ti­on nun auf 31 Bit verkürzt. Hierfür werden zunächst die letzten 4 Bit be­trach­tet, also die Zahl 0x5, die auch in dezimaler Schreib­wei­se als 5 ge­schrie­ben wird. Dies ent­spricht dem Offset-Wert der Dynamic Trun­ca­ti­on und bedeutet, dass man vom Byte mit dem Index 5 ausgehend (von links aus beginnend mit 0 zählen), vier Bytes ex­tra­hiert: 0x377a3af0. In diesem Fall beginnt der Wert bereits mit einem Bit, das auf 0 steht. Sollte dies nicht der Fall sein, ändert man ent­spre­chend. Der 31 Bit lange Wert lautet hier also auch: 0x377a3af0 bzw. 930757360.

Um diese neun­stel­li­ge Zif­fern­fol­ge nun auf sechs Stellen zu re­du­zie­ren, wendet man eine Modulo-Operation an und füllt bei Bedarf links mit Nullen auf: 930757360 mod (106) = 757360. Dies ist nun das TOTP, das 30 Sekunden lang gültig ist. In Kom­bi­na­ti­on mit einem weiteren Faktor hat man so ein ziemlich sicheres An­mel­de­ver­fah­ren.

Zum Hauptmenü