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.