duo-labs / py_webauthn

Pythonic WebAuthn 🐍
https://duo-labs.github.io/py_webauthn
BSD 3-Clause "New" or "Revised" License
856 stars 171 forks source link

webauthn_assertion_response.verify incorrect padding on public key #49

Closed haydenth closed 5 years ago

haydenth commented 5 years ago

Hello! Great library, I'm using it for some projects I'm working on. I'm having some problems getting the webauthn_assertion_response.verify method to work ONLY on the cases where I am completing the assertion of a key. The error is below.

pipe_web          | Traceback (most recent call last):
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/webauthn/webauthn.py", line 899, in verify
pipe_web          |     _webauthn_b64_decode(credential_public_key))
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/webauthn/webauthn.py", line 1173, in _webauthn_b64_decode
pipe_web          |     return base64.urlsafe_b64decode(encoded)
pipe_web          |   File "/usr/lib/python3.6/base64.py", line 133, in urlsafe_b64decode
pipe_web          |     return b64decode(s)
pipe_web          |   File "/usr/lib/python3.6/base64.py", line 87, in b64decode
pipe_web          |     return binascii.a2b_base64(s)
pipe_web          | binascii.Error: Incorrect padding
pipe_web          | 
pipe_web          | During handling of the above exception, another exception occurred:
pipe_web          | 
pipe_web          | Traceback (most recent call last):
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2463, in __call__
pipe_web          |     return self.wsgi_app(environ, start_response)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2449, in wsgi_app
pipe_web          |     response = self.handle_exception(e)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1866, in handle_exception
pipe_web          |     reraise(exc_type, exc_value, tb)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
pipe_web          |     raise value
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 2446, in wsgi_app
pipe_web          |     response = self.full_dispatch_request()
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1951, in full_dispatch_request
pipe_web          |     rv = self.handle_user_exception(e)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1820, in handle_user_exception
pipe_web          |     reraise(exc_type, exc_value, tb)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 39, in reraise
pipe_web          |     raise value
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1949, in full_dispatch_request
pipe_web          |     rv = self.dispatch_request()
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1935, in dispatch_request
pipe_web          |     return self.view_functions[rule.endpoint](**req.view_args)
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/flask_login/utils.py", line 261, in decorated_view
pipe_web          |     return func(*args, **kwargs)
pipe_web          |   File "/app/web/views/u2f.py", line 114, in u2f_assert_complete
pipe_web          |     sign_count = webauthn_assertion_response.verify()
pipe_web          |   File "/usr/local/lib/python3.6/dist-packages/webauthn/webauthn.py", line 1093, in verify
pipe_web          |     'Authentication rejected. Error: {}.'.format(e))
pipe_web          | webauthn.webauthn.AuthenticationRejectedException: Authentication rejected. Error: Incorrect padding.

And here is the calling code. My pub_key is being stored in the method used in the demo flask app (which doesnt look like it is being stored as a base64 object into my db): https://github.com/duo-labs/py_webauthn/blob/master/flask_demo/app.py

  webauthn_user = webauthn.WebAuthnUser(
    current_user.u2f_key,
    current_user.name,
    current_user.name,
    U2F_ICON,
    current_user.credential_id,
    current_user.pub_key,
    current_user.sign_count, 
    current_user.rp_id)

  webauthn_assertion_response = webauthn.WebAuthnAssertionResponse(
    webauthn_user,
    assertion,
    challenge,
    U2F_RELAYING_ORIGIN,
    uv_required=False)

  sign_count = webauthn_assertion_response.verify()

Thanks! Any options you can suggest would be great.

haydenth commented 5 years ago

My user.pub_key looks something like this, which is why I suspect it's complaining about incorrect padding. I'm not quite sure what it IS looking for, though. I tried converting it to a base64 object myself with no luck.


\x70514543417959674153465949416247424164665362543636337057434346314a63486c6e6c556b434a646d6e714b3854744b785a626175496c6767467668537937517a50413175692d3556495a725034716c34364c563731634f67353848436e326c5549596b```
haydenth commented 5 years ago

One thing, looks like when saving the key I need to make sure to dump out its string representation to the database

  uc.pub_key = str(webauthn_credential.public_key, 'utf-8')

Will submit a pull request to the demo app

futureimperfect commented 5 years ago

Fixed in #50. Thanks @haydenth!