Skip to content

Commit b9e58a3

Browse files
committed
Update asycnssh to use version 2 of the fido2 package
1 parent 1806f5e commit b9e58a3

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

asyncssh/sk.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ def _ctap2_enroll(dev: 'CtapHidDevice', alg: int, application: str,
128128
def _win_enroll(alg: int, application: str, user: str) -> Tuple[bytes, bytes]:
129129
"""Enroll a new security key using Windows WebAuthn API"""
130130

131-
client = WindowsClient(application, verify=_verify_rp_id)
131+
data_collector = DefaultClientDataCollector(origin=application,
132+
verify=_verify_rp_id)
133+
client = WindowsClient(data_collector)
132134

133135
rp = {'id': application, 'name': application}
134136
user_cred = {'id': user.encode('utf-8'), 'name': user}
@@ -137,7 +139,8 @@ def _win_enroll(alg: int, application: str, user: str) -> Tuple[bytes, bytes]:
137139
'pubKeyCredParams': key_params}
138140

139141
result = client.make_credential(options)
140-
cdata = result.attestation_object.auth_data.credential_data
142+
response = result.response
143+
cdata = response.attestation_object.auth_data.credential_data
141144

142145
# pylint: disable=no-member
143146
return _decode_public_key(alg, cdata.public_key), cdata.credential_id
@@ -188,17 +191,20 @@ def _win_sign(data: bytes, application: str,
188191
key_handle: bytes) -> Tuple[int, int, bytes, bytes]:
189192
"""Sign a message with a security key using Windows WebAuthn API"""
190193

191-
client = WindowsClient(application, verify=_verify_rp_id)
194+
data_collector = DefaultClientDataCollector(origin=application,
195+
verify=_verify_rp_id)
196+
client = WindowsClient(data_collector)
192197

193198
creds = [{'type': 'public-key', 'id': key_handle}]
194199
options = {'challenge': data, 'rpId': application,
195200
'allowCredentials': creds}
196201

197202
result = client.get_assertion(options).get_response(0)
198-
auth_data = result.authenticator_data
203+
response = result.response
204+
auth_data = response.authenticator_data
199205

200206
return auth_data.flags, auth_data.counter, \
201-
result.signature, bytes(result.client_data)
207+
response.signature, bytes(response.client_data)
202208

203209

204210
def sk_webauthn_prefix(data: bytes, application: str) -> bytes:
@@ -327,21 +333,16 @@ def sk_get_resident(application: str, user: Optional[str],
327333

328334

329335
try:
330-
from fido2.client import WindowsClient
336+
from fido2.client import DefaultClientDataCollector
331337
from fido2.ctap import CtapError
332338
from fido2.ctap1 import Ctap1, APDU, ApduError
333339
from fido2.ctap2 import Ctap2, ClientPin, PinProtocolV1
334340
from fido2.ctap2 import CredentialManagement
335341
from fido2.hid import CtapHidDevice
336342

337343
sk_available = True
338-
339-
sk_use_webauthn = WindowsClient.is_available() and \
340-
hasattr(ctypes, 'windll') and \
341-
not ctypes.windll.shell32.IsUserAnAdmin()
342344
except (ImportError, OSError, AttributeError): # pragma: no cover
343345
sk_available = False
344-
sk_use_webauthn = False
345346

346347
def _sk_not_available(*args: object, **kwargs: object) -> NoReturn:
347348
"""Report that security key support is unavailable"""
@@ -351,3 +352,13 @@ def _sk_not_available(*args: object, **kwargs: object) -> NoReturn:
351352
sk_enroll = _sk_not_available
352353
sk_sign = _sk_not_available
353354
sk_get_resident = _sk_not_available
355+
356+
try:
357+
from fido2.client.windows import WindowsClient
358+
359+
sk_use_webauthn = WindowsClient.is_available() and \
360+
hasattr(ctypes, 'windll') and \
361+
not ctypes.windll.shell32.IsUserAnAdmin()
362+
except ImportError:
363+
WindowsClient = None
364+
sk_use_webauthn = False

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dynamic = ['version']
3535

3636
[project.optional-dependencies]
3737
bcrypt = ['bcrypt >= 3.1.3']
38-
fido2 = ['fido2 >= 0.9.2, < 2']
38+
fido2 = ['fido2 >= 2']
3939
gssapi = ['gssapi >= 1.2.0']
4040
libnacl = ['libnacl >= 1.4.2']
4141
pkcs11 = ['python-pkcs11 >= 0.7.0']

tests/sk_stub.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ def __init__(self, attestation_object):
9393
self.attestation_object = attestation_object
9494

9595

96+
class _RegistrationResponse:
97+
"""Security key registration response"""
98+
99+
def __init__(self, attestation_response):
100+
self.response = attestation_response
101+
102+
96103
class _AuthenticatorData:
97104
"""Security key authenticator data in aseertion"""
98105

@@ -110,6 +117,13 @@ def __init__(self, client_data, auth_data, signature):
110117
self.signature = signature
111118

112119

120+
class _AuthenticationResponse:
121+
"""Security key authentication response"""
122+
123+
def __init__(self, response):
124+
self.response = response
125+
126+
113127
class _AssertionSelection:
114128
"""Security key assertion response list"""
115129

@@ -261,9 +275,9 @@ def get_assertions(self, application, message_hash, allow_creds, options):
261275
class WindowsClient(_CtapStub):
262276
"""Stub for unit testing U2F security keys via Windows WebAuthn"""
263277

264-
def __init__(self, origin, verify):
265-
self._origin = origin
266-
self._verify = verify
278+
def __init__(self, data_collector):
279+
self._origin = data_collector._origin
280+
self._verify = data_collector._verify
267281

268282
def make_credential(self, options):
269283
"""Make a credential using Windows WebAuthN API"""
@@ -275,8 +289,9 @@ def make_credential(self, options):
275289
public_key, key_handle = self._enroll(alg)
276290

277291
cdata = _CredentialData(alg, public_key, key_handle)
292+
attestation_object = _Credential(_CredentialAuthData(cdata))
278293

279-
return _AttestationResponse(_Credential(_CredentialAuthData(cdata)))
294+
return _RegistrationResponse(_AttestationResponse(attestation_object))
280295

281296
def get_assertion(self, options):
282297
"""Get assertion using Windows WebAuthN API"""
@@ -297,7 +312,8 @@ def get_assertion(self, options):
297312
key_handle, flags)
298313

299314
auth_data = _AuthenticatorData(flags, counter)
300-
assertion = _AssertionResponse(data, auth_data, sig)
315+
response = _AssertionResponse(data, auth_data, sig)
316+
assertion = _AuthenticationResponse(response)
301317

302318
return _AssertionSelection([assertion])
303319

0 commit comments

Comments
 (0)