You've already forked fido2-tests
mirror of
https://github.com/trussed-dev/fido2-tests.git
synced 2026-03-11 16:30:32 -07:00
188 lines
4.8 KiB
Python
188 lines
4.8 KiB
Python
import math
|
|
import random
|
|
import secrets
|
|
import sys
|
|
|
|
from fido2.ctap2 import ES256, AttestedCredentialData, PinProtocolV1
|
|
from fido2.utils import hmac_sha256, sha256
|
|
|
|
if 'trezor' in sys.argv:
|
|
from .vendor.trezor.utils import DeviceSelectCredential
|
|
else:
|
|
from .vendor.solo.utils import DeviceSelectCredential
|
|
|
|
name_list = open("data/first-names.txt").readlines()
|
|
|
|
|
|
def shannon_entropy(data):
|
|
s = 0.0
|
|
total = len(data)
|
|
for x in range(0, 256):
|
|
freq = data.count(x)
|
|
p = freq / total
|
|
if p > 0:
|
|
s -= p * math.log2(p)
|
|
return s
|
|
|
|
|
|
def verify(reg, auth, cdh=None):
|
|
credential_data = AttestedCredentialData(reg.auth_data.credential_data)
|
|
if cdh is None:
|
|
cdh = auth.request.cdh
|
|
auth.verify(cdh, credential_data.public_key)
|
|
assert auth.credential["id"] == reg.auth_data.credential_data.credential_id
|
|
|
|
|
|
def generate_rp():
|
|
return {"id": "example.org", "name": "ExampleRP"}
|
|
|
|
|
|
def generate_user():
|
|
|
|
# https://www.w3.org/TR/webauthn/#user-handle
|
|
user_id_length = random.randint(1, 64)
|
|
user_id = secrets.token_bytes(user_id_length)
|
|
|
|
# https://www.w3.org/TR/webauthn/#dictionary-pkcredentialentity
|
|
name = " ".join(random.choice(name_list).strip() for i in range(0, 3))
|
|
icon = "https://www.w3.org/TR/webauthn/"
|
|
display_name = "Displayed " + name
|
|
|
|
return {"id": user_id, "name": name, "icon": icon, "displayName": display_name}
|
|
|
|
|
|
counter = 1
|
|
|
|
def generate_user_maximum():
|
|
"""
|
|
Generate RK with the maximum lengths of the fields, according to the minimal requirements of the FIDO2 spec
|
|
"""
|
|
global counter
|
|
|
|
# https://www.w3.org/TR/webauthn/#user-handle
|
|
user_id_length = 64
|
|
user_id = secrets.token_bytes(user_id_length)
|
|
|
|
# https://www.w3.org/TR/webauthn/#dictionary-pkcredentialentity
|
|
name = " ".join(random.choice(name_list).strip() for i in range(0, 30))
|
|
name = f'{counter}: {name}'
|
|
icon = "https://www.w3.org/TR/webauthn/" + 'A'*128
|
|
display_name = "Displayed " + name
|
|
|
|
name = name[:64]
|
|
display_name = display_name[:64]
|
|
icon = icon[:128]
|
|
|
|
counter += 1
|
|
|
|
return {"id": user_id, "name": name, "icon": icon, "displayName": display_name}
|
|
|
|
|
|
def generate_challenge():
|
|
return secrets.token_bytes(32)
|
|
|
|
|
|
def get_key_params():
|
|
return [{"type": "public-key", "alg": ES256.ALGORITHM}]
|
|
|
|
|
|
def generate_cdh():
|
|
return b"123456789abcdef0123456789abcdef0"
|
|
|
|
|
|
def generate(param):
|
|
if param == "rp":
|
|
return generate_rp()
|
|
if param == "user":
|
|
return generate_user()
|
|
if param == "challenge":
|
|
return generate_challenge()
|
|
if param == "cdh":
|
|
return generate_cdh()
|
|
if param == "key_params":
|
|
return get_key_params()
|
|
if param == "allow_list":
|
|
return []
|
|
if param == "on_keepalive":
|
|
return DeviceSelectCredential(1)
|
|
return None
|
|
|
|
|
|
class Empty:
|
|
pass
|
|
|
|
|
|
class FidoRequest:
|
|
def __init__(self, request=None, **kwargs):
|
|
|
|
if not isinstance(request, FidoRequest) and request is not None:
|
|
request = request.request
|
|
|
|
self.request = request
|
|
|
|
for i in (
|
|
"cdh",
|
|
"key_params",
|
|
"allow_list",
|
|
"challenge",
|
|
"rp",
|
|
"user",
|
|
"pin_protocol",
|
|
"options",
|
|
"appid",
|
|
"exclude_list",
|
|
"extensions",
|
|
"pin_auth",
|
|
"timeout",
|
|
"on_keepalive",
|
|
):
|
|
self.save_attr(i, kwargs.get(i, Empty), request)
|
|
|
|
if isinstance(self.rp, dict) and "id" in self.rp:
|
|
if hasattr(self.rp["id"], "encode"):
|
|
self.appid = sha256(self.rp["id"].encode("utf8"))
|
|
|
|
# self.chal = sha256(self.challenge.encode("utf8"))
|
|
|
|
def save_attr(self, attr, value, request):
|
|
"""
|
|
Will assign attribute from source, in following priority:
|
|
Argument, request object, generated
|
|
"""
|
|
if value != Empty:
|
|
setattr(self, attr, value)
|
|
elif request is not None:
|
|
setattr(self, attr, getattr(request, attr))
|
|
else:
|
|
setattr(self, attr, generate(attr))
|
|
|
|
def toGA(self,):
|
|
return [
|
|
None if not self.rp else self.rp["id"],
|
|
self.cdh,
|
|
self.allow_list,
|
|
self.extensions,
|
|
self.options,
|
|
self.pin_auth,
|
|
self.pin_protocol,
|
|
self.timeout,
|
|
self.on_keepalive,
|
|
]
|
|
|
|
def toMC(self,):
|
|
return [
|
|
self.cdh,
|
|
self.rp,
|
|
self.user,
|
|
self.key_params,
|
|
self.exclude_list,
|
|
self.extensions,
|
|
self.options,
|
|
self.pin_auth,
|
|
self.pin_protocol,
|
|
self.timeout,
|
|
self.on_keepalive,
|
|
]
|
|
|
|
return args + self.get_optional_args()
|