77 lines
1.9 KiB
Python
77 lines
1.9 KiB
Python
"""
|
|
CRC-ITU Implementation for KKS Badge Protocol
|
|
|
|
Uses CRC-16/X-25 (reflected CRC-CCITT):
|
|
Polynomial: 0x8408 (reflected 0x1021)
|
|
Initial value: 0xFFFF
|
|
Final XOR: 0xFFFF
|
|
"""
|
|
|
|
from typing import List
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Pre-computed CRC lookup table (256 entries, reflected polynomial 0x8408)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_CRC_TABLE: List[int] = []
|
|
|
|
|
|
def _generate_crc_table() -> List[int]:
|
|
"""Generate the CRC-16/X-25 lookup table for reflected polynomial 0x8408."""
|
|
table: List[int] = []
|
|
for i in range(256):
|
|
crc = i
|
|
for _ in range(8):
|
|
if crc & 1:
|
|
crc = (crc >> 1) ^ 0x8408
|
|
else:
|
|
crc >>= 1
|
|
table.append(crc)
|
|
return table
|
|
|
|
|
|
_CRC_TABLE = _generate_crc_table()
|
|
|
|
|
|
def crc_itu(data: bytes) -> int:
|
|
"""
|
|
Compute the CRC-ITU checksum for the given data.
|
|
|
|
Uses the CRC-16/X-25 algorithm (reflected CRC-CCITT with final XOR).
|
|
For a KKS protocol packet this should be the bytes from (and including)
|
|
the packet-length field through the serial-number field.
|
|
|
|
Parameters
|
|
----------
|
|
data : bytes
|
|
The data to compute the CRC over.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
16-bit CRC value.
|
|
"""
|
|
crc: int = 0xFFFF
|
|
for byte in data:
|
|
crc = (crc >> 8) ^ _CRC_TABLE[(crc ^ byte) & 0xFF]
|
|
return crc ^ 0xFFFF
|
|
|
|
|
|
def verify_crc(data: bytes, expected_crc: int) -> bool:
|
|
"""
|
|
Verify that *data* produces the *expected_crc*.
|
|
|
|
Parameters
|
|
----------
|
|
data : bytes
|
|
The data slice to check (same range used when computing the CRC).
|
|
expected_crc : int
|
|
The 16-bit CRC value to compare against.
|
|
|
|
Returns
|
|
-------
|
|
bool
|
|
``True`` if the computed CRC matches *expected_crc*.
|
|
"""
|
|
return crc_itu(data) == (expected_crc & 0xFFFF)
|