In most websites today, security doesn’t stop at just a username and password. To add an extra layer of protection against phishing and unauthorized access, Two-Factor Authentication (2FA) is commonly used.
There are different ways to implement 2FA:
- SMS OTPs sent to your mobile
- Push notifications (e.g., GitHub’s mobile approval)
- Authenticator apps like Google Authenticator, Microsoft Authenticator, or Authy
Among these, authenticator apps are the most widely used. They generate one-time passwords (OTPs) that refresh either:
- On demand (HOTP – Hash-based OTP), or
- After a fixed period (TOTP – Time-based OTP).
Example: QR Code + Authenticator App
When you enable 2FA on a website, you’re usually presented with a QR code to scan in your authenticator app:
The QR code encodes a special URI in the following format:
otpauth://totp/Issuer:Account?secret=BASE32SECRET&issuer=IssuerName&algorithm=SHA1&digits=6&period=30
Key parts:
-
otpauth://totp → scheme (could also be
hotp
) - Issuer:Account → helps you identify which service/account the OTP belongs to
- secret → Base32 encoded secret key shared between server and your app
-
algorithm → hashing algorithm (usually
SHA-1
, sometimesSHA-256/512
) - digits → OTP length (6 or 8)
-
period → validity window in seconds (default:
30s
for TOTP)
Your authenticator app extracts these details and starts generating OTPs automatically.
HOTP – Hash-based One-Time Password
HOTP is counter-based. Both the server and your authenticator app maintain:
- A secret key (shared during setup)
- A counter (incremented each time an OTP is generated)
Flow diagram:
Steps:
- Combine the secret key and counter.
- Hash them using the chosen algorithm (usually SHA-1), producing a 20-byte HMAC code.
- Apply dynamic truncation to extract a 6–8 digit OTP.
- The generated OTP is sent to the server, which independently performs the same calculation to verify it.
Note: Each byte is 8 bits, so a 20-byte HMAC gives a 160-bit code.
TOTP – Time-based One-Time Password
TOTP is time-based. Instead of a counter, it uses the current timestamp:
0 The server and client compute a time step (e.g., floor(currentUnixTime / period))
- The time step is treated as the counter in the HOTP algorithm
Flow diagram:
Steps:
- Compute the time step C = floor(currentUnixTime / period).
- Combine the secret key and time step, then hash with HMAC.
- Apply dynamic truncation to get the OTP.
- OTP is valid for the selected time period (e.g., 30 seconds).
This allows both server and client to generate the same OTP independently, as long as their clocks are synchronized.
Dynamic Truncation
Dynamic truncation is a common step in both HOTP and TOTP:
Steps:
- Take the last byte of the HMAC result and perform a bitwise AND with 0x0F (decimal 15) to calculate an offset.
- Select 4 bytes starting from the offset.
- Convert these 4 bytes to a 31-bit integer (ignore the sign bit).
- Apply modulo 10^d (where d is the number of digits, usually 6 or 8) to get the final OTP.
This ensures the OTP is a fixed-length numeric code, even though the HMAC is 20 bytes
Differences: HOTP vs TOTP
Feature | HOTP | TOTP |
---|---|---|
Counter/Time | Incremented counter | Time step (current time / period) |
Validity | Valid until used | Valid only for the time period |
Sync Requirement | Counter sync required | Clock sync required |
Use Case | Hardware tokens, banking apps | Mobile authenticator apps, web apps |
Additional Notes
- Always use SHA-1 or stronger algorithms (from server POV).
- For TOTP, if the client and server clocks drift, the OTP may fail. - Many servers implement a window of 1–2 time steps to allow minor clock differences.
- HOTP is mostly used for hardware tokens, while TOTP is widely used in mobile apps.
- Avoid SMS-based OTPs where possible due to SIM swap attacks.
Check out slide
Check out video
Top comments (0)