Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_long_pin(self):
prot = PinProtocolV1(mock.MagicMock())
with self.assertRaises(ValueError):
prot.set_pin("1" * 256)
def test_get_pin_token(self):
prot = PinProtocolV1(mock.MagicMock())
prot.get_shared_secret = mock.Mock(return_value=({}, SHARED))
prot.ctap.client_pin.return_value = {2: TOKEN_ENC}
self.assertEqual(prot.get_pin_token("1234"), TOKEN)
prot.ctap.client_pin.assert_called_once()
self.assertEqual(
prot.ctap.client_pin.call_args[1]["pin_hash_enc"], PIN_HASH_ENC
)
def test_change_pin(self):
prot = PinProtocolV1(mock.MagicMock())
prot.get_shared_secret = mock.Mock(return_value=({}, SHARED))
prot.change_pin("1234", "4321")
prot.ctap.client_pin.assert_called_with(
1,
4,
key_agreement={},
new_pin_enc=a2b_hex(
"4280e14aac4fcbf02dd079985f0c0ffc9ea7d5f9c173fd1a4c843826f7590cb3c2d080c6923e2fe6d7a52c31ea1309d3fcca3dedae8a2ef14b6330cafc79339e" # noqa E501
),
pin_auth=a2b_hex("fb97e92f3724d7c85e001d7f93e6490a"),
pin_hash_enc=a2b_hex("afe8327ce416da8ee3d057589c2ce1a9"),
)
def test_establish_shared_secret(self, patched_generate):
prot = PinProtocolV1(mock.MagicMock())
patched_generate.return_value = ec.derive_private_key(
EC_PRIV, ec.SECP256R1(), default_backend()
)
prot.ctap.client_pin.return_value = {
1: {1: 2, 3: -25, -1: 1, -2: DEV_PUB_X, -3: DEV_PUB_Y}
}
key_agreement, shared = prot.get_shared_secret()
self.assertEqual(shared, SHARED)
self.assertEqual(key_agreement[-2], EC_PUB_X)
self.assertEqual(key_agreement[-3], EC_PUB_Y)
ctap = CTAP2(dev)
info = ctap.get_info()
if not info.options.get("clientPin"):
print("PIN not set for the device!")
sys.exit(1)
if "bioEnroll" not in info.options:
if "userVerificationMgmtPreview" not in info.options: # TODO: Remove later
print("Device does not support bio enrollment!")
sys.exit(1)
# Authenticate with PIN
print("Preparing to enroll a new fingerprint.")
pin = getpass("Please enter PIN: ")
pin_token = PinProtocolV1(ctap).get_pin_token(pin)
bio = FPBioEnrollment(ctap, PinProtocolV1.VERSION, pin_token)
print(bio.enumerate_enrollments())
# Start enrollment
enroller = bio.enroll()
template_id = None
while template_id is None:
print("Press your fingerprint against the sensor now...")
try:
template_id = enroller.capture()
except CaptureError as e:
print(e)
print("Fingerprint registered successfully with ID:", template_id)
ctap = CTAP2(dev)
info = ctap.get_info()
if not info.options.get("clientPin"):
print("PIN not set for the device!")
sys.exit(1)
if "bioEnroll" not in info.options:
if "userVerificationMgmtPreview" not in info.options: # TODO: Remove later
print("Device does not support bio enrollment!")
sys.exit(1)
# Authenticate with PIN
print("Preparing to enroll a new fingerprint.")
pin = getpass("Please enter PIN: ")
pin_token = PinProtocolV1(ctap).get_pin_token(pin)
bio = FPBioEnrollment(ctap, PinProtocolV1.VERSION, pin_token)
print(bio.enumerate_enrollments())
# Start enrollment
enroller = bio.enroll()
template_id = None
while template_id is None:
print("Press your fingerprint against the sensor now...")
try:
template_id = enroller.capture()
except CaptureError as e:
print(e)
print("Fingerprint registered successfully with ID:", template_id)
def get_shared_secret(self):
be = default_backend()
sk = ec.generate_private_key(ec.SECP256R1(), be)
pn = sk.public_key().public_numbers()
key_agreement = {
1: 2,
3: -25, # Per the spec, "although this is NOT the algorithm actually used"
-1: 1,
-2: int2bytes(pn.x, 32),
-3: int2bytes(pn.y, 32),
}
resp = self.ctap.client_pin(
PinProtocolV1.VERSION, PinProtocolV1.CMD.GET_KEY_AGREEMENT
)
pk = resp[PinProtocolV1.RESULT.KEY_AGREEMENT]
x = bytes2int(pk[-2])
y = bytes2int(pk[-3])
pk = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()).public_key(be)
shared_secret = sha256(sk.exchange(ec.ECDH(), pk)) # x-coordinate, 32b
return key_agreement, shared_secret
def __init__(self, device, origin, verify=verify_rp_id):
super(Fido2Client, self).__init__(origin, verify)
self.ctap1_poll_delay = 0.25
try:
self.ctap2 = CTAP2(device)
self.info = self.ctap2.get_info()
if PinProtocolV1.VERSION in self.info.pin_protocols:
self.pin_protocol = PinProtocolV1(self.ctap2)
else:
self.pin_protocol = None
self._do_make_credential = self._ctap2_make_credential
self._do_get_assertion = self._ctap2_get_assertion
except (ValueError, CtapError):
self.ctap1 = CTAP1(device)
self.info = _CTAP1_INFO
self._do_make_credential = self._ctap1_make_credential
self._do_get_assertion = self._ctap1_get_assertion
def get_shared_secret(self):
be = default_backend()
sk = ec.generate_private_key(ec.SECP256R1(), be)
pn = sk.public_key().public_numbers()
key_agreement = {
1: 2,
3: -25, # Per the spec, "although this is NOT the algorithm actually used"
-1: 1,
-2: int2bytes(pn.x, 32),
-3: int2bytes(pn.y, 32),
}
resp = self.ctap.client_pin(
PinProtocolV1.VERSION, PinProtocolV1.CMD.GET_KEY_AGREEMENT
)
pk = resp[PinProtocolV1.RESULT.KEY_AGREEMENT]
x = bytes2int(pk[-2])
y = bytes2int(pk[-3])
pk = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()).public_key(be)
shared_secret = sha256(sk.exchange(ec.ECDH(), pk)) # x-coordinate, 32b
return key_agreement, shared_secret
def __init__(self, device, origin, verify=verify_rp_id):
super(Fido2Client, self).__init__(origin, verify)
self.ctap1_poll_delay = 0.25
try:
self.ctap2 = CTAP2(device)
self.info = self.ctap2.get_info()
if PinProtocolV1.VERSION in self.info.pin_protocols:
self.pin_protocol = PinProtocolV1(self.ctap2)
else:
self.pin_protocol = None
self._do_make_credential = self._ctap2_make_credential
self._do_get_assertion = self._ctap2_get_assertion
except (ValueError, CtapError):
self.ctap1 = CTAP1(device)
self.info = _CTAP1_INFO
self._do_make_credential = self._ctap1_make_credential
self._do_get_assertion = self._ctap1_get_assertion