-
-
Save oysstu/68072c44c02879a2abf94ef350d1c7c6 to your computer and use it in GitHub Desktop.
def crc16(data: bytes, poly=0x8408): | |
''' | |
CRC-16-CCITT Algorithm | |
''' | |
data = bytearray(data) | |
crc = 0xFFFF | |
for b in data: | |
cur_byte = 0xFF & b | |
for _ in range(0, 8): | |
if (crc & 0x0001) ^ (cur_byte & 0x0001): | |
crc = (crc >> 1) ^ poly | |
else: | |
crc >>= 1 | |
cur_byte >>= 1 | |
crc = (~crc & 0xFFFF) | |
crc = (crc << 8) | ((crc >> 8) & 0xFF) | |
return crc & 0xFFFF |
I'm confused. If I send b'313233343536373839' to the above I get crc 64705 which is C1FC. But if I send the same bytestring to http://www.sunshine2k.de/coding/javascript/crc/crc_js.html (CRC_AUG_CCITT, poly 0x1021, initial 0x1D0F), it returns E5CC not C1FC.
It's not easy to help you if you don't indicate what code you have used...
FYI, the variant of CRC16-CCITT implemented in the function I posted here a while ago is "CRC-16/CCITT-FALSE"
It is completely defined with:
poly = 0x1021
init = 0xFFFF
no reflection on input, no reflection on output
no xoring after final result
check = 0x29B1
Instead of www.sunshine2k.de I would recommend https://crccalc.com
the "check" value is the CRC you get when you feed the ascii string '123456789' in its binary form
it is characteristic of the variant of CRC you're using
e.g. with the function I posted, either of these calls:
print(hex(crc16(b'123456789')))
print(hex(crc16(b'\x31\x32\x33\x34\x35\x36\x37\x38\x39')))
would produce the output:
0x29b1
def crc16(data: bytes): ''' CRC-16 (CCITT) implemented with a precomputed lookup table ''' table = [ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 ] crc = 0xFFFF for byte in data: crc = (crc << 8) ^ table[(crc >> 8) ^ byte] crc &= 0xFFFF # important, crc must stay 16bits all the way through return crc
i have an input given as a list input=[1,0,0,1,0,0,1,0]. What am i supposed to convert this list to in order for that function to return the expected output 0x420B?
420B is returned by this particular variant of crc16 if you feed it with b'45377 So if you can figure out the connection between that & your list you're good to go. Unfortunately nothing obvious comes to mind.
…
Well converting it from binary to hexadecimal it’s 0x92 and according to https://crccalc.com/ that should return 420B for CRC-16-CCITT-FALSE. If that is a different one than the above code, how can i change the code for this variant that i need?
return('{:04X}'.format(crc))
Thanks, it works. Is there a better way to convert the list to be in a suitable format than this ChatGPT suggestion? (i'm very new to python)
bits_string = ''.join(str(bit) for bit in input_list)
int_value = int(bits_string, 2)
hex_value = hex(int_value)
hex_string = hex_value.replace('0x', '0x0') if len(hex_value) % 2 == 1 else hex_value
hex_value = bytes.fromhex(hex_string[2:])
crc=crc16(hex_value)
@pragma31 if I have a payload like this : " 623e0200000000000000000000000000" where 623e is crc given by a software i want to verify it , so what should i pass to get this value to the function that you have written here crc16 , thanks
same if i want to use https://crccalc.com/
@oysstu could you please guide me how could I use this code.
My data is (hex) E3BCBEBEA65EB3B87266124B2B238B6B
Polynomial is 0x1021
I'm confused. If I send b'313233343536373839' to the above I get crc 64705 which is C1FC. But if I send the same bytestring to http://www.sunshine2k.de/coding/javascript/crc/crc_js.html (CRC_AUG_CCITT, poly 0x1021, initial 0x1D0F), it returns E5CC not C1FC.