52 lines
2.0 KiB
Python
52 lines
2.0 KiB
Python
import argparse
|
|
from typing import List
|
|
import numpy as np
|
|
|
|
def crc(data: List[int], len_: int, start_val: int, poly: int) -> int:
|
|
crc_val = start_val
|
|
for i in range(len_):
|
|
crc_val ^= data[i]
|
|
for _ in range(8):
|
|
if (crc_val & 0x80) != 0:
|
|
crc_val = ((crc_val << 1) ^ poly) & 0xFF
|
|
else:
|
|
crc_val <<= 1
|
|
crc_val &= 0xFF
|
|
return crc_val ^ 0xFF
|
|
|
|
def is_sum_checksum_valid(messages: List[List[int]], correlation_threshold: float) -> bool:
|
|
for idx in [0, -1]:
|
|
sums = [sum(message[:idx] + message[idx+1:]) % 256 for message in messages]
|
|
checksums = [message[idx] for message in messages]
|
|
stddev_sums = np.std(sums)
|
|
stddev_checksums = np.std(checksums)
|
|
if stddev_sums == 0 or stddev_checksums == 0:
|
|
continue
|
|
correlation = np.corrcoef(sums, checksums)[0, 1]
|
|
if correlation > correlation_threshold:
|
|
return True
|
|
return False
|
|
|
|
def detect_checksum_type(messages: List[List[int]], threshold: float = 0.5, correlation_threshold: float = 0.9):
|
|
total_messages = len(messages)
|
|
crc_matches = 0
|
|
if is_sum_checksum_valid(messages, correlation_threshold):
|
|
return "Sum"
|
|
for message in messages:
|
|
data_len = len(message) - 1
|
|
for poly in range(0x01, 0xFF):
|
|
for start in range(0x00, 0x100):
|
|
if crc(message[:data_len], data_len, start, poly) == message[-1]:
|
|
crc_matches += 1
|
|
if crc_matches / total_messages > threshold:
|
|
return "CRC"
|
|
return "Unknown"
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Checksum type detector for CAN bus messages")
|
|
parser.add_argument("messages", nargs="+", help="CAN bus messages (AABBCCDDEEFF0011)")
|
|
args = parser.parse_args()
|
|
messages = [list(bytes.fromhex(msg)) for msg in args.messages]
|
|
checksum_type = detect_checksum_type(messages)
|
|
print(f"The detected checksum type is: {checksum_type}")
|