Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No OTP for long secrets #334

Open
rkilchmn opened this issue Apr 21, 2022 · 5 comments
Open

No OTP for long secrets #334

rkilchmn opened this issue Apr 21, 2022 · 5 comments

Comments

@rkilchmn
Copy link

rkilchmn commented Apr 21, 2022

More and more sites seem to have quite long secrets e.g. JREEWT1JJRFTGNCKLF7UMVJVJBETEQ2CIJGD6NKGGRLU6RJWJ54A

With such a secret no OTP is displayed
passman_longsecret_screenshot

Interestingly it works in the Nextcloud app and the Android Passman app

@Thimoty44
Copy link

Same for me I can confirm

@wilya7
Copy link

wilya7 commented Mar 4, 2024

Workaround: the secret key must have a length divisible by 8. If necessary, add 'A' characters to the end of the key until it meets this requirement. This is because adding "A" (which decodes to zero in base32) does not alter the meaningful part of the secret but allows it to pass the length check

see nextcloud/passman#293 (comment)

EDIT: I just realized that my comment is completely wrong here. These long strings are > 64 bit, therefore the padding would not work. Also the string provided by @rkilchmn is divisible by 8. This is a completely different issue of passman.

@olfek
Copy link

olfek commented Sep 8, 2024

@wilya7 ...

This is because adding "A" (which decodes to zero in base32) does not alter the meaningful part of the secret

So a secret with leading or trailing zero bits does not change the output TOTP code?
Is this a feature of the TOTP algorithm?
Where is it mentioned in the TOTP RFC?

@wilya7
Copy link

wilya7 commented Sep 8, 2024

@olfek This is how I understand the issue, but I am not an expert so take all this with a grain of salt.

The issue doesn't lie within the TOTP or HMAC algorithms themselves (*), but rather in the handling of the Base32-encoded key during the transition to the hexadecimal format required by HMAC. Base32 encoding, using 5-bit groups, can lead to incomplete byte representations when the key's length isn't a multiple of 8 bits. Padding with 'A's (representing 0 bits) ensures correct Base32 decoding, preventing truncated bytes that would disrupt the TOTP generation process.

For example, Amazon gives to passman a key 30 bit long encoded in base32. This key needs to be converted in binary and then in hex and fed to HMAC algorithm. While 30 bits form complete Base32 blocks (6 characters in Base32, as each character represents 5 bits), they don't translate to complete bytes when converted to hexadecimal. Therefore you pad the number with zeros to a 40 bit number, which is a multiple of 8 and gives a correct binary representation of the original number, although the numbers are different. While this padded representation results in a different hexadecimal string, it doesn't affect the HMAC calculation due to how HMAC handles the keys.

HMAC (**) uses a fixed block size (64 bytes for SHA-1, SHA-256, etc.), If the key is shorter than the block size, it's padded with zeros anyway. If the key is longer than the block size, it's hashed to create a shorter key. In this case, both the 30-bit and 40-bit keys are shorter than the block size, so they are both zero-padded to the full block size internally by the HMAC function leading to the same MAC values.

(*) the HMAC algorithm is used as a basis for many cryptographic protocols and applications, including TOTP
(**) RFC2104

@olfek
Copy link

olfek commented Sep 12, 2024

@wilya7 ...

After some experimentation, I can confirm the following -

  • Leading zeroes in the secret change the output OTP.
  • Trailing zeroes in the secret have no affect on the output OTP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants