Как использовать побитовые операторы для сырых двоичных данных в Python для проверки CRC?

Это первый раз, когда я использую bitewise-операторы и необработанные двоичные данные в Python, и я изо всех сил пытаюсь закодировать CRC-проверку, как определено в документации.

Документация определяет проверку CRC в псевдокоде следующим образом:

GENERATOR = 1111111111111010000001001
MSG = binary("8D4840D6202CC371C32CE0576098") # total 112 bits
FOR i FROM 0 TO 88: # 112 - 24 parity bits if MSG[i] is 1: MSG[i:i+24] = MSG[i:i+24] ^ GENERATOR
CRC = MSG[-24:] # last 24 bits
IF CRC not 0: MSG is corrupted

До сих пор я кодировал это:

adsb_hex = "8D4840D6202CC371C32CE0576098"
adsb_dec = int(adsb_hex, 16)
adsb_bin = bin(adsb_dec)[2:].zfill(8)
generator = 0b1111111111111010000001001
adsb_bin_list = [int((adsb_dec >> bit) & 1) for bit in range(112 - 1, -1, -1)]
check = []
for i in range(88): curr_bit = adsb_bin_list[i] if curr_bit is 1: check[i:i+24] = int(adsb_bin_list[i:i+24]) ^ generator
crc = check[-24:]

Я не знаю, как правильно это сделать:

MSG[i:i+24] = MSG[i:i+24] ^ GENERATOR
CRC = MSG[-24:]

Как я могу сделать это правильно, питоновский путь?

2 ответа

Если вы можете использовать библиотеки, я рекомендую искать вашу любимую библиотеку bitstring/bitvector. Например, используя BitVector==3.4.8 вы можете написать

from BitVector import BitVector
generator = BitVector(bitstring='1111111111111010000001001')
crc_length = len(generator) - 1
def compute_crc(message : BitVector) -> BitVector: content_length = len(message) - crc_length # to encode a message, you pad it with 0 # to decode, you pass in the message with the crc appended assert content_length >= 0 # operate on a copy of the data message = message.deep_copy() for i in range(content_length): if message[i]: message[i:i + len(generator)] ^= generator return message[-crc_length:]
if __name__ == "__main__": adsb_hex = "8D4840D6202CC371C32CE0576098" adsb_crc = compute_crc(BitVector(hexstring = adsb_hex))


Здесь вы можете использовать более пифонический подход, хотя он отказывается от арифметики прямого бита.

msg_hex = "8D4840D6202CC371C32CE0576098"
msg_dec = int(msg_hex, 16)
msg_bin = list(bin(msg_dec)[2:].zfill(8))
generator = "1111111111111010000001001"
for i in range(88): if msg_bin[i] == "1": msg_bin[i:i+24] = ["1" if a != b else "0" for a, b in zip(msg_bin[i:i+24], generator)]
if int("".join(msg_bin[-24:])): print("corrupted")

Вы можете заменить "1" if a != b else "0" с "01"[a!=b] если хотите, но я думаю, что первый более питонический.

Я не мог проверить, правильно ли это решение, так как код не компилируется и не упоминается, что должен генерировать данный генератор и сообщение. Я подозреваю, что в описании проблемы есть ошибка, поскольку она выполняет проверку последних 24 бит, но генератор содержит 25.

licensed under cc by-sa 3.0 with attribution.