yubico / python-fido2 Goto Github PK
View Code? Open in Web Editor NEWProvides library functionality for FIDO 2.0, including communication with a device over USB.
License: BSD 2-Clause "Simplified" License
Provides library functionality for FIDO 2.0, including communication with a device over USB.
License: BSD 2-Clause "Simplified" License
Currently, CoseKey (and its subclasses) abstract the entire chain from parsing the public key data to using the public key to verify the signature of an arbitrary message. I can see why this is desirable, as it entirely abstracts RSA versus elliptic curve approaches.
However, it would be nice if the ES256 subclass also supported getting the actual EllipticCurvePublicNumbers object. This would allow me to use methods from the Python Cryptography library to implement an SSH agent that exports FIDO keys (well, more cleanly than my current proof-of-concept work, anyway). Some background: an SSH agent needs to report available ECDSA keys using the SEC 1 v2.0 section 2.3.3 format, which is available via the EllipticCurvePublicNumbers.encode_point() method.
It would also be nice to be able to obtain the RSAPublicNumbers objects as well (for similar reasons).
Hi ๐
In other examples i have seen previously (without python-fido2), the server returns the view containing the webauthn javascript that communicates with the authenticator on the device. (the server does a redirect to a page that it hosts)
Having had a look through the server example here, am i right in thinking that the ctap code is run locally (not hosted from the server)? If the CTAP code is hosted locally, how does the server talk to the client to say that the assertions need to take place
I'm working on a project where I'd like to use fido2 to provide usernameless/passwordless auth, but i don't want to use a webbrowser; all the ctap code would live locally on the device
Many thanks
FYI, OpenBSD switched FIDO devices to a new dedicated driver, see http://man.openbsd.org/fido.4
The reason is that we want to restrict access to uhid devices and to stop relying on ioctls (for sandboxes/pledge(2)) just to open a read/write device. See the related libfido2 changes:
Cycle through cbor encoding doesn't return the original value. I'd expect
from fido2 import cbor
a = 42
a == cbor.loads(cbor.dumps(a))
to be true, but it isn't, because loads
returns a tuple of two. I'd suggest to modify loads
to return only decoded value and provide other function for cases where needed (ctap2
module).
Regarding Yubico email that was sent yesterday to developers 'Developers implementing FIDO U2F, update to Chrome coming in v 72', Is the library affected by this and needs a fix, or it is safe with Chrome v72+?
Thanks
According to https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html the COSE_Key-encoded public key MUST contain the optional "alg" parameter. However, the key agreement public key returned by PinProtocolV1::get_shared_secret() is missing the "alg" parameter, see
Lines 802 to 807 in 1021538
I am trying to install yubikey-manager
on macos (10.14.6), but building wheel for uhid-freebsd
is failing. Somehow it is not skipped for this platform.
> pip install yubikey-manager
Collecting yubikey-manager
Requirement already satisfied: click in ./env/lib/python3.5/site-packages (from yubikey-manager) (6.7)
Collecting fido2>=0.7 (from yubikey-manager)
Requirement already satisfied: cryptography in ./env/lib/python3.5/site-packages (from yubikey-manager) (2.7)
Requirement already satisfied: pyscard in ./env/lib/python3.5/site-packages (from yubikey-manager) (1.9.9)
Requirement already satisfied: six in ./env/lib/python3.5/site-packages (from yubikey-manager) (1.12.0)
Requirement already satisfied: pyusb in ./env/lib/python3.5/site-packages (from yubikey-manager) (1.0.2)
Requirement already satisfied: pyopenssl in ./env/lib/python3.5/site-packages (from yubikey-manager) (19.0.0)
Collecting uhid-freebsd>=1.2.1 (from fido2>=0.7->yubikey-manager)
Using cached https://files.pythonhosted.org/packages/55/c8/aee05809c37437b5aeca56608e9b12c368a97cdd1be017642e3a8f1ecd88/uhid-freebsd-1.2.1.tar.gz
Requirement already satisfied: asn1crypto>=0.21.0 in ./env/lib/python3.5/site-packages (from cryptography->yubikey-manager) (0.24.0)
Requirement already satisfied: cffi!=1.11.3,>=1.8 in ./env/lib/python3.5/site-packages (from cryptography->yubikey-manager) (1.12.3)
Requirement already satisfied: pycparser in ./env/lib/python3.5/site-packages (from cffi!=1.11.3,>=1.8->cryptography->yubikey-manager) (2.19)
Building wheels for collected packages: uhid-freebsd
Building wheel for uhid-freebsd (setup.py) ... error
ERROR: Command errored out with exit status 1:
command: /Users/daniel/code/oll/taf/env/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"'; __file__='"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-wheel-k5az3543 --python-tag cp35
cwd: /private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/
Complete output (12 lines):
running bdist_wheel
running build
running build_ext
building 'uhid_freebsd' extension
creating build
creating build/temp.macosx-10.14-x86_64-3.5
clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/daniel/.pyenv/versions/3.5.6/include/python3.5m -c uhid_freebsd.cpp -o build/temp.macosx-10.14-x86_64-3.5/uhid_freebsd.o
uhid_freebsd.cpp:15:10: fatal error: 'dev/usb/usb_ioctl.h' file not found
#include <dev/usb/usb_ioctl.h>
^~~~~~~~~~~~~~~~~~~~~
1 error generated.
error: command 'clang' failed with exit status 1
----------------------------------------
ERROR: Failed building wheel for uhid-freebsd
Running setup.py clean for uhid-freebsd
Failed to build uhid-freebsd
Installing collected packages: uhid-freebsd, fido2, yubikey-manager
Running setup.py install for uhid-freebsd ... error
ERROR: Command errored out with exit status 1:
command: /Users/daniel/code/oll/taf/env/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"'; __file__='"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-record-ocgvl2a5/install-record.txt --single-version-externally-managed --compile --install-headers /Users/daniel/code/oll/taf/env/include/site/python3.5/uhid-freebsd
cwd: /private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/
Complete output (12 lines):
running install
running build
running build_ext
building 'uhid_freebsd' extension
creating build
creating build/temp.macosx-10.14-x86_64-3.5
clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/daniel/.pyenv/versions/3.5.6/include/python3.5m -c uhid_freebsd.cpp -o build/temp.macosx-10.14-x86_64-3.5/uhid_freebsd.o
uhid_freebsd.cpp:15:10: fatal error: 'dev/usb/usb_ioctl.h' file not found
#include <dev/usb/usb_ioctl.h>
^~~~~~~~~~~~~~~~~~~~~
1 error generated.
error: command 'clang' failed with exit status 1
----------------------------------------
ERROR: Command errored out with exit status 1: /Users/daniel/code/oll/taf/env/bin/python -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"'; __file__='"'"'/private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-install-vfbfeayn/uhid-freebsd/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/lc/c_lvyn5x6cbd12ysjly61qcr0000gn/T/pip-record-ocgvl2a5/install-record.txt --single-version-externally-managed --compile --install-headers /Users/daniel/code/oll/taf/env/include/site/python3.5/uhid-freebsd Check the logs for full command output
WebAuthn is in the news these days. It seems there is a relationship between WebAuthn and FIDO2 and this code, and clarifying that in the README etc would be helpful.
Which attribute holds an authenticator unique identifier to make sure that the authenticator is NOT used by another user?
In U2F, we used to check the X509 certificate.
Thanks in advance
I'm trying to get resident keys to work with the example server. I can get resident keys to work with webauthn.me but not with the example server using a YubiKey 5 NFC. I am modifying the register_begin call to pass resident_key=True
@app.route("/api/register/begin", methods=["POST"])
def register_begin():
registration_data, state = server.register_begin(
{
"id": b"user_id",
"name": "a_user",
"displayName": "A. User",
"icon": "https://example.com/image.png",
},
credentials,
resident_key=True,
user_verification="discouraged",
)
and it does look like Chrome sees the resident key request by saying:
"A record of your visit to this site will be kept on your security key."
but I do not see a userHandle in the authentication response:
@app.route("/api/authenticate/complete", methods=["POST"])
def authenticate_complete():
if not credentials:
abort(404)
data = cbor.decode(request.get_data())
print("authenticate finish data:", data)
authenticate finish data: {u'credentialId': "\x17\xfbZ{\xa5\xbcB\x12\xa5\xe3\xd3'\xd7\x97\xb0\xac", u'clientDataJSON': '{"challenge":"sbtMTP_IGixS4-Ur6uNhxqpty3jfsIKN8nDzWOu_Eeg","origin":"https://localhost:10000","type":"webauthn.get"}', u'authenticatorData': 'I\x96\r\xe5\x88\x0e\x8cht4\x17\x0fdv`[\x8f\xe4\xae\xb9\xa2\x862\xc7\x99\\xf3\xba\x83\x1d\x97c\x05\x00\x00\x00\t', u'signature': '0E\x02 \x16)\xc8\x1d\x82\xac\x14\xcd\xe0\x8c\xb3\xe2s\xb2\xc1GN\x17u\t\x81R"\x96\xc7?\xbb\x8b\x10\xfa\x9c\xdd\x02!\x00\xc2\xdb\xea\x84yP\xe9\x9c\x87\x9a5\xc9G\x9fR\xd5\\x97\x97\xf7\xd1\xe5\xaa\x80\xb0>4/3\xef0\xf4'}
Am I doing something wrong?
UPDATE: I found it, had to add "userHandle" to authenticate.html:
body: CBOR.encode({
"credentialId": new Uint8Array(assertion.rawId),
"authenticatorData": new Uint8Array(assertion.response.authenticatorData),
"clientDataJSON": new Uint8Array(assertion.response.clientDataJSON),
"userHandle": new Uint8Array(assertion.response.userHandle),
"signature": new Uint8Array(assertion.response.signature)
})
How about creating ClientData from a dict, and having a from_json
to decode from a str?
Line 45 in 492eac9
(In my case, for example, the api layer already takes care about json decoding)
The following code from fido2/hid.py assumes that successful CTAPHID responses will have the same command field as the initial request.
def call(self, cmd, data=b'', event=None, on_keepalive=None):
event = event or Event()
self._dev.InternalSend(TYPE_INIT | cmd, bytearray(data))
last_ka = None
while not event.is_set():
status, resp = self._dev.InternalRecv()
status ^= TYPE_INIT
if status == cmd:
return bytes(resp)
elif status == CTAPHID.ERROR:
raise CtapError(resp[0])
elif status == CTAPHID.KEEPALIVE:
ka_status = resp[0]
if on_keepalive and last_ka != ka_status:
try:
ka_status = STATUS(ka_status)
except ValueError:
pass # Unknown status value
last_ka = ka_status
on_keepalive(ka_status)
continue
else:
raise CtapError(CtapError.ERR.INVALID_COMMAND)
self.call(CTAPHID.CANCEL, b'', _SingleEvent())
raise CtapError(CtapError.ERR.KEEPALIVE_CANCEL)
In the CTAP spec, for HID CBOR requests, it says the response should use CTAPHID_MSG in the command field (rather than CTAPHID_CBOR). Is this a mistake in the spec?
Recent changes in example endpoint register_begin require two values returning from server.register_begin
but just one is coming in 0.4.0, leading to:
File "/server/server.py", line 73, in register_begin
}, credentials)
ValueError: not enough values to unpack (expected 2, got 1)
Follow-up from issue #75:
I was able to get resident keys to work with 0.8.1, thanks! In order to get it to work, I had to delete 'allowCredentials' from public_key (it was an empty list) before calling client.get_assertion.
I have the following code in place but it doesn't seem ideal:
if not public_key['allowCredentials']:
del public_key['allowCredentials']
Otherwise it works!
Thanks,
Patrick
I apologize as this is likely an issue in my code, and not the repo- but I have tried this for days to no avail, and the lack of documentation is exacerbating my confusion.
I am running a local https server and testing FIDO2 keys. I generate a key like this:
registration_data, state = server.register_begin({
u'id': '1',
u'name': 'my user',
u'displayName': 'my user',
}, credentials)
request.session['fido2_state'] = state
# generate pubkey to pass to front end credential
publicKey = {
'challenge': websafe_encode(registration_data['publicKey']['challenge']),
'rp': {
'name':'Example Inc.',
'id': 'localhost',
},
'user': {
'id': 1,
'name': '[email protected]',
'displayName': 'Alice von Wunderland'
},
'pubKeyCredParams': [
{ 'type': 'public-key', 'alg': -7 },
{ 'type': 'public-key', 'alg': -257 }
]
}
return render(request, self.template_name, {'registration_data': publicKey})
And in the front end:
//Get response from server and convert values to array buffer
publicKey = {{ registration_data | safe }}
challenge = publicKey['challenge']
user_id = publicKey['user']['id']
publicKey['challenge'] = str2ab(challenge)
publicKey['user']['id'] = str2ab(user_id)
navigator.credentials.create({ 'publicKey': publicKey }) .then(function(attestation) {
return fetch('/fido/', {
method: 'POST',
credentials: 'same-origin',
headers: {'Content-Type': 'application/cbor'},
body: CBOR.encode({
"attestationObject": new Uint8Array(attestation.response.attestationObject),
"clientDataJSON": new Uint8Array(attestation.response.clientDataJSON),
});
});
});
Once it's posted to server, I get the data from the request and try to verify
# verify response from server
data = cbor.loads(request.body)[0]
client_data = ClientData(data['clientDataJSON'])
att_obj = AttestationObject(data['attestationObject'])
state = request.session['fido2_state']
auth_data = server.register_complete(
state,
client_data,
att_obj
)
This consistently returns
File "/usr/local/lib/python2.7/dist-packages/fido2/server.py", line 180, in register_complete
raise ValueError('Wrong challenge in response.')
I am completely lost. I have tried the few examples I have found online. However I truly have no idea how to proceed. My guess is my encoding of the challenge in the original registration challenge generation is incorrect, but I'm not sure what to do. I have tried encoding this in a variety of ways, completely unsuccessfully.
I would appreciate any hints here. If this is too far out of the scope for these issues, I apologize and will close it out.
Hi,
Do you think that getting the FIDO conformance certification will be beneficial for the library?
https://fidoalliance.org/certification/functional-certification/conformance/
Jwkmw
perhaps this isnt a concern at all, but on alpine latest and some pinned versions, as of 0.7.2, this four-line docker file is no longer happy:
docker build -f Dockerfile-FidoNotBestFriendRightNow .
Sending build context to Docker daemon 15.36kB
Step 1/4 : FROM alpine:latest
latest: Pulling from library/alpine
89d9c30c1d48: Already exists
Digest: sha256:c19173c5ada610a5989151111163d28a67368362762534d8a8121ce95cf2bd5a
Status: Downloaded newer image for alpine:latest
---> 965ea09ff2eb
Step 2/4 : RUN apk --update add py-pip
---> Running in 9333bbd464a3
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.10/community/x86_64/APKINDEX.tar.gz
(1/12) Installing libbz2 (1.0.6-r7)
(2/12) Installing expat (2.2.8-r0)
(3/12) Installing libffi (3.2.1-r6)
(4/12) Installing gdbm (1.13-r1)
(5/12) Installing ncurses-terminfo-base (6.1_p20190518-r0)
(6/12) Installing ncurses-terminfo (6.1_p20190518-r0)
(7/12) Installing ncurses-libs (6.1_p20190518-r0)
(8/12) Installing readline (8.0.0-r0)
(9/12) Installing sqlite-libs (3.28.0-r1)
(10/12) Installing python2 (2.7.16-r1)
(11/12) Installing py-setuptools (40.8.0-r1)
(12/12) Installing py2-pip (18.1-r0)
Executing busybox-1.30.1-r2.trigger
OK: 65 MiB in 26 packages
Removing intermediate container 9333bbd464a3
---> e9a5a9b7c953
Step 3/4 : RUN pip install --upgrade pip
---> Running in aad56e921bdf
Collecting pip
Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB)
Installing collected packages: pip
Found existing installation: pip 18.1
Uninstalling pip-18.1:
Successfully uninstalled pip-18.1
Successfully installed pip-19.3.1
Removing intermediate container aad56e921bdf
---> deaa4a1558ca
Step 4/4 : RUN pip install 'fido2<=0.7.2'
---> Running in c462207ee2c8
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting fido2<=0.7.2
Downloading https://files.pythonhosted.org/packages/97/2b/dd7ecc8838881ec1f68b1d581821933d54d7ed8f3ef16874ebf2ed277e2b/fido2-0.7.2.tar.gz (188kB)
ERROR: Command errored out with exit status 1:
command: /usr/bin/python2 -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-EYkTQ9/fido2/setup.py'"'"'; __file__='"'"'/tmp/pip-install-EYkTQ9/fido2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-EYkTQ9/fido2/pip-egg-info
cwd: /tmp/pip-install-EYkTQ9/fido2/
Complete output (9 lines):
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/tmp/pip-install-EYkTQ9/fido2/setup.py", line 33, in <module>
if StrictVersion(__version__) < StrictVersion("20.2"):
File "/usr/lib/python2.7/distutils/version.py", line 40, in __init__
self.parse(vstring)
File "/usr/lib/python2.7/distutils/version.py", line 107, in parse
raise ValueError, "invalid version number '%s'" % vstring
ValueError: invalid version number '40.8.0.post20190503'
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
The command '/bin/sh -c pip install 'fido2<=0.7.2'' returned a non-zero code: 1
~/local/dockerfiles
I'm running into an issue where my Yubikey 5 NFC becomes unusable after a some time (typically fine after a reboot, but then this issue comes back after a couple of days). Doesn't seem specific to older or newer library versions (had this same issue in the 0.7.x versions on a ubuntu 19.04 system, and I'm seeing it still with a fresh ykman install on a ubuntu 19.10 system)
The exact output looks like:
troyready@notebook:~$ .local/bin/ykman fido list
Traceback (most recent call last):
File ".local/bin/ykman", line 8, in <module>
sys.exit(main())
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/__main__.py", line 273, in main
cli(obj={})
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 717, in main
rv = self.invoke(ctx)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/core.py", line 555, in invoke
return callback(*args, **kwargs)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/click/decorators.py", line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/fido.py", line 112, in list_creds
controller = ctx.obj['controller']
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/util.py", line 127, in __getitem__
self.resolve()
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/util.py", line 124, in resolve
self._objects[k] = f()
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/__main__.py", line 194, in resolve_device
dev = _run_cmd_for_single(ctx, subcmd.name, transports, reader)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/cli/__main__.py", line 132, in _run_cmd_for_single
return descriptor.open_device(transports)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/descriptor.py", line 96, in open_device
for drv in _list_drivers(transports):
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/descriptor.py", line 164, in _list_drivers
for dev in open_fido():
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/ykman/driver_fido.py", line 97, in open_devices
for dev in CtapHidDevice.list_devices(descriptor_filter):
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/fido2/hid.py", line 135, in list_devices
for d in hidtransport.hid.Enumerate():
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/fido2/_pyu2f/linux.py", line 193, in Enumerate
ParseReportDescriptor(rd_file.read(), desc)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/fido2/_pyu2f/linux.py", line 149, in ParseReportDescriptor
usage_page = ReadLsbBytes(rd, pos + 1, value_length)
File "/home/troyready/.local/venvs/yubikey-manager/lib/python3.7/site-packages/fido2/_pyu2f/linux.py", line 86, in ReadLsbBytes
raise OSError('Invalid value size specified')
OSError: Invalid value size specified
If I add a debug print line to that ReadLsbBytes function, it's a bunch of 1s, a few 2s, and then a 0 causes that ^ exception.
Not sure if there's some method of resetting or troubleshooting I can provide, but would love to help.
Documentation and docstrings would certainly help to understand the code.
After update to Windows 10 1903 yubikey devices are no longer listed and consequently python-fido2 cannot be used
In recent beta releases of iOS14, Apple started to provide attestation during WebAuthn registration process. However, this attestation is of the type "apple" that is unknown to python-fido2. It would be great if library could support also this new format. This format is not registered in https://www.iana.org/assignments/webauthn/webauthn.xhtml#webauthn-attestation-statement-format-ids and I cannot find anything about it publicly.
I couldn't re-open #71 so creating a new issue here. I couldn't get it to work with 0.7.3.
Is it possible to have a new release to capture the new authenticatorAttachment option?
As mentioned, this is running on Windows 1809. Upon importing fido2.client
, the below error is raised.
File "c:\users\containeradministrator\.virtualenvs\data-nggunt9q\lib\site-packages\fido2\client.py", line 44, in <module>
from .win_api import (
File "c:\users\containeradministrator\.virtualenvs\data-nggunt9q\lib\site-packages\fido2\win_api.py", line 531, in <module>
WEBAUTHN_API_VERSION = WEBAUTHN.WebAuthNGetApiVersionNumber()
File "c:\python38\Lib\ctypes\__init__.py", line 386, in __getattr__
func = self.__getitem__(name)
File "c:\python38\Lib\ctypes\__init__.py", line 391, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'WebAuthNGetApiVersionNumber' not found
I propose either handing the error in the library so that other aspects can be used on older versions of windows or raise a more meaningful error to be handled app side.
If you comment out this from setup.py:
extras_require={
':python_version < "3.4"': ['enum34']
},
it works again. Error is:
Downloading https://files.pythonhosted.org/packages/58/0d/655ef526ab14b8eecc70f773294f15b23402d5184da290c4f23d5d893048/fido2-0.4.0.tar.gz (141kB)
100% |โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ| 143kB 6.6MB/s
Complete output from command python setup.py egg_info:
/usr/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'python_requires'
warnings.warn(msg)
error in fido2 setup command: Invalid environment marker: python_version < "3.4"
Hello,
I am trying to run server.py:
server = Fido2Server(rp, user_verification=USER_VERIFICATION.PREFERED) works fine.
server = Fido2Server(rp, user_verification=USER_VERIFICATION.REQUIRED) no prompt from browser or os..
Is the field decoded in cbor.js or its not implemented ?
Thank you
I'm building this package in our build system. Versions up until 0.5.0 were working fine, but with the latest 0.6.0 release, one test case is failing:
======================================================================
[ 67s] FAIL: test_EdDSA_parse_verify (test.test_cose.TestCoseKey)
[ 67s] ----------------------------------------------------------------------
[ 67s] Traceback (most recent call last):
[ 67s] File "/home/abuild/rpmbuild/BUILD/fido2-0.6.0/test/test_cose.py", line 84, in test_EdDSA_parse_verify
[ 67s] self.assertIsInstance(key, EdDSA)
[ 67s] AssertionError: {1: 1, 3: -8, -1: 6, -2: '\xee\x9b!\x804\x05\xd3\xcfE`\x1eX\xb6\xf4\xc0n\xa98b\xde\x87\xd3\xaf\x90<Xp\xa5\x01n\x86\xf5'} is not an instance of <class 'fido2.cose.EdDSA'>
Not sure what is at fault here (library version, etc.). The full build log can be found here.
On another distribution (openSUSE Factory / Tumbleweed) this works just fine, but libraries versions are newer, etc.: https://build.opensuse.org/package/live_build_log/openSUSE:Factory/python-fido2/standard/x86_64
Please let me know what additional information you need.
I trying to integrating this repo with Django 1.8 on Python 2.7 and I getting this strange in object loaded in JS
view.py
registration_data, state = server.register_begin({
'id': request.user.username,
'name': request.user.first_name + " " + request.user.last_name,
'displayName': request.user.username,
'icon': settings.STATIC_URL + "img/favicon.ico"
}, [])
return HttpResponse(cbor.dumps(registration_data),content_type='application/octet-stream')
JS Object received from begin_registeration
The problem that user dict keys are represented in binary so the navigator.credentials.create() fails as no username is provided.
For version 0.3.0 we have signed source tarball on release page. Can we have that for version 0.4.0 as well? Thanks!
Hi all,
Not sure if this is a known/solved issue, but my Google Titan USB keys are not being recognized when using the list_devices()
options when trying to check ctap
or hid
. Am I missing something simple here, or is this simply not supported?
When I was trying to debug and go through each device, none of the page information matched 0xF1D0
.
Edit: Additional info:
Both USB A and USB c keys are not being recognized on Windows 10 using both front-panel IO and back-panel IO. They are, however, recognized inside of device manager as fido compliant devices.
Thanks in advance
When i execute the credential.py example i always get the following error AttributeError: 'AttestationObject' object has no attribute 'verify'
Making me believe AttestationObject doesn't have a verify method please either make a verify method or fix the example.
Kind regards.
Lars
Dear All,
With iOS 13.3, users can use Security Keys (USB, NFC, Bluetooth) on Safari, and i tested it using Yubico 5Ci and it worked like charm using this library
How can we serialize the auth_data.credential_data to store as JSON in the user's profile?
Answer as Py2 and Py3 will be appreciated
currently playing around a bit and tried few of the example scripts on a GoTrust Idem Card
https://www.gotrustid.com/idem-card
and well upon running get_info.py the script immediately dies due to the CBOR not being canonical
my1@my1-qb:~$ python3 python-fido2/examples/get_info.py
CONNECT: CtapPcscDevice(REINER SCT cyberJack RFID basis 00 00)
CTAPHID protocol version: 2
Traceback (most recent call last):
File "python-fido2/examples/get_info.py", line 58, in <module>
info = ctap2.get_info()
File "/home/my1/.local/lib/python3.6/site-packages/fido2/ctap2.py", line 755, in get_info
return self.send_cbor(CTAP2.CMD.GET_INFO, parse=Info)
File "/home/my1/.local/lib/python3.6/site-packages/fido2/ctap2.py", line 656, in send_cbor
"Got: {}\n".format(enc_h) + "Expected: {}".format(exp_h)
ValueError: Non-canonical CBOR from Authenticator.
Got: b'a60182684649444f5f325f30665532465f563202816b686d61632d73656372657403509f0d8150baa54c009299ad62c8bb4e8704a464706c6174f462726bf569636c69656e7450696ef5627570f505190400068101'
Expected: b'a60182684649444f5f325f30665532465f563202816b686d61632d73656372657403509f0d8150baa54c009299ad62c8bb4e8704a462726bf5627570f564706c6174f469636c69656e7450696ef505190400068101'
considering there are actual authenticators flying around that dont nesecarily run canonical and unsurprisigly cannot be updated (a bad trend Yubico as far as I can see started as one of the first well known FIDO devices), it would kinda break stuff if canonical is enforced.
for now all of the other CTAP2 capable devices I am currently possessing which are
do NOT seem to have this problem U2F devices as far as the script says dont even do CBOR so they are out all the way
my1@my1-qb:~$ python3 python-fido2/examples/get_info.py
CONNECT: CtapHidDevice(/dev/hidraw0)
CTAPHID protocol version: 2
Device does not support CBOR
WINK sent!
When I try to run the command pipenv run server
in the server directory, I get this error message:
Traceback (most recent call last):
File "/usr/bin/pipenv", line 11, in <module>
load_entry_point('pipenv==11.9.0', 'console_scripts', 'pipenv')()
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 722, in _call_
return self.main(*args, **kwargs)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/lib/python3/dist-packages/pipenv/vendor/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/lib/python3/dist-packages/pipenv/cli.py", line 602, in run
core.do_run(command=command, args=args, three=three, python=python)
File "/usr/lib/python3/dist-packages/pipenv/core.py", line 2200, in do_run
command = ' '.join(project.scripts[command])
File "/usr/lib/python3/dist-packages/pipenv/project.py", line 374, in scripts
scripts[k] = shlex.split(v, posix=True)
File "/usr/lib/python3.7/shlex.py", line 305, in split
return list(lex)
File "/usr/lib/python3.7/shlex.py", line 295, in _next_
token = self.get_token()
File "/usr/lib/python3.7/shlex.py", line 105, in get_token
raw = self.read_token()
File "/usr/lib/python3.7/shlex.py", line 136, in read_token
nextchar = self.instream.read(1)
AttributeError: 'list' object has no attribute 'read'
Version 0.5.0
Environment: RHEL 7, Python 2.7.5
Traceback:
att_obj = AttestationObject(data['attestationObject'])
File 'venv/lib/python2.7/site-packages/fido2/ctap2.py', line 372 in __init__
self.auth_data = AuthenticatorData(data[AttestationObject.KEY.AUTH_DATA]
File 'venv/lib/python2.7/site-packages/fido2/ctap2.py', line 240 in __init__
self.counter = struct.unpack('>I', self[33:33+4])[0]
TypeError: Struct() argument 1 must be string, not unicode
The problem stems from limitations of the built-in struct module in the Python 2.7.5 version.
Recommend warning users about earlier versions of Python 2.7. I can report that Python 2.7.6 on Ubuntu Trusty does not exhibit this problem.
The last release v0.8.1 for fido2 was on November 25 2019. There have been a number of awesome fixes since then. For example, v0.8.1 has a segfault when enumerating HID devices on MacOS Big Sur which is all ready fixed by the new HID cleanup in a862fda.
Would it be possible to publish an interim release to PyPI so that the fixes can be picked up downstream. At the moment, the only way to consume it is as an egg from this repo, i.e:
pip install git+https://github.com/Yubico/python-fido2@507818c95ed84f543511455bc7fef646801f1cd8#egg=fido2
Do you have interest to make this library compatible with NFC u2f/fido2 channel via pyscard ?
To easily check if the library works under different version of python, tox would be of a great help.
I encountered this issue while trying to install gimme-aws-creds on Xubuntu 16.04. It pulls in fido2 which triggered the attempted installation of uhid-freebsd.
Installing the prior version of fido2 avoids the issue and unblocked me. However, it is unclear why this FreeBSD package was getting pulled into a LInux installation.
Python 2.7 had been End-of-Lifed since January 1st, 2020. https://www.python.org/doc/sunset-python-2/
I recommend dropping support for Python 2.7 and also making Python 3.6 the minimum required version.
The reason for Python 3.6 as a minimum version is that it supports type-hints and also f-strings. Both features are useful.
Currently, there is only fido-u2f, android-safetynet and packet attestation implemented.
With the release of Windows 1903, Windows Hello can be used as a WebAuthn device, which is supported with Chrome, Edge and I think also Firefox.
Implementing the attestation for tpm modules, fido2 could be brought to more users.
The CBOR value for the FMT key is 0x1 in ctap2.py:
Line 337 in 2860264
But in the official spec, the value is 0x2:
Is this a bug?
The CTAPHID_CANCEL command MAY be sent by the client during ongoing processing of a CTAPHID_CBOR request. The CTAP2_ERR_KEEPALIVE_CANCEL response MUST be the response to that request, not an error response in the HID transport.
Thus if the client sends a CTAPHID_CANCEL command to cancel an outstanding CTAPHID_CBOR request, then the authenticator must respond with "9000012d". However, when this happens, CtapHidDevice::Call() incorrectly interprets this response as an invalid command, raising CtapError(CtapError.ERR.INVALID_COMMAND) instead of CtapError(CtapError.ERR.KEEPALIVE_CANCEL).
Line 106 in cacc0c4
examples/server/server.py is not working.
The following error occurred in register phase.
127.0.0.1 - - [14/Jul/2018 18:18:24] "POST /api/register/complete HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/prprhyt/gitdir/python-fido2/examples/server/server.py", line 94, in register_complete
session['challenge'], client_data, att_obj)
File "/Users/prprhyt/.pyenv/versions/3.5.2/lib/python3.5/site-packages/werkzeug/local.py", line 377, in <lambda>
__getitem__ = lambda x, i: x._get_current_object()[i]
KeyError: 'challenge'
Hi,
This isn't a bug, this is info that Touch ID on Macbook using Chrome 70 is working fine and it is recognized as 'packed'
I believe the API exposed by Fido2Client
can be improved. Let's say I have a security key which supports CTAP2 and have a PIN configured. Right now there is no easy way to check if there is PIN set before calling make_credential
or get_assertion
. Calling a method and catching ValueError
as shown in examples/credential.py
leads to bad user experience. When I run credential.py
it first asks to touch the device and then asks for PIN which is incorrect and confusing.
I see there is a ctap2
member in Fido2Client
but it's not always set because the client can fallback to CTAP1. So I have to either to check for this or explicitly create a CTAP2
object.
Maybe consider to always expose ctap2
member which is None
in case of CTAP1. Or directly provide methods for manipulating CTAP2 info?
Annotations would help a lot. Any chance they we can see them soon?
I am trying to build a thick client application for windows which will do Fido2 2FA against an [IdP](https://en.wikipedia.org/wiki/Identity_provider#:~:text=An%20identity%20provider%20(abbreviated%20IdP,user%20authentication%20as%20a%20service.)
Now when I do an primary authentication call using username and password I get a challenge and credential id in a JSON response and then I am trying to pass them to Yubikey 5 NFC to get signed assertion but I am getting below error.
Here is the code snippet.
def create_client():
client = WindowsClient("https://IdPUrl.com")
return client
def assertion(initiated_response):
#Parsing the received JSON response for Cred_ID and Challenge
credential_id = initiated_response['credentialId']
challenge = initiated_response['challenge']
allow_list = [{"type": "public-key", "id":
bytes(credential_id, 'utf-8')
}]
clientdev = create_client()
# Authenticate the credential
result = clientdev.get_assertion(
{
"rpId": "IdPUrl.com",
"challenge": bytes(challenge, 'utf-8'),
"allowCredentials": allow_list
},
pin=pin,
).get_response(
0
)
Can you help me me point out where I am going wrong!!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.