0

If we assume that Time based OTP generates the OTP using the hash function like SHA-3. Then, the generated OTP would Hash(Secret, Shared time).

We want a shortened string rather than a full hash string, so truncation is needed.

But that hash function is not reversible. Attackers cannot predict the next OTP based on the current OTP.

Then, why not use the OTP from just the first 6-8 digits from the hash? Why do we need the sophisticated truncation algorithms in RFC 6238 (https://www.rfc-editor.org/info/rfc6238)?

They hashed and extract the OTP as below:

     byte[] hash = hmac_sha(crypto, k, msg);

     // put selected bytes into result int
     int offset = hash[hash.length - 1] & 0xf;

     int binary =
         ((hash[offset] & 0x7f) << 24) |
         ((hash[offset + 1] & 0xff) << 16) |
         ((hash[offset + 2] & 0xff) << 8) |
         (hash[offset + 3] & 0xff);

     int otp = binary % DIGITS_POWER[codeDigits];

     result = Integer.toString(otp);
     while (result.length() < codeDigits) {
         result = "0" + result;
     }
     return result;

Why do we need the process starting from offset?

I want to know the reason why they did not use just MSBs of the hash output.

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • 1
    Are you asking about how TOTP actually works (if so, please do some reading first and ask a specific question if you don't understand something), or about how a hypothetical version of it based on `SHA3(key, time)` would work, or...? The standard TOTP algorithm, popularized by Google Authenticator but used by tons of devices, apps, and services, is fully public (RFC 6238). – CBHacking Mar 15 '22 at 09:06
  • 2
    *"Why we need sophisticated truncation algorithms?"* - do we? The one used as example in RFC6238 is just using as much leading bits as needed. *" just the first 6-8 digits from the hash"* - there are no "digits" in the hash - it is a sequence of bits. Don't confuse it with a specific representation of these bits, like as hex string, base64 ... – Steffen Ullrich Mar 15 '22 at 09:11
  • OK, digging deeper into this, there's actually an interesting question here that was just kind of poorly specified. TOTP (RFC 6238) describes a time-based extension to HOTP (RFC 4226). HOTP does have a rather curious truncate function: of the 160 bit (20 byte) HMAC-SHA1 output, the 4 least-significant bits are used to get the starting offset of a 4-byte value (0-15, end offset 3-18 inclusive). The low 31 bits of that value (everything except the most significant bit) are used to get a 32-bit integer (the high bit is masked off to avoid the question of signed vs. unsigned). – CBHacking Mar 15 '22 at 09:23
  • *From there* the process is straightforward; the 31-bit value is interpreted as a positive integer, the 10^d (where `d` is the number of digits desired) modulus of this integer is taken, and the modulus is rendered in base 10 as the HOTP (and thus TOTP) output. Every step of this process has an explanation (explicit or easily inferred, such as "31 bits is a good balance of easy on the ALU but large enough to not skew the modulus too much") except for one: why the weird way to select the four bytes from the digest? Why not just use an arbitrary 31 bits (e.g. the first or last)? – CBHacking Mar 15 '22 at 09:28
  • @CBHacking isn't it simply a resilient coding approach? It's not dependent on a specific output length from the hash? – schroeder Mar 15 '22 at 09:44
  • @schroeder Leaving aside that the standard specifies HMAC-SHA1 which has a fixed digest size, the algorithm isn't even suitable for generic digest sizes. For example, if the HMAC used MD5 instead, with its 128-bit digest, then the the algorithm as defined above would take the least significant four bits and (if they were 0xc - 0xf), try to read bytes including those indexed 15 (which we already know half of) and those indexed 16-18, which don't even exist. Meanwhile just taking the first (or last) 31 bits works on any digest of at least 31 bits, so it's actually the less-dependent option. – CBHacking Mar 15 '22 at 10:50
  • See also https://crypto.stackexchange.com/questions/5249/why-does-hotp-use-such-a-complex-truncate-function for a similar question. – Jeff Mar 16 '22 at 13:35
  • TOTP is basically the same algorithm like HOTP. HOTP was specified in 2004. No smartphones around! The algorithm was specified for **hardware tokens**! Really! So my guess is that such truncation could be implemented easily in hardware. – cornelinux Jul 26 '22 at 20:26

0 Answers0