"""激活 keygen 测试 — 向量按 docs/firmware-analysis.md §4.2 手工推算。""" import pytest from ppclock import protocol as P class TestKeygen: def test_keygen_vector(self): """MAC 00:11:22:33:44:55 → [49,14,32,98,15,81](ror2(((m<<1)&FF)^EF)%101 手算)""" code = P.keygen_code(bytes([0x00, 0x11, 0x22, 0x33, 0x44, 0x55])) assert list(code) == [49, 14, 32, 98, 15, 81] def test_keygen_all_zero_mac(self): # t = 0^0xEF = 0xEF; ror2(0xEF)=0xFB=251; 251%101=49 assert list(P.keygen_code(bytes(6))) == [49] * 6 def test_keygen_all_ff_mac(self): # t = (0x1FE & 0xFF)^0xEF = 0xFE^0xEF = 0x11; rol2(0x11)=0x44=68; 68%101=68 assert list(P.keygen_code(b"\xFF" * 6)) == [68] * 6 def test_keygen_requires_6_bytes(self): with pytest.raises(ValueError): P.keygen_code(b"\x01" * 5) class TestRecoverMac: def test_recover_vector(self): """MAC [9A,01,99,50,10,20] → ID '89794900980101'(|MAC4-99|,|MAC5-99|,|MAC3-99|, |MAC2-99|,|MAC1-99|,|MAC0-99|,flags;flags=各字节≥0x9A 位掩码)""" mac = P.recover_mac_from_device_id("89794900980101") assert list(mac) == [0x9A, 0x01, 0x99, 0x50, 0x10, 0x20] def test_roundtrip_all_high(self): # 全 ≥0x9A:flags=0x3F;v=|m-0x99| mac = bytes([0x9A, 0xB0, 0xC1, 0xFF, 0xA0, 0x9B]) vals = [abs(mac[4] - 0x99), abs(mac[5] - 0x99), abs(mac[3] - 0x99), abs(mac[2] - 0x99), abs(mac[1] - 0x99), abs(mac[0] - 0x99)] dev_id = "".join(f"{v:02X}" for v in vals) + "3F" assert P.recover_mac_from_device_id(dev_id) == mac def test_id_must_be_14_hex(self): with pytest.raises(ValueError): P.recover_mac_from_device_id("123") def test_keygen_after_recover_matches(self): """recovered MAC → keygen:与直接对原 MAC keygen 一致""" mac = bytes([0x9A, 0x01, 0x99, 0x50, 0x10, 0x20]) recovered = P.recover_mac_from_device_id("89794900980101") assert P.keygen_code(recovered) == P.keygen_code(mac)