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
Default output of random_base32()
is not valid base32
#115
Comments
Thanks for reporting and researching the problem. While your assessment is correct in general applications of the base32 encoding, the specific implementation in PyOTP is specific to the otpauth:// key URI schema defined here: https://github.com/google/google-authenticator/wiki/Key-Uri-Format In particular, https://github.com/google/google-authenticator/wiki/Key-Uri-Format#secret states:
So the issue you describe appears to be a bug in the speakeasy library's base32 parsing logic as applied to the variant of base32 used in the otpauth schema. |
Actually it looks like there are multiple issues here. The inconsistency in provisioning_uri output after calling verify() is definitely a bug, I've addressed it in ee827b4. |
Actually since the RFC recommends 160 bits, I'm going to go ahead and follow your suggestion, requiring base32 strings of minimum length 32. |
Fixes released in v2.6.0, please test. |
Thanks for the fast response and patches - after reading the spec I agree that the current behaviour for unpadded values is correct, both for genreation and interpretation. I will investigate the I can confirm the behaviour of the new release looks good in our test suite. |
Relates to #109
Introduced in 9576711
The current output of the
random_base32()
function is a string of base32 alphabet characters, of 26 length. This is not a valid base32 string, as it does not include padding to a length multiple of 8.This causes problems when it is used as the secret value for a TOTP, like the output of
TOTP.provisioning_uri
changing depending on whether or notTOTP.verify
has previously been called:More importantly, it introduces undefined behaviour when interoperating with other TOTP libraries, such as node's speakeasy. The example secret below is the same in both examples, but produces different codes in each library:
This is flaky behaviour, as a different base32 alphabet string of length 26 does give the same codes between libraries. I imagine how the two libraries handle invalid base32 differs in implementation detail.
To fix this, I suggest increasing the default length of the generated string to 32, which is a multiple of 8.
The text was updated successfully, but these errors were encountered: