Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Understanding How the Time-Based One-Time Password Algorithm Works (digitalbunker.dev)
110 points by aryamansharda on Aug 31, 2020 | hide | past | favorite | 35 comments


I did my own deep dive on TOTP a few years ago and wrote a blog post on how to implement a Google Authenticator compatible 2fa system in java including generating QR codes[0]. Demo code is on GitHub[1].

[0] https://www.asaph.org/2016/04/google-authenticator-2fa-java....

[1] https://github.com/asaph/twofactorauth


The code samples make it super easy to follow. This is fantastic; thank you for sharing!


What confuses me is that TOTP is usually referred to as "something you have" (the app on your smartphone, with the secret), as opposed to "something you know" (your password). But the TOTP algorithm and the current time is known to any attacker. What remains, is just the secret, which is the same as a password (a password given to you by the service provider instead of a self-chosen one). So in the end, TOTP just increases password complexity, doesn't it?

EDIT Trying to answer my question: it prevents a MITM attacker from sniffing your password hash once and using that forever, since the TOTP code is different each time and the attacker would still need to brute-force the secret. But if that's the only benefit of using TOTP, couldn't that be combined with the password: The service where I want to authenticate sends me a "challenge" (random number), I enter my password and an algorithm on my client combines the challenge and my password-hash to create the result to send back to the service. This way the value sent over the insecure line is always different, since it is based on the challenge. The user would not have the added inconvenience of having to enter the TOTP code.


Kind of, but TOTP differs from passwords in important ways. Unlike user-selected passwords, the TOTP secret is guaranteed to be unique and strong as it's generated by the server. Observing some TOTP codes doesn't reveal the secret, so even if the password leaks the TOTP secret probably remains safe. Finally, the TOTP secret is typically managed in a device separate from the one where the TOTP code is entered, making it harder to steal.


I think you can get most of the advantages by just assigning users their passwords. Users either have a password manager to store the assigned password in, or they’re totally insecure and can’t be trusted to make up a password. Either way, just assign something random to them.


It's not all that difficult to remember a strong password, and if you use it with pwdhash, it's unbreakable.


But you need multiple strong passwords for (almost) every site. You need at least one to start, and when one of those sites inevitably leaks all of its passwords you'll have to change that one. Also 50% or more of the sites will have incompatible password content rules, so you'll have to work around that.

Password managers are a lot easier than trying to keep the state for a deterministic system. They're just as unbreakable with a good master password, and actually work with real-world site's rules around passwords.


See how it works: https://pwdhash.github.io/website/ - the master password is hashed with the site name, you supply the resulting hash as the password, you can't reverse this hash if the master password is strong. The result has uppercase letters and lowercase letters and digits, which is good enough for most sites. In practice I saw one site restricting password length to 16 chars, but in case of a hash 16 chars are decent: they contain 95 bits of entropy. And saw one site requiring fourth complexity - punctuation characters - this is easy to circumvent by adding a minus at the end, you can store this information in the open, since circumvention of password policy doesn't affect password strength.


I know how it works. It doesn't help the issues I listed. You can't change passwords when required without storing a database of site names & increments (or similar) to allow you to get the right password. So it's not stateless, and you may as well get all the other benefits of a properly encrypted storage database (autofill, metadata, storing extra things like TOTP keys, SSH keys, etc).


Remember reddit app? Typically TOTP secret is used on the same device, where TOTP code and password are entered (phoneposting).


There are a number of challenge-response authentication systems, e.g. in my first job after university we used cryptocards: https://www.linuxjournal.com/article/8252

And my bank used to supply a similar (but smaller) authentication keypad - they now use a smartphone app instead.

The “know” vs “have” question in multifactor auth traditionally assumes the thing you know is memorized (which you can’t expect people to do with TOTP secrets) and the thing you have is a physical device that authenticates itself with an embedded secret. There’s an intermediate category of secrets you have access to (e.g. in a password manager) but which can’t protect themselves against copying by the authorised user like a physical token.

TOTP and HOTP were designed to be implemented in physical tokens (similar to SecureID https://en.wikipedia.org/wiki/RSA_SecurID tho that uses a different algorithm) but they are often supported by password managers or apps that allow the OTP secrets to be copied.


TOTP is not U2F so it is not something you have, U2F is a setup with physical keys, you can have in android U2F module nowadays, but that is not TOTP. Keys like yubi also store TOTP secrets but that still is not U2F.

TOTP is 2FA so only a second factor, which is different device so you don't have your password and secret key on the same device. With your after edit scenario password can be stolen via keylogger and if you have secret on your mobile phone or just other it is a lot harder to compromise all the devices person has. Where compromising one laptop is of course a lot easier.

Secret key is sent over the network only once when you set up your 2FA and is on different device. It is also generated randomly with really long key so brute forcing it is not feasible at all. If you take into account that nowadays most passwords are available via leaked databases and attacks are just reusing already cracked weak passwords TOTP adds real value. Because even if you steal database with secret keys you are not going to be able to use it for other accounts that single person has.

In the end generating new key and just scanning QR code is IMO great user experience, to change that secret key you don't have to "come up with yet another password". Where ideally you should generate your passwords with password manager a lot of people don't do this. If you generate different password for each site with password manager you probably don't need 2FA that much.


    [...] with really long key so brute forcing it is not feasible at all.
When setting up MFA for a Microsoft Azure AD account, they use a 9 digit code as the secret, which you can either enter manually or by scanning a QR code. My gut feeling is that 1 billion possibilities is not that hard to brute-force.

I don't know if that is standard or if other services use longer secrets.


That's too small. Are you sure it's correct?

Google Authenticator often uses 80-bit keys which is not really ideal but unlikely to be a practical attack avenue. But a billion possibilities is too small.


Nevermind - I might be mistaken. You need to enter the 9 digit number AND a URL. Probably the secret is then loaded from that URL. In the past, I must have used the QR code (I thought I used the number).

Here is a screenshot of the screen with the "secret":

https://docs.microsoft.com/en-us/azure/active-directory/user...

And if you choose to set up a 3rd party app, you get the secret directly, which is indeed 16 characters long (alphanumeric, all lowercase as it seems).


Notably Microsoft's "Microsoft Authenticator app" allows you to pick much shorter codes than rival products. This is definitely unsafe. For example if I tell Google's app that the secret key for my vanity site is 333 it rejects that as too short, but Microsoft's app will cheerfully begin showing "correct" six digit TOTP codes for the secret 333

What exactly is going on with that URL is interesting and since I wasn't immediately able to discover more with some obvious Google searches I'll spend some time poking it later. It will cheerfully POST something to the provided URL and it didn't like the 404 error my vanity site gives back but that's as far I looked so far.

My instinct which I haven't verified is that the (too short) nine digit code may all that protects you when using the one time codes, the URL is for their device notification mechanism, and the way it makes you give the device both allows you (or an Azure administrator) to change which is used later.

Both these are bad news. For the too short secrets what you do is this:

"Hi what's your OTP?" X "I'm sorry, we had a temporary problem. Please wait until a new OTP appears and enter that one." Y

Then you just try all billion secrets and one of them spits out X followed by Y at the appropriate times, you now have the nine digit secret and the "one time" system is trashed.

For the verification it's in some ways even worse, again you just send the user to a phishing site and:

"I'm sorry, for security reasons we're sending you a two factor verification right now, please press Accept".

And then the user cheerfully hits accept and lets you in.

What I particularly love is that Microsoft appears to have bought an entire company to acquire these bad technologies. It would be interesting to learn from key people at Google how they think Google hired and retained people who'd do good crypto design and why Microsoft wasn't able/ willing to do whatever it took to achieve the same.


Further investigation:

The HTTP POST is definitely getting back more secret data. I actually can't easily find out how much, but it's presumably a lot more than nine digits and it would make sense for it to be the same amount used in other products. So that's actually a good sign, the nine digit code as you imagined is just to try to secure that one step.


What you explained in EDIT, reminds me of HTTP Digest auth: https://stackoverflow.com/questions/2384230/what-is-digest-a...


Years ago it took me a few times encountering these keys to realize how they were working (like for Google, etc). Now, on being presented any shared secret to initialize my Authenticator app, I screen capture / print out the secret and store it in my files at home. Just like those recovery codes. Too much of my life is with Google not to have this stored somewhere safe.


Google Authenticator now allows exporting your entire list as a single QR code, so you don't have to save the initial QR code. It's a godsend for migrating between phones.


Googling that, it appears to be available only on Android.


not affiliated with them, but I have used Authy for years for the simple reason that they allow easy sync across devices, backup, and import/export of the credential list.

It's another party to trust, but I prefer it to google authenticator.


Yeah. I keep my Authy backup password in a tiny safe along with other important documents (note: NOT in my password manager, since that would reduce 2FA to 1FA). Last time my phone died a couple years back I just got a new one, registered it to my phone number, downloaded Authy, verified the phone number, entered my paper backup password, and I was good to go. The way Authy is set up this makes me immune to SIM cloning attacks, because they offer no recovery method if you lose your backup password.

As an additional 2FA backup I keep one of those cheap Yubico security keys in the safe, registered to as many sites as will accept them.


Some sites only display the QR code. For those I found ZBar Barcode Tools helpful for converting an image/screenshot to alphanumeric seed:

https://github.com/mchehab/zbar


I wrote a TOTP library and a client program that uses this library (in C - as an attempt of learning C) to make the desktop tool compatible with andOTP encrypted files. Things went well. I was able to get OTPs from andOTP encrypted JSON files. But I am unable to get time to work on it further. The code is open-source. It was fun :)

https://gitlab.com/grijul/libzotp

https://gitlab.com/grijul/zotp


So the HOTP/TOTP rely on the same secret being stored "plaintext" by both the server and the client? I am guessing this is not as concerning at all, as storing a password plaintext on the server, since this mechanism is used _on top of_ a password...


Yes. The main thing going for these mechanisms is that they're so cheap to implement. A Nokia 6310 can run the algorithm, the set of people who could receive SMS based one time codes but can't do TOTP on their phone is close to zero. If you have a "programmer" employed and they can't add TOTP to your system check they said "computer programmer" - my father was a "programmer" who figured out the "programme" as in schedule for a paper factory, that's the wrong kind.

In every other respect they're pretty bad:

The article suggests they can resist phishing. Against a poor adversary (e.g. Email links to a web form masquerading as "fraud check" by your bank) that hasn't considered TOTP they might be enough, but there are ready-to-use tools to help phish TOTP, SMS one time codes, RSA-style key fobs, even the old crude Yubikey one time code thing where you press a button and it squirts text into a form field.

If either the server or the client gets knocked over, the attackers get this long term underlying secret that they can use to fulfil the role of the other permanently.

It's not as likely you'd stupidly log the underlying secret as a password sent to your server in an HTTP POST request, but you still might do it and then you're screwed.

The right take away is probably that this is the low bar, it's so easy that it's inexcusable for a site to pretend it cares you used a "good" password (e.g. by having password complexity rules or requiring Pwned Passwords checks) and then not even bother having TOTP. Oh you want me to put in real effort to protect your stupid web site but then you aren't even doing the bare minimum, how about fuck off?


It's not quite so cheap for a site to implement 2FA. It surely increases support costs by quite a bit. Also possibly weakens security, because an authentication system is only as secure as its recovery process.

With email + password, account recovery is simple: you send a message to the email address. With 2FA, things get very complex very quickly and there isn't any standardized approach I've heard of. Most involve waiting a week or so.

The gold standard would be everyone owning two U2F keys, keeping one safe as backup. Don't even want to imagine what the recovery process would be like for that system if someone manages to lose both keys (which will eventually happen). Probably would involve mailing a new key directly from the company to your address.


Oh, do all dumbphones run unsigned code? Big if true.


I don't know about all dumbphones, some models from last century (many of which won't function on today's networks because the radio standards they need are no longer deployed) aren't even smart enough to manage over-the-air firmware updates and it may be impossible to meaningfully reprogram those. But, like I said, if it doesn't speak a modern radio protocol it can't use the network so who cares?

I believe a Nokia 6310 is just barely new enough that it should work everywhere in the world, although I might be mistaken.

This phone (and many from that era) implement Java MIDP, a thin Java API to do some simple things commonly across different models of mobile phone. In particular we need to discover the UTC time (or at least a local time and then use a stored offset) and remember a secret, and then calculate the TOTP code and display it.

Getting a program onto these phones isn't necessarily easy though. It's not like they're running a web browser and you can just type in a URL somehow. You need to either have a dedicated program and a cable to connect it to a PC, or else you might be able to use WAP, a long obsolete simplified hypermedia protocol for these phones.


Ideally the secrets would be encrypted to prevent outside snooping (and my authenticator app does this at my end) but it would seem that at some point the secret does need to be in plain text at some point.


If the server had a public key with which it could verify OTPs, then the small search space (only 1 million for 6-digit OTPs) means an attacker with that key could also produce one.


There's an bug - the base64 value is being hex-encoded, not the binary SHA1 result. So the hex values are wrong, and the rest as well.


I didn't know how it worked. Thanks for the blog.


>TOPT and HOPT




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: