
Ich verwende Google Authenticator derzeit für 2FA, beispielsweise zum Herstellen einer VPN-Verbindung usw. Ich wollte sehen, ob ich den sechsstelligen Code auf meiner OSX-Box abrufen kann, aber aus irgendeinem Grund oathtool
wird nie der gleiche Wert wie bei Authenticator zurückgegeben. Und der Authenticator-Code funktioniert, der oathtool
andere nicht.
Interessanterweise habe ich auch in einem iOS-Simulator versucht mithttps://github.com/mattrubin/Authenticatorauf demselben System und der von ihm erzeugte Code stimmt mit oathtool
Authenticator überein und nicht mit diesem.
Ich vermutete, dass dies vielleicht ein Problem mit der Zeitsynchronisierung ist, aber nachdem ich meine OSX-Zeit manuell synchronisiert habe, ist der Code derselbe. Ich frage mich, ob es im TOTP-Algorithmus vielleicht Standardparameter gibt, die nicht übereinstimmen, aber ich weiß nicht, welche das sein könnten.
Der oathtool
Befehl gibt ungefähr Folgendes aus
% oathtool --verbose --base32 --totp "$SECRET"
Hex secret: ...
Base32 secret: ...
Digits: 6
Window size: 0
Step size (seconds): 30
Start time: 1970-01-01 00:00:00 UTC (0)
Current time: 2016-10-20 22:27:22 UTC (1477002442)
Counter: 0x2EF3E06 (49233414)
(Beachten Sie, $SECRET
dass oben derselbe Wert angegeben ist, der zum Generieren des QR-Codes verwendet wurde, den Authenticator verwendet hat.)
Gibt es einen Grund, warum diese nicht übereinstimmen sollten?
Aktualisieren
Ich habe versucht, die Zeit um 30 Sekunden vor oder nach der Zeit meines Systems zu manipulieren, indem ich
oathtool --now "$(perl -e'use DateTime; print DateTime->now()->subtract(seconds=>30)->strftime( "%Y-%m-%d %H:%M:%S %Z" )')" -b --totp $SECRET -w 20|sort
Das obige Perl generiert Zeit im Format
2016-10-20 23:36:15 UTC
Ich habe auch jedes Mal 20 Zahlen ausgegeben, aber keine davon schien mit dem übereinzustimmen, was ich im Authenticator habe.
Antwort1
Da Sie durch die Suche nach „Google Authenticator Oathtool“ hierher gelangen und die Antwort der Einfachheit und Vollständigkeit halber teilweise in den Kommentaren zu finden ist …
oathtool
und Google Authenticator sind Implementierungen vonRFC 6238 TOTP. TOTP erzeugt mithilfe eines HMAC eine 6-stellige Ausgabe. Obwohl der offizielle Android-Client nicht mehr Open Source ist, liegt das nicht daran, dass sich die TOTP-Implementierung geändert hat oder „geheim“ ist.
Es gibt 2 Eingaben für den HMAC, eine Zahl und ein Geheimnis. In TOTP ist die Zahl die Anzahl der Zeitintervalle aus einer Epoche, wobei die Standardwerte für beide oathtool
und GA 30-Sekunden-Intervalle („Zeitschritt“-Größe) und 1970-01-01 00:00:00 UTC sind. Um es klarzustellen, oathtool
und GA wird zustimmen, solange die Parameter übereinstimmen: Epoche und Zeit müssen ausreichend nahe beieinander liegen und Zeitschritt und Geheimnis müssen übereinstimmen.
Bei Bedarf (z. B. verwenden einige Hardware-TOTP-Token ein Intervall von 60 Sekunden) können Sie -s
die Intervallgröße festlegen und zum Ausgleich von Offset/Drift das überschreiben, was Oathtool für „jetzt“ hält (oder die Epoche manipulieren).
Zur Fehlerbehebung ist Folgendes hilfreich:
oathtool -v --now "now -30 minutes" -w 120 --totp $SECRET
Bei einer Intervallgröße von 30 Sekunden wird eine volle Stunde an Werten generiert, von vor 30 Minuten bis 30 Minuten in der Zukunft. Daraus können Sie einen Token-Offset oder einen Uhr-Offset ableiten (es diff -y
kann nützlich sein, Ausgaben nebeneinander zu vergleichen). TOTP verwendet „Unix-Zeit“, daher sollten Zeitzonen kein Problem darstellen, es sei denn, eine Zeitzone „verbirgt“ einen großen Offset einer falschen Uhr.
--now
und --epoch
verwenden den robusten GNU-Datum-/Uhrzeit-Parser und unterstützen relative Zeitangaben sowie absolute Zeitstempel, --now "30 min ago"
funktioniert auch.
Wie der OP festgestellt hat, gilt: Wenn die Zeit für die Standardepoche und den Standardzeitschritt stimmt, dann muss es das Geheimnis sein, das nicht stimmt.
Antwort2
Ich habe Google Authenticator und Oathtool synchronisiert:
secret=`echo 1234567812345678 | base32`
oathtool -v --totp -b $secret
qrencode -t ANSI "otpauth://totp/test?secret="${secret}""