Skip to main content
Deep DiveAuthentication MathExplainer· 6 min read· in Technology

The SHA-1 Hash and Time-Step Math That Generates a Six-Digit One-Time Password

Every 30 seconds, authenticator apps use a shared secret and the current Unix time to compute a 160-bit cryptographic hash, immediately discarding 80 percent of it to produce a scannable six-digit code. The security of the system relies entirely on keeping the initial seed secret and the clocks synchronized, not on the complexity of the final number.

By Lila Morgan

Usability Advocates 40%Protocol Standardizers 40%Cryptographic Purists 20%
Usability Advocates
Prioritizes the human-readable six-digit format over theoretical cryptographic strength.
Protocol Standardizers
Focuses on maintaining the interoperability and deterministic math of the original RFCs.
Cryptographic Purists
Argues for upgrading the underlying hash function from SHA-1 to SHA-256.

Perspectives this story doesn't cover

  • End users who experience account lockouts due to lost seeds or clock drift
  • Hardware token manufacturers competing against free software authenticators

Summary

  • TOTP codes are generated independently by the device and the server using a shared secret key and the current Unix time.
  • The algorithm uses HMAC-SHA-1 to create a 160-bit hash, then uses dynamic truncation to extract a 31-bit integer.
  • A final modulo operation divides the integer by one million, leaving a six-digit remainder that serves as the user's code.
  • The process deliberately discards 80.6 percent of the cryptographic hash to prioritize human readability.
  • Because the math is deterministic, authenticator apps require no internet connection or cellular service to function.

A six-digit authenticator code is the remainder of a 31-bit integer divided by one million, derived from a 160-bit cryptographic hash of the current time and a secret key. When a user opens an app like Google Authenticator or Authy, the software does not request a new code over the network; instead, it independently performs a mathematical operation defined in a 2011 standard called RFC 6238, ensuring its output exactly matches the server's expectation for that specific 30-second window.[4]

The mechanism, known as a Time-Based One-Time Password (TOTP), is often marketed by security vendors as an impenetrable cryptographic shield. In reality, it is a highly lossy compression function that prioritizes human readability over mathematical complexity. The system works precisely because it throws away the vast majority of its own cryptographic work, relying entirely on the premise that the starting ingredients—the secret seed and the clock—cannot be guessed.[1]

The process begins during account setup, when a server generates a random secret key, typically represented as a Base32 string and displayed as a QR code. When the user scans this code, the authenticator app stores the secret locally. From that moment on, the server and the device share the same starting material, allowing them to run identical calculations in parallel without ever communicating again.[3]

To generate a code, the algorithm needs a moving factor. In the older HMAC-Based One-Time Password (HOTP) standard, defined in 2005 by RFC 4226, this moving factor was a sequential counter that incremented with each login. TOTP replaces that counter with the current Unix time—the number of seconds elapsed since January 1, 1970.[1][4]

Because a code that changes every second would be impossible to type, the algorithm divides the current Unix time by a fixed time step, which defaults to 30 seconds. "The TOTP algorithm takes the current timestamp and a shared secret key to generate a new numeric code every 30 seconds," notes Descope's 2025 technical breakdown of the protocol. This division creates a stable integer that remains constant for the duration of the window, ensuring the user has time to read and enter the digits.[4]

The TOTP algorithm discards the vast majority of its cryptographic hash to produce a human-readable number.

With the secret key and the time step integer in hand, the algorithm feeds both into a cryptographic hash function. The default function specified by the Internet Engineering Task Force (IETF) is HMAC-SHA-1. This operation scrambles the inputs together, producing a 160-bit output, which is equivalent to 20 bytes of data.[1][4]

A 160-bit hash is mathematically robust, but it is entirely useless for consumer authentication. Displayed in hexadecimal, it would be a 40-character string—far too long for a user to quickly type into a login prompt. To solve this, the algorithm performs an operation called dynamic truncation.[1]

Dynamic truncation extracts a small, unpredictable slice of the 160-bit hash. The algorithm looks at the very last byte of the 20-byte hash and reads its lower four bits. These four bits form a number between 0 and 15, which the algorithm uses as an offset index.[1][3]

Dynamic truncation extracts a small, unpredictable slice of the 160-bit hash.

Using that offset, the algorithm jumps to that specific byte in the hash and extracts exactly four consecutive bytes—32 bits of data. To avoid software bugs caused by different systems interpreting the first bit as a positive or negative sign, the algorithm deliberately masks out the most significant bit, leaving a clean 31-bit integer.[1]

At this stage, the algorithm has successfully reduced a 160-bit cryptographic hash down to a 31-bit number. This intermediate integer can be as large as 2.14 billion. However, a 10-digit number is still considered too cumbersome for rapid human data entry.

The final step is a simple modulo operation. The algorithm takes the 31-bit integer and divides it by 10 to the power of the desired code length. For a standard six-digit code, it divides the integer by 1,000,000 and keeps the remainder. If the remainder is 492,817, that becomes the code displayed on the screen. If the remainder is just 42, the app pads it with leading zeros to display 000042.[1][3]

Dynamic truncation discards 129 bits of the original 160-bit SHA-1 hash before the final code is calculated.

This mathematical sequence reveals a stark reality about TOTP security: the algorithm deliberately discards 80.6 percent of the original SHA-1 hash—129 of the 160 bits—before the final modulo reduction. The six digits the user types are not cryptographically secure on their own; they are merely a temporary byproduct of a secure, hidden process.[1][5]

Because the final output is so constrained, the system is highly vulnerable to phishing. If an attacker intercepts the six-digit code and the user's password, they have a 30-second window to use those credentials on the real site. The math cannot detect who is entering the code, only that the code matches the expected output for that specific half-minute.

Despite the reliance on SHA-1—a hashing algorithm that the National Institute of Standards and Technology (NIST) formally deprecated for digital signatures due to collision vulnerabilities—TOTP remains secure against mathematical reverse-engineering. "The default HMAC-SHA-1 function could be replaced by HMAC-SHA-256 or HMAC-SHA-512," the IETF authors noted in RFC 6238, but the industry largely ignored the suggestion.[4]

Security firm Protectimus highlighted this inertia in a 2023 analysis, noting that while SHA-256 is objectively stronger, the truncation process renders the upgrade practically meaningless for TOTP. Because the algorithm throws away most of the hash anyway, the theoretical vulnerabilities of SHA-1 do not give an attacker a viable path to reverse-engineer the original Base32 secret from a six-digit remainder.[2]

The more pressing vulnerability is clock drift. The algorithm assumes the server and the smartphone agree on the exact Unix time. If a smartphone's internal clock drifts by just two minutes, it will generate codes that are four time-steps ahead of or behind the server.[2]

Because the algorithm relies on Unix time, a clock drift of just two minutes can cause the server and the device to generate completely different codes.

To prevent users from being locked out by minor synchronization issues, servers typically implement a look-ahead window. When a user submits a code, the server does not just calculate the hash for the current 30-second step; it calculates the hashes for the previous step and the next step as well. If the user's code matches any of those three results, the server accepts the login and quietly notes the time offset for future authentications.[3]

This mathematical simplicity is why TOTP defeated earlier, proprietary hardware tokens. By relying on standard Unix time and open-source HMAC-SHA-1 hashing, the protocol allowed any developer to build an authenticator app and any service to verify the codes without paying licensing fees. The math is entirely deterministic, requiring no network connection, no proprietary hardware, and no centralized authority.

As the industry slowly pivots toward passkeys and cryptographic hardware that resist phishing, the six-digit TOTP code remains the fallback standard. Its survival is a testament to the durability of RFC 6238—a protocol that accepted massive cryptographic data loss in exchange for a string of numbers short enough for a human to type before a 30-second timer runs out.[4][5]

Definitions

TOTP
Time-Based One-Time Password, an algorithm that generates temporary numeric codes using a shared secret key and the current time.
Unix Time
A system for describing a point in time, defined as the number of seconds that have elapsed since midnight on January 1, 1970.
HMAC
Hash-based Message Authentication Code, a specific type of cryptographic function that combines a cryptographic hash with a secret cryptographic key.
Dynamic Truncation
A mathematical process used in TOTP to extract a specific 31-bit slice from a larger 160-bit cryptographic hash.
Modulo Operation
A mathematical operation that finds the remainder after division of one number by another, used in TOTP to reduce a large integer to exactly six digits.

Questions & answers

Why do authenticator codes expire after 30 seconds?

The algorithm divides the current Unix time by 30 to create a stable time step. This ensures the code remains constant long enough for a user to type it, but expires quickly enough to limit an attacker's window if the code is intercepted.

Does my authenticator app communicate with the server to get the code?

No. The app and the server both possess the same secret key and use the same mathematical formula. They independently calculate the exact same code at the same time without needing an internet connection.

Why does TOTP still use SHA-1 if it is considered outdated?

While SHA-1 has theoretical vulnerabilities, the TOTP algorithm discards over 80 percent of the hash before displaying the six-digit code. This truncation makes it mathematically impossible for an attacker to reverse-engineer the secret key from the final code, rendering SHA-1's weaknesses irrelevant in this specific context.

What happens if my phone's clock is slightly wrong?

If your clock drifts, your app will generate codes for the wrong time step. However, most servers check the codes for the previous and next 30-second windows to accommodate minor synchronization issues.

Sources

Source coverage

5 outlets

3 viewpoints surfaced

Usability Advocates 40%Protocol Standardizers 40%Cryptographic Purists 20%
  1. [1]RFC EditorProtocol Standardizers

    HOTP: An HMAC-Based One-Time Password Algorithm

    Read on RFC Editor →
  2. [2]ProtectimusCryptographic Purists

    The Advantages of SHA-256 over SHA-1 for TOTP Token Security

    Read on Protectimus →
  3. [3]HexnodeUsability Advocates

    What is HMAC-based OTP (HOTP)?

    Read on Hexnode →
  4. [4]RFC EditorProtocol Standardizers

    TOTP: Time-Based One-Time Password Algorithm

    Read on RFC Editor →
  5. [5]Factlen Editorial Team

    Synthesis by Factlen editorial team

    Read on Factlen Editorial Team →

Comments

Stay informed

Every angle. Every day.

Get Technology stories with full source coverage and perspective breakdowns delivered to your inbox.