Skip to content

Instantly share code, notes, and snippets.

@stefan2904
Created January 18, 2021 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stefan2904/7938f540ab0e2bc6f94ab86c78300d12 to your computer and use it in GitHub Desktop.
Save stefan2904/7938f540ab0e2bc6f94ab86c78300d12 to your computer and use it in GitHub Desktop.
U2F Host Demo (in Python)
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