In practice, clocks are often out of sync enough that you want to give some leeway and accept some codes on either side of the current code. The implementation I use for sourcehut is similarly tiny:
Yes, in fact the RFCs for both HOTP and TOTP have a section each dedicated to resynchronization of counter/clock to account for client and server being out of sync. Here are the relevant sections:
In case of HOTP, the client's counter could be ahead of the server's counter if a user requests multiple HOTPs from the client before the user presents the HOTP to the server. Therefore the server should look ahead according to a permissible look-ahead window to see if any succeeding HOTP value matches the HOTP presented by the user or client.
In case of TOTP, there is of course the problem of clock drifts. Therefore the server should look backward as well as forward by a few time steps to see if any TOTP backward or forward matches the TOTP presented by the user or client.
In the past, when I've implemented TOTP on the server, I've allowed for a couple of time periods of drift. But I recorded the time period that last matched, and only allowed subsequent authentication attempts to be strictly greater than the last successful time period, to prevent replay attacks.
> Note that a prover may send the same OTP inside a given time-step window multiple times to a verifier. The verifier MUST NOT accept the second attempt of the OTP after the successful validation has been issued for the first OTP, which ensures one-time only use of an OTP.
Plugging my hotp/totp python library hotpie[0]. Written originally in 2010. Around 100 lines including comments and tests against the RFC. Available on Pypi for python 2.x and 3.x.
The beauty of HOTP/TOTP for me is its simplicity. And being able to write a simple implementation makes it easy to test, debug and be sure that there are little or no holes.
I get your point but equally the point of programming languages is to abstract away the harder stuff. The question is just how much abstraction developers want between the code and the execution.
I mean, you could make the same claim about one written in C because it doesn’t include stdio.h. So where do you draw the line? Assembly?
My point is that saying that something is written in 18 lines of code when actually all the heavy lifting is done by the libraries is misleading. That doesn’t mean I don’t appreciate Python’s expressiveness and rich standard library.
Yeah, but that comment can be made about literally every software in existence. Even core language keywords are doing a lot of heavy lifting in the interpreter.
In Python, the stdlib is effectively part of the language, so as long as they're not installing third-party libs, I don't see how it can be misleading.
Along with micropython-hmac (MicroPython doesn't include hmac), and the touch sensor on an ESP32 I threw together an authenticator with the same inspiration as this project. It seems to work quite well, overall.
micropython-lib packages aren't included in the base MicroPython (well, not the main one. The Pycopy fork does), and are published on PyPI under micropython-x. You've found the source for the package I named.
Am I the only one who found the use of acronyms here a little annoying? Like, use the whole word expansion at least once before introducing the acronym. That should be standard practice regardless of discipline and audience.
I didn't know what it meant, and looked it up. "Time-based One Time Password" explains a hell of a lot more that "TOTP." From just those 4 words I figured out we were talking about the kind of thing that powers 2-factor auth implementations where get a time-based one-time code.
Before I looked it up, I thought it was somehow related to NTP.
My point is that "time based one-time password" doesn't really tell you anything about what TOTP is; what you want is the phrase "the protocol code-based 2FA applications like Google Authenticator use", after which you don't care anymore about the stupid name the protocol has.
It's a little bit like expanding "transport control protocol". I mean, sure, I guess it's marginally better than the acronym TCP? But really, that's not the clarification you want to provide to someone who doesn't know what TCP is.
Also, obviously, if you don't know what TOTP is, you might just not be the audience for the article. Remember that most people don't write their personal blogs (or, in this case, their Github personal projects) specifically for an audience of Hacker News people, even though HN sometimes makes it seem that way.
Although not at the very first line, I do expand the acronyms in the first section:
> Introduction: TOTP stands for Time-based One-Time Password. At the heart of the TOTP algorithm lies the HOTP algorithm. HOTP stands for HMAC-based One-Time Password.
>However, doing so defeats the purpose of two-factor authentication (2FA).
There are still some 2FA benefits from this. The biggest one is for people who reuse passwords. Some websites might put you into a higher security tier if you have 2FA. Also if you have to choose between SMS vs this, this has some benefits, for example it can't be hijacked by social engineering your phone provider.
Also it says regular TOTP protects you from keyloggers. That's not fully true, because the keylogger could steal your TOTP code as you enter it into the website. If the keylogger is realtime, it could log into your account before you're able to. Or if you assume there's malware on your computer, it could steal your cookies, or perform whatever account actions it wants directly on your computer.
The README does not say that TOTP protects us from keyloggers. I was either not clear in writing that paragraph or you may have misundertood that paragraph. Here's what the README says,
> If your desktop/laptop device is compromised, then both authentication factors would be compromised. The attacker can steal the first authentication factor that only you should know (e.g., password) by running a key logger on the compromised device. The attacker can also steal the second authentication factor that only you should have ...
What I mean here is that generating the TOTP on the same system that we would use to log into a website with 2FA defeats the purpose of 2FA because the attacker can steal the TOTP secret key in addition to stealing the password (keylogger being one way to steal the password).
I think the grandparent is just trying to say that while it defeats one of the purposes behind 2fa, it doesn't defeat all of them. Security is all about trade-offs and defense in depth and 2fa is still valuable in this sense even with the 2fa secret stored on your laptop. That is, it trades off some security for convenience but is still more secure than not having 2fa.
I agree. I think it is acceptable to trade some security for convenience and in this case the convenient solution is still more secure than not having 2FA at all. However, the fact that some security is being traded for convenience should be documented in the README, otherwise one can criticize that the README is promoting a less secure usage of TOTP.
>because the attacker can steal the TOTP secret key
My question is why are we worrying so much about theft of the secret key? There are easier things to steal and abuse (cookies, TOTP codes, website data). Those can be stolen even if the TOTP generator is a different device than the logging in device.
I agree that there are easier things to steal. However, that should not allow us to be lax with the security of the TOTP secret key. I think it still makes sense to worry about the theft of the TOTP secret itself. It's just an additional thing to protect along with cookies, TOTP codes, website data, etc.
I personally prefer this golang library to generate my OTP codes https://github.com/pquerna/otp as it's much faster than running a python script.
My personal computer is the 'what I have' to do the second factor of authentication for most sites via a shell script, followed by xclip (linux) or pbcopy (mac). I prefer this over browser extensions using javascript to paste in your OTP code for you.
If you want raw speed, oathtool is hard to beat. Only 132KB to load to memory, compared to the megabytes of the typical Go binary. But unless you're playing an FPS where you have to input TOTP codes to shoot, this script is probably fast enough (80ms on my old laptop).
It's amusing to see people think 100KB+ is small, when the whole TOTP algorithm, including SHA1 (probably the biggest part), and the input/output conversion, likely needs only a few KB of code. With the exception of SHA1, everything else is doable in dozens of bytes.
True, but I'm just talking about the sizes of the binaries generated by the default settings of common compilers (gcc, in the case of oathtool), for comparing orders of magnitude. I'm sure there's plenty of fat you could trim by simply tuning the compilation a bit.
(Oathtool also supports SHA2, since it may be used by other implementations, per the RFC. )
https://git.sr.ht/~sircmpwn/meta.sr.ht/tree/master/metasrht/...