-
Notifications
You must be signed in to change notification settings - Fork 1
/
read.py
114 lines (88 loc) · 3.03 KB
/
read.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
from rich import print
from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client, WindowsClient
from fido2.server import Fido2Server
from getpass import getpass
from fido2.ctap2 import CredentialManagement
import sys
import ctypes
try:
from fido2.pcsc import CtapPcscDevice
except ImportError:
CtapPcscDevice = None
def enumerate_devices():
for dev in CtapHidDevice.list_devices():
yield dev
if CtapPcscDevice:
for dev in CtapPcscDevice.list_devices():
yield dev
use_prompt = False
pin = None
uv = "discouraged"
if WindowsClient.is_available() and not ctypes.windll.shell32.IsUserAnAdmin():
# Use the Windows WebAuthn API if available, and we're not running as admin
client = WindowsClient("https://example.com")
else:
# Locate a device
for dev in enumerate_devices():
print(dev)
client = Fido2Client(dev, "https://example.com")
if client.info.options.get("rk"):
use_prompt = not (CtapPcscDevice and isinstance(dev, CtapPcscDevice))
break
else:
print("No Authenticator with support for resident key found!")
sys.exit(1)
# Prefer UV if supported
if client.info.options.get("uv"):
uv = "preferred"
print("Authenticator supports User Verification")
elif client.info.options.get("clientPin"):
# Prompt for PIN if needed
pin = getpass("Please enter PIN: ")
else:
print("PIN not set, won't use")
server = Fido2Server({"id": "example.com", "name": "Example RP"}, attestation="direct")
user = {"id": b"user_id", "name": "A. User"}
# Prepare parameters for makeCredential
create_options, state = server.register_begin(
user,
resident_key=True,
user_verification=uv,
authenticator_attachment="cross-platform",
)
# Create a credential
if use_prompt:
print("\nTouch your authenticator device now...\n")
result = client.make_credential(create_options["publicKey"], pin=pin)
# Complete registration
auth_data = server.register_complete(
state, result.client_data, result.attestation_object
)
credentials = [auth_data.credential_data]
print("New credential created!")
print("CLIENT DATA:", result.client_data)
print("ATTESTATION OBJECT:", result.attestation_object)
print()
print("CREDENTIAL DATA:", auth_data.credential_data)
# Prepare parameters for getAssertion
request_options, state = server.authenticate_begin(user_verification=uv)
# Authenticate the credential
if use_prompt:
print("\nTouch your authenticator device now...\n")
selection = client.get_assertion(request_options["publicKey"], pin=pin)
result = selection.get_response(0) # There may be multiple responses, get the first.
print("USER ID:", result.user_handle)
# Complete authenticator
server.authenticate_complete(
state,
credentials,
result.credential_id,
result.client_data,
result.authenticator_data,
result.signature,
)
print("Credential authenticated!")
print("CLIENT DATA:", result.client_data)
print()
print("AUTHENTICATOR DATA:", result.authenticator_data)