Created
January 18, 2021 14:37
-
-
Save stefan2904/7938f540ab0e2bc6f94ab86c78300d12 to your computer and use it in GitHub Desktop.
U2F Host Demo (in Python)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from u2flib_host import u2f, exc | |
from u2flib_host.utils import websafe_encode, websafe_decode | |
from u2flib_host.register import register | |
from u2flib_host.authenticate import authenticate | |
import json | |
import struct | |
import base64 | |
# Using https://github.com/Yubico/python-u2flib-host | |
# See also: https://webauthn.guide/#webauthn-api | |
VERSION = 'U2F_V2' | |
FACET = 'https://example.com' | |
CHALLENGE = 'challenge_from_website' | |
KEY_HANDLE = websafe_encode(b'\0' * 64) | |
REG_DATA = json.dumps({ | |
'version': VERSION, | |
'challenge': CHALLENGE, | |
'appId': FACET | |
}) | |
def slog(prefix, txt): | |
print() | |
print('### {}:'.format(prefix)) | |
print(txt) | |
print() | |
# Enumerate available devices | |
devices = u2f.list_devices() | |
for device in devices: | |
slog('device', device.path) | |
# The with block ensures that the device is opened and closed. | |
with device as dev: | |
slog('Step 1.1', 'register the device with some service (= navigator.credentials.create)') | |
registrationResponse = register([dev], REG_DATA, FACET) | |
slog('registrationResponse', registrationResponse) | |
slog('Step 1.2', 'parse registrationData (= attestationObject) to extract key handle') | |
# OR: receive AUTH_DATA from server | |
response = registrationResponse['registrationData'] | |
response = websafe_decode(response) | |
pub_key, key_handle_len, key_handle, cert, signature = struct.unpack('x 65s B 64s %is 32s' % (len(response)-(1+65+1+64+32),), response) | |
# Step 1.3: Verify signature, store key, handle, etc into database | |
# OR: Send Data to Server | |
AUTH_DATA = json.dumps({ | |
'version': VERSION, | |
'challenge': CHALLENGE, | |
'appId': FACET, | |
'keyHandle': websafe_encode(key_handle) | |
}) | |
slog('Step 2', 'now authenticate with the same device (= navigator.credentials.get)') | |
authenticationResponse = authenticate([dev], AUTH_DATA, FACET, False) | |
slog('authenticationResponse', authenticationResponse) | |
# Step 2.2: Verify signature with key from database, login user | |
# → storedCredential.publicKey.verify(signature, signedData); | |
# OR: Send Data to Server |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment