TOTP tokens not working after upgrade - 'ascii' codec can't decode byte 0xdf in position 0

Hi,
After server crash I had to make recovery with clean install to move from very old PID 2.1 release to new 2.23.3. After everything was installed and recovered I’ve faced issue. When trying to use or just check any of TOTP, getting this error:

‘ascii’ codec can’t decode byte 0xdf in position 0: ordinal not in range(128)

All required fields in DB was created, data recovered from sql dump, original enckey file was recovered (test machine was created with PID 2.1 and there are no issues checking TOTP with same data set)
New TOTP tockens, created after upgrade working fine.
Is there any way to fix it?
Thank you in advance!

Below is a full error log:

 Traceback (most recent call last):
   File "/opt/privacyidea/local/lib/python2.7/site-packages/flask/app.py", line 2292, in wsgi_app
     response = self.full_dispatch_request()
   File "/opt/privacyidea/local/lib/python2.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
     rv = self.handle_user_exception(e)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/flask/app.py", line 1718, in handle_user_exception
     reraise(exc_type, exc_value, tb)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
     rv = self.dispatch_request()
   File "/opt/privacyidea/local/lib/python2.7/site-packages/flask/app.py", line 1799, in dispatch_request
(**req.view_args)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/postpolicy.py", line 102, in policy_wrapper
     response = wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/prepolicy.py", line 120, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/prepolicy.py", line 120, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/prepolicy.py", line 120, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/decorators.py", line 96, in check_user_or_serial_in_request_wrapper
     f_result = func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/subscriptions.py", line 333, in check_subscription_wrapper
     f_result = func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/lib/prepolicy.py", line 120, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/event.py", line 98, in event_wrapper
     f_result = func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/api/validate.py", line 350, in check
     result, details = check_otp(serial, password)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 154, in log_wrapper
     return func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/token.py", line 1957, in check_otp
     res = tokenobject.check_otp(otpval) >= 0
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/decorators.py", line 44, in token_locked_wrapper
     f_result = func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/totptoken.py", line 334, in check_otp
     symetric=True)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 154, in log_wrapper
     return func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/HMAC.py", line 147, in checkOtp
     otpval = self.generate(c)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/HMAC.py", line 122, in generate
     hmac = self.hmac(counter=counter, key=key)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/tokens/HMAC.py", line 82, in hmac
     dig = str(self.secretObj.hmac_digest(data_input, self.hashfunc))
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/crypto.py", line 124, in hmac_digest
     self._setupKey_()
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/crypto.py", line 156, in _setupKey_
     akey = decrypt(self.val, self.iv)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/log.py", line 154, in log_wrapper
     return func(*args, **kwds)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/crypto.py", line 409, in decrypt
     ret = hsm.decrypt(input, iv, id)
   File "/opt/privacyidea/local/lib/python2.7/site-packages/privacyidea/lib/security/default.py", line 397, in decrypt
     eof = output.rfind(u"\\x01\\x02")
 UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)

“After a server crash”?

This sounds bad. Where did you get your DB from?

The data in the DB is encrypted. You probably used the wrong encryption key during the fresh install. This is why the old data can not be decrypted.
Check if you can find your old encrpytion key, which was probably located at /etc/privacyidea/enckey.

If you want to run a professional setup, please consider getting professional help.

Sorry, i missed this:

Well, this is actually the error message, if the encryption key does not match.
So I could also assume, that you think you have the correct encryption key.
Please note, that the encryption key is read at startup. If you change the encryption keyfile, while the system is running, the system does not care until you restart the server.
So the following can happen:

  1. start the system encrypt data with existing encryption key
  2. change the encryption key on the filesystem
  3. system still works with the old encryption key
  4. restart system (or recover) and system will not work the with new encryption key.

Hope this helps and maybe gives you an idea.
What was your install method?

Yes, I’ve used enckey and sql base from backup (luckly I had them). If Im installing old version (2.1, from archive) on test machine, it is working with TOTP restored from sql dump with this encfile. But when Im applying this DB and encfile on version 2.23.3 it throws this error. And yes, server is restarted after any change. Maybe there is any way to export/import this tokens from old version to new?
Install methode for new server was as per website manual.
Thank you in advance!

Check that the same enckey is used!
I.e. if your install method between 2.1 and 2.23 changes, you might use a different enckey.
This depends on how you are running the server! If you choose a slightly different way to run the server, the app could load an enckey from a different location.

Where are your users? Are they located in an ldap resolver? If so, then a changing enckey should also lead to not being able to read the LDAP, since the ldap password is also encrypted.

Check, how your old enckey llooks like. It should be 96bytes file.
I think version 2.1 did not really have a neet way to export the tokens.

cornelinux - Thanks for help! Today I’ve found what was the issue - somehow it was reading encfile from different path. Did a clean install, removed all other files and it started to work!

1 Like