SOLVED:
Using code snippet from he PyOTP library to pad and encode the key before passing it to the algorithm.
missing_padding = len(key) % 8
if missing_padding != 0:
key += '=' * (8 - missing_padding)
byte_key = b32decode(key, casefold=True)
totp = cryptography.hazmat.primitives.twofactor.totp.TOTP(
byte_key,
6,
SHA1(),
30,
backend=default_backend(),
enforce_key_length=False
)
print("{:<10} {}".format(account, totp.generate(time()).decode()))
I'm generating one-time passwords for 2-factor authentication using the cryptography and PyOTP libraries. However, the TOTP objects from the two libraries give different outputs despite using the same key. I suspect it's something to do whether the key should be provided as a string or bytes-like object, but I'm unsure about how to handle the encoding/decoding.
Snippet (key is provided as a string read from a (encrypted) file) ->
totp = cryptography.hazmat.primitives.twofactor.totp.TOTP(
key.encode(),
6,
SHA1(),
30,
backend=default_backend()
)
totp2 = pyotp.TOTP(key)
print("{:<10} {}".format(
account,
totp.generate(time()).decode()),
totp2.now()
)
Result ->
Dropbox 508629 405771
The OTP generated by PyOTP is consistent with Google Authenticator.