Problem importing TOTP tokens: error 500 for "Test OTP only” in WebUI

Ladies and Gentlemen,
we are currently evaluating privacyIdea (v3.9.3) and this is our first attempt (please excuse any beginner’s mistakes).

We have successfully configured one of our LDAP servers and see all active users, they all belong to one realm. We can enroll and assign TOTP tokens to users, “Test OTP only” in the WebUI works fine.

In the course of a migration from an older system, we wanted to import TOTP setting using a CSV file:

# version: 2
muster,ldap3,sf.mpg.de,abc123,HNA5GSU3YGXAVVRK,TOTP,6,30
...

Importing the CSV is reported as successful. The tokens are all listed. However, “Test OTP only” for any of these imported tokens results in the error message:

[2024-08-23 16:15:25,425][214960][140364862203456][ERROR][privacyidea.app:1891] Exception on /validate/check [POST]
Traceback (most recent call last):
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/opt/privacyidea/lib/python3.10/site-packages/flask/app.py", line 1936, in dispatch_request
...
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/log.py", line 146, in log_wrapper
    return func(*args, **kwds)
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/tokens/HMAC.py", line 154, in checkOtp
    otpval = self.generate(c)
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/tokens/HMAC.py", line 120, in generate
    hmac = self.hmac(counter=counter, key=key)
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/tokens/HMAC.py", line 82, in hmac
    dig = self.secretObj.hmac_digest(data_input, self.hashfunc)
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/crypto.py", line 115, in hmac_digest
    self._setupKey_()
  File "/opt/privacyidea/lib/python3.10/site-packages/privacyidea/lib/crypto.py", line 138, in _setupKey_
    self.bkey = binascii.unhexlify(akey)

Many thank in advance!
Best regards,
Stefan Vollmar

It seems our problem is now solved thanks to a related observation in [Import C-100 tokens] and the solution offered by its author (koenr - thank you!). In our case, we wanted to import the seeds from Google Authenticator files and that format requires a conversion. Using the code provided by koenr:

import base64
import binascii
...
key_bin = base64.b32decode(seed)
key_hex = binascii.hexlify(key_bin).decode("utf-8")

where seed is the first line of a .google_authenticator file and key_hex needs to go into the seed column of the csv file.

1 Like

Thaks a lot for posting your solution.

Some background: Google Authenticator usually uses base32 encoding.

However, the much older RFC4226 uses hex values like usually most hardware vendors of HOTP and TOTP token. This is why privacyIDEA assumes the import file/seed file to be hex values.