mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-14 03:59:30 +00:00
107 lines
3.1 KiB
Python
107 lines
3.1 KiB
Python
import sys
|
|
import pytest
|
|
import hashlib
|
|
|
|
from unittest.mock import patch
|
|
|
|
from keycard.constants import INS_PAIR, PairingMode
|
|
from keycard.commands.pair import pair
|
|
from keycard.exceptions import APDUError, InvalidResponseError
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_urandom():
|
|
pair_module = sys.modules['keycard.commands.pair']
|
|
with patch.object(pair_module, 'urandom', return_value=b'\x01' * 32):
|
|
yield
|
|
|
|
|
|
def test_pair_success(card, mock_urandom):
|
|
shared_secret = b'\xAA' * 32
|
|
client_challenge = b'\x01' * 32
|
|
card_challenge = b'\x02' * 32
|
|
expected_card_cryptogram = hashlib.sha256(
|
|
shared_secret + client_challenge).digest()
|
|
expected_client_cryptogram = hashlib.sha256(
|
|
shared_secret + card_challenge).digest()
|
|
|
|
first_response = expected_card_cryptogram + card_challenge
|
|
second_response = b'\x05' + card_challenge
|
|
|
|
card.send_apdu.side_effect = [first_response, second_response]
|
|
|
|
result = pair(card, shared_secret)
|
|
|
|
assert result == (5, expected_client_cryptogram)
|
|
assert card.send_apdu.call_count == 2
|
|
|
|
|
|
def test_pairing_mode(card, mock_urandom):
|
|
shared_secret = b'\xAA' * 32
|
|
client_challenge = b'\x01' * 32
|
|
card_challenge = b'\x02' * 32
|
|
expected_card_cryptogram = hashlib.sha256(
|
|
shared_secret + client_challenge).digest()
|
|
first_response = expected_card_cryptogram + card_challenge
|
|
second_response = b'\x05' + card_challenge
|
|
|
|
card.send_apdu.side_effect = [first_response, second_response]
|
|
|
|
pair(card, shared_secret, PairingMode.EPHEMERAL)
|
|
card.send_apdu.assert_any_call(
|
|
ins=INS_PAIR,
|
|
p2=PairingMode.EPHEMERAL,
|
|
data=client_challenge
|
|
)
|
|
|
|
|
|
def test_pair_invalid_shared_secret(card, mock_urandom):
|
|
with pytest.raises(ValueError, match='Shared secret must be 32 bytes'):
|
|
pair(card, b'short')
|
|
|
|
|
|
def test_pair_apdu_error_on_first(card, mock_urandom):
|
|
card.send_apdu.side_effect = APDUError(0x6A82)
|
|
|
|
with pytest.raises(APDUError):
|
|
pair(card, b'\x00' * 32)
|
|
|
|
|
|
def test_pair_invalid_response_length_first(card, mock_urandom):
|
|
card.send_apdu.return_value = bytes(10)
|
|
|
|
with pytest.raises(
|
|
InvalidResponseError,
|
|
match='Unexpected response length'
|
|
):
|
|
pair(card, b'\x00' * 32)
|
|
|
|
|
|
def test_pair_cryptogram_mismatch(card, mock_urandom):
|
|
wrong_card_cryptogram = b'\xAB' * 32
|
|
card_challenge = b'\x02' * 32
|
|
response = wrong_card_cryptogram + card_challenge
|
|
|
|
card.send_apdu.side_effect = [response]
|
|
|
|
with pytest.raises(InvalidResponseError, match='Card cryptogram mismatch'):
|
|
pair(card, b'\xAA' * 32)
|
|
|
|
|
|
def test_pair_invalid_response_second_apdu(card, mock_urandom):
|
|
shared_secret = b'\xAA' * 32
|
|
client_challenge = b'\x01' * 32
|
|
card_challenge = b'\x02' * 32
|
|
card_cryptogram = hashlib.sha256(shared_secret + client_challenge).digest()
|
|
|
|
first_response = card_cryptogram + card_challenge
|
|
second_response = b'\x00' * 10
|
|
|
|
card.send_apdu.side_effect = [first_response, second_response]
|
|
|
|
with pytest.raises(
|
|
InvalidResponseError,
|
|
match='Unexpected response length'
|
|
):
|
|
pair(card, shared_secret)
|