def test_reverse_engineering(self): c = GenericCRC(polynomial="16_standard", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) bitstring_set = [ "1110001111001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110010011001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110010111001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110011011001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010" ] bitset = [] crcset = [] for i in bitstring_set: tmp = c.str2bit(i) bitset.append(tmp) crcset.append(c.crc(tmp)) polynomial = c.reverse_engineer_polynomial(bitset, crcset) if polynomial: self.assertEqual(c.bit2str(polynomial), "1000000000000101") self.assertEqual(util.bit2hex(polynomial), "8005")
def test_adaptive_crc_calculation(self): c = GenericCRC(polynomial="16_ccitt", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) inpt1 = "10101010101010" inpt2 = "1010101010101001" crc1 = c.crc(c.str2arr(inpt1)) crc2 = c.crc(c.str2arr(inpt2)) # Compute crc2 from crc1 in a faster way # Note: In general only forward direction delta = "01" c.start_value = crc1 crcx = c.crc(c.str2arr(delta)) self.assertEqual(crcx, crc2)
def test_crc(self): # http://depa.usst.edu.cn/chenjq/www2/software/crc/CRC_Javascript/CRCcalculation.htm # CRC-16: polynomial="16_standard", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False # CRC-16-CCITT: polynomial="16_ccitt", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False # http://www.lammertbies.nl/comm/info/crc-calculation.html <- Fehler # CRC-16: polynomial="16_standard", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False c = GenericCRC(polynomial=WSPChecksum.CRC_8_POLYNOMIAL) e = Encoding() bitstr = [ "010101010110100111011010111011101110111011100110001011101010001011101110110110101101", "010101010110101001101110111011101110111011100110001011101010001011101110110111100101", "010101010110100111010010111011101110111011100110001011101010001011101110110110100101" ] expected = ["78", "c9", "f2"] for value, expect in zip(bitstr, expected): nv = "" for i in range(0, len(value)): if value[i] == "1": nv += "0" else: nv += "1" self.assertEqual(util.bit2hex(c.crc(e.str2bit(value[4:-8]))), expect)
def test_crc(self): # http://depa.usst.edu.cn/chenjq/www2/software/crc/CRC_Javascript/CRCcalculation.htm # CRC-16: polynomial="16_standard", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False # CRC-16-CCITT: polynomial="16_ccitt", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False # http://www.lammertbies.nl/comm/info/crc-calculation.html <- Fehler # CRC-16: polynomial="16_standard", start_value = False, final_xor = False, reverse_polynomial=False, reverse_all=False c = GenericCRC(polynomial=WSPChecksum.CRC_8_POLYNOMIAL) e = Encoding() bitstr = ["010101010110100111011010111011101110111011100110001011101010001011101110110110101101", "010101010110101001101110111011101110111011100110001011101010001011101110110111100101", "010101010110100111010010111011101110111011100110001011101010001011101110110110100101"] expected = ["78", "c9", "f2"] for value, expect in zip(bitstr, expected): nv = "" for i in range(0, len(value)): if value[i] == "1": nv += "0" else: nv += "1" self.assertEqual(util.bit2hex(c.crc(e.str2bit(value[4:-8]))), expect)
def test_crc8(self): messages = ["aabbcc", "abcdee", "dacafe"] expected = ["7d", "24", "33"] crc = GenericCRC(polynomial=GenericCRC.DEFAULT_POLYNOMIALS["8_ccitt"]) for msg, expect in zip(messages, expected): bits = util.hex2bit(msg) self.assertEqual(util.bit2hex(crc.crc(bits)), expect)
def test_guess_standard_parameters_and_datarange(self): c = GenericCRC(polynomial="16_ccitt", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) inpt = "101010101010101010000000111000000000000011100000001011010010110100000000111000000101001010000100000000000100111001111110010000000011011111111001001101100001100010100000000000111011110100010" vrfy_crc = "0011101111010001" result = c.guess_standard_parameters_and_datarange(c.str2arr(inpt), c.str2arr(vrfy_crc)) self.assertEqual(result, (2, 84, 172)) self.assertEqual(vrfy_crc, c.bit2str(c.crc(c.str2arr(inpt[result[1]:result[2]]))))
def test_different_crcs(self): c = GenericCRC(polynomial="16_standard", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) bitstring_set = [ "101001001010101010101011101111111000000000000111101010011101011", "101001001010101101111010110111101010010110111010", "00000000000000000000000000000000100000000000000000000000000000000001111111111111", "1111111111111111111111111111111110111111111111111111110111111111111111110000000000" "1"] for j in c.DEFAULT_POLYNOMIALS: c.polynomial = c.choose_polynomial(j) for i in bitstring_set: # Standard crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) # Special final xor c.final_xor = c.str2bit("0000111100001111") crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.final_xor = [False] * 16 # Special start value c.start_value = c.str2bit("1010101010101010") crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.start_value = [False] * 16 # reverse_polynomial c.reverse_polynomial = True crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.reverse_polynomial = False # lsb_first c.lsb_first = True crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.lsb_first = False # little_endian c.little_endian = True crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.little_endian = False # reverse all c.reverse_all = True crc_new = c.crc(c.str2bit(i)) crc_old = c.reference_crc(c.str2bit(i)) self.assertEqual(crc_new, crc_old) c.reverse_all = False
def test_not_aligned_data_len(self): c = GenericCRC(polynomial="16_standard", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) polynomials = ["8_standard", "16_standard", "16_ccitt", "16_dnp"] crcs = {"8_standard": 0xd5, "16_standard": 0x8005, "16_ccitt": 0x1021, "16_dnp": 0x3d65} for j in polynomials: c.polynomial = c.choose_polynomial(j) inpt = "1" for i in range(0, 32): val = c.bit2int(c.crc(c.str2bit(inpt))) self.assertEqual(val, crcs[j]) inpt = "0" + inpt
def test_reverse_engineering(self): c = GenericCRC(polynomial="16_standard", start_value=False, final_xor=False, reverse_polynomial=False, reverse_all=False, lsb_first=False, little_endian=False) bitstring_set = [ "1110001111001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110010011001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110010111001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010", "1110011011001011100010000101010100000010110111000101100010100100111110111101100110110111011001010010001011101010"] bitset = [] crcset = [] for i in bitstring_set: tmp = c.str2bit(i) bitset.append(tmp) crcset.append(c.crc(tmp)) # print(c.guess_standard_parameters(bitset[0], crcset[0])) polynomial = c.reverse_engineer_polynomial(bitset, crcset) if polynomial: self.assertEqual(c.bit2str(polynomial), "1000000000000101") self.assertEqual(util.bit2hex(polynomial), "8005")
def apply_data_whitening(self, decoding, inpt): len_sync = len(self.data_whitening_sync) len_polynomial = len(self.data_whitening_polynomial) inpt_from = 0 inpt_to = len(inpt) # Crop last bit, if duplicate if decoding and inpt_to > 1: if inpt[-1] == inpt[-2]: inpt_to -= 1 # # Crop last bit, if len not multiple of 8 # if decoding and inpt_to % 8 != 0: # inpt_to -= (8 - (inpt_to % 8)) % 8 # inpt empty, polynomial or syncbytes are zero! (Shouldn't happen) if inpt_to < 1 or len_polynomial < 1 or len_sync < 1: return inpt[ inpt_from:inpt_to], 0, self.ErrorState.MISC # Misc Error # Search for whitening start position (after sync bytes) whitening_start_pos = inpt_from i = inpt_from while i < (inpt_to - len_sync): equalbits = 0 for j in range(0, len_sync): if inpt[i + j] == self.data_whitening_sync[j]: equalbits += 1 else: continue if len_sync == equalbits: whitening_start_pos = i + j + 1 break else: i += 1 # Sync not found if decoding and whitening_start_pos == inpt_from: return inpt[inpt_from:inpt_to], 0, self.ErrorState.SYNC_NOT_FOUND # Prepare keystream self.lfsr_state = array.array("B", []) keystream = self.lfsr(0) for i in range(whitening_start_pos, inpt_to, 8): keystream.extend(self.lfsr(8)) # If data whitening polynomial is wrong, keystream can be less than needed. Check and exit. if len(keystream) < inpt_to - whitening_start_pos: return inpt[ inpt_from:inpt_to], 0, self.ErrorState.MISC # Error 31338 # Overwrite crc16 in encoding case if not decoding and self.cc1101_overwrite_crc: # Remove additional bits offset = inpt_to % 8 data_end = inpt_to - 16 - offset c = GenericCRC(polynomial="16_standard", start_value=True) crc = c.crc(inpt[whitening_start_pos:data_end]) for i in range(0, 16): inpt[data_end + i] = crc[i] # Apply keystream (xor) for i in range(whitening_start_pos, inpt_to): inpt[i] ^= keystream[i - whitening_start_pos] # Duplicate last bit when encoding if not decoding: inpt += array.array("B", [inpt[-1]]) inpt_to += 1 return inpt[inpt_from:inpt_to], 0, self.ErrorState.SUCCESS
def apply_data_whitening(self, decoding, inpt): len_sync = len(self.data_whitening_sync) len_polynomial = len(self.data_whitening_polynomial) inpt_from = 0 inpt_to = len(inpt) # Crop last bit, if duplicate if decoding and inpt_to > 1: if inpt[-1] == inpt[-2]: inpt_to -= 1 # # Crop last bit, if len not multiple of 8 # if decoding and inpt_to % 8 != 0: # inpt_to -= (8 - (inpt_to % 8)) % 8 # inpt empty, polynomial or syncbytes are zero! (Shouldn't happen) if inpt_to < 1 or len_polynomial < 1 or len_sync < 1: return inpt[inpt_from:inpt_to], 0, self.ErrorState.MISC # Misc Error # Search for whitening start position (after sync bytes) whitening_start_pos = inpt_from i = inpt_from while i < (inpt_to - len_sync): equalbits = 0 for j in range(0, len_sync): if inpt[i + j] == self.data_whitening_sync[j]: equalbits += 1 else: continue if len_sync == equalbits: whitening_start_pos = i + j + 1 break else: i += 1 # Sync not found if decoding and whitening_start_pos == inpt_from: return inpt[inpt_from:inpt_to], 0, self.ErrorState.SYNC_NOT_FOUND # Prepare keystream self.lfsr_state = array.array("B", []) keystream = self.lfsr(0) for i in range(whitening_start_pos, inpt_to, 8): keystream.extend(self.lfsr(8)) # If data whitening polynomial is wrong, keystream can be less than needed. Check and exit. if len(keystream) < inpt_to - whitening_start_pos: return inpt[inpt_from:inpt_to], 0, self.ErrorState.MISC # Error 31338 # Overwrite crc16 in encoding case if not decoding and self.cc1101_overwrite_crc: # Remove additional bits offset = inpt_to % 8 data_end = inpt_to - 16 - offset c = GenericCRC(polynomial="16_standard", start_value=True) crc = c.crc(inpt[whitening_start_pos:data_end]) for i in range(0, 16): inpt[data_end + i] = crc[i] # Apply keystream (xor) for i in range(whitening_start_pos, inpt_to): inpt[i] ^= keystream[i - whitening_start_pos] # Duplicate last bit when encoding if not decoding: inpt += array.array("B", [inpt[-1]]) inpt_to += 1 return inpt[inpt_from:inpt_to], 0, self.ErrorState.SUCCESS