TOTP for developers
The algorithm is short. Most mistakes are in what surrounds it.
What the RFCs require and recommend
- Secret length. RFC 4226 (requirement R6) says the shared secret must be at least 128 bits and recommends 160 bits. Make it with a cryptographically secure random generator. 160 bits is 20 bytes, or 32 Base32 characters. The tester can make one.
- Digits. RFC 4226 says the value must be at least 6 digits.
- Time step. RFC 6238 recommends 30 seconds. It says a larger step gives an attacker a longer window.
- Window. RFC 6238 recommends allowing at most one time step as network delay.
- One use. A code that was accepted once must not be accepted again: RFC 6238 says the verifier must not accept the second attempt of the OTP after the first one was validated.
- Throttling. RFC 4226 describes a throttling parameter: refuse a user after a number of failed attempts.
- Time beyond 2038. RFC 6238 says the implementation must support a time value larger than 32 bits.
Storing the secret
The verifier needs the secret itself, so it cannot be stored as a hash like a password. NIST says the keys held by verifiers must be strongly protected against unauthorized disclosure and limited to the software parts that need them. In practice: encrypt secrets at rest with a key kept outside the database, limit who can read them, and never write them into logs.
Test it
Use the vectors: RFC 4226 Appendix D for HOTP and RFC 6238 Appendix B for TOTP. Our page of RFC test vectors lists them and explains the longer seeds for SHA-256 and SHA-512. A test with a wrong code, a code from two steps ago and a reused code should fail.
Other points
- Compare codes in constant time where your language allows it.
- Show the QR code once, over https, and do not keep the image.
- Offer backup codes and a way to turn off the second step with proper checks.
- Plan for phishing. Codes can be relayed by a fake site in real time. If your users are at high risk, offer security keys or passkeys.
Should I allow codes from the previous step?
RFC 6238 recommends at most one step of delay. Many servers accept the previous and the next step to cover clock drift.
Can I use SHA-256 instead of SHA-1?
RFC 6238 allows it, but many authenticator apps support only SHA-1. Check your users' apps before you change it.
Sources
- RFC 4226 (rfc-editor.org/rfc/rfc4226): requirement R4, R6 and throttling
- RFC 6238 (rfc-editor.org/rfc/rfc6238): time-step size, validation, 2038
- NIST SP 800-63B-4 (pages.nist.gov/800-63-4/sp800-63b.html): protection of OTP keys at the verifier
Read on 14 November 2026.
This is an independent guide. It is not connected with the IETF, NIST, CISA, any authenticator app or any company named here. Facts were read on 14 November 2026 from the documents named on each page; codes and examples were calculated with Python and with the page's own code, and checked against the RFC test vectors.