HOTP, the HMAC-based One-Time Password algorithm from RFC 4226, uses a "dynamic truncation" function to turn the 20 byte HMAC-SHA-1 value into a 31 bit string. The dynamic truncation (from Section 5.3) works like this (and is probably useless):

 DT(String) // String = String[0]...String[19]
 Let OffsetBits be the low-order 4 bits of String[19]
 Offset = StToNum(OffsetBits) // 0 <= OffSet <= 15
 Let P = String[OffSet]...String[OffSet+3]
 Return the Last 31 bits of P

TOTP (RFC 6238) allows using SHA-256 and SHA-512 as the HMAC hash in HOTP, but doesn't seem to define a new dynamic truncation function for use with them:

TOTP implementations MAY use HMAC-SHA-256 or HMAC-SHA-512 functions, based on SHA-256 or SHA-512 [SHA2] hash functions, instead of the HMAC-SHA-1 function that has been specified for the HOTP computation in [RFC4226].

Should I use low 4 bits of String[19] as offset, low 4 bits of String[length-1], or perhaps some other number of bits or a completely different truncation algorithm?

  • $\begingroup$ If you wanted to replicate it, use String[length-1] and do the low 4 bits of SHA-256 or low 5 bits of SHA-512... however the truncation method is probably useless with a well engineered hash function, and fixed LSB or MSB truncation is acceptable. $\endgroup$ Commented Aug 14, 2015 at 9:19
  • 1
    $\begingroup$ @RichieFrame, I agree that it's useless and I could do away with it if I didn't care about compatibility. However, I would like to be able to just say "uses TOTP" rather than having to justify the change. $\endgroup$
    – otus
    Commented Aug 14, 2015 at 10:17

1 Answer 1


I managed to find it out by reproducing the test vectors.

TL;DR: The standard assumes that you use the low 4 bits of the last byte of the hash, regardless of its length. So replace 19 in the original DT definition with 31 for SHA-256 or 63 for SHA-512 and you are good to go.

Finding this out wasn't completely straightforward, as the standard only has a single test secret listed:

The test token shared secret uses the ASCII string value "12345678901234567890". With Time Step X = 30, and the Unix epoch as the initial value to count time steps, where T0 = 0, the TOTP algorithm will display the following values for specified modes and timestamps.

If fact, to reproduce the test vector values for SHA-256 and SHA-512 you have to extend that secret to 32/64 characters. I.e. use the ASCII strings "12345678901234567890123456789012" and "1234567890123456789012345678901234567890123456789012345678901234" instead.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.