pyhunterbtt

Protocol library for Hunter BTT
git clone https://git.stephank.nl/pyhunterbtt
Log | Files | Refs | README | LICENSE | ZIP

test_auth.py (2192B)


      1 """Tests for the current FF81 authentication payload."""
      2 
      3 import unittest
      4 
      5 from pyhunterbtt.auth import encode_authentication, encode_passcode_change
      6 from pyhunterbtt.protocol import ProtocolError
      7 
      8 SYNTHETIC_CLIENT_IDENTIFIER = bytes.fromhex("01 23 45 67 89 ab")
      9 SYNTHETIC_NONCE = b"K7m"
     10 
     11 
     12 class AuthenticationTests(unittest.TestCase):
     13     """Verify the app-compatible encoder without captured credentials."""
     14 
     15     def test_synthetic_known_vector(self) -> None:
     16         payload = encode_authentication(
     17             "2468",
     18             SYNTHETIC_CLIENT_IDENTIFIER,
     19             nonce=SYNTHETIC_NONCE,
     20         )
     21         self.assertEqual(
     22             payload,
     23             bytes.fromhex("8a 86 82 9e 8c c8 04 40 9d d9 00 4b 37 6d"),
     24         )
     25 
     26     def test_passcode_change_sets_operation_byte(self) -> None:
     27         payload = encode_passcode_change(
     28             "2468",
     29             SYNTHETIC_CLIENT_IDENTIFIER,
     30             nonce=SYNTHETIC_NONCE,
     31         )
     32         self.assertEqual(payload[10], 1)
     33         self.assertEqual(payload[11:], SYNTHETIC_NONCE)
     34 
     35     def test_generated_nonce_has_app_compatible_shape(self) -> None:
     36         payload = encode_authentication("2468", SYNTHETIC_CLIENT_IDENTIFIER)
     37         self.assertEqual(len(payload), 14)
     38         self.assertEqual(payload[10], 0)
     39         self.assertEqual(len(payload[11:]), 3)
     40         self.assertTrue(payload[11:].isalnum())
     41 
     42     def test_rejects_non_digit_passcode(self) -> None:
     43         for passcode in ("123", "12345", "12x4", "1234"):
     44             with self.subTest(passcode=passcode), self.assertRaises(ProtocolError):
     45                 encode_authentication(
     46                     passcode,
     47                     SYNTHETIC_CLIENT_IDENTIFIER,
     48                     nonce=SYNTHETIC_NONCE,
     49                 )
     50 
     51     def test_rejects_wrong_identifier_or_nonce_size(self) -> None:
     52         with self.assertRaises(ProtocolError):
     53             encode_authentication("2468", b"short", nonce=SYNTHETIC_NONCE)
     54         with self.assertRaises(ProtocolError):
     55             encode_authentication(
     56                 "2468",
     57                 SYNTHETIC_CLIENT_IDENTIFIER,
     58                 nonce=b"no",
     59             )
     60 
     61 
     62 if __name__ == "__main__":
     63     unittest.main()