| 1 | #!/usr/bin/env python3 |
| 2 | """CRC64-ECMA reference implementation in Python.""" |
| 3 | |
| 4 | import sys |
| 5 | import binascii |
| 6 | |
| 7 | CRC64_ECMA = 0x42F0E1EBA9EA3693 |
| 8 | |
| 9 | class CRC64: |
| 10 | def __init__(self): |
| 11 | self.table = self._make_table(CRC64_ECMA) |
| 12 | |
| 13 | @staticmethod |
| 14 | def _make_table(poly): |
| 15 | table = [] |
| 16 | for i in range(256): |
| 17 | crc = i << 56 |
| 18 | for _ in range(8): |
| 19 | if crc & 0x8000000000000000: |
| 20 | crc = (crc << 1) ^ poly |
| 21 | else: |
| 22 | crc <<= 1 |
| 23 | table.append(crc & 0xFFFFFFFFFFFFFFFF) |
| 24 | return table |
| 25 | |
| 26 | def checksum(self, data): |
| 27 | """Compute CRC64 checksum of data.""" |
| 28 | crc = 0 |
| 29 | for byte in data: |
| 30 | crc = self.table[((crc >> 56) ^ byte) & 0xFF] ^ ((crc << 8) & 0xFFFFFFFFFFFFFFFF) |
| 31 | return crc & 0xFFFFFFFFFFFFFFFF |
| 32 | |
| 33 | |
| 34 | def main(): |
| 35 | crc = CRC64() |
| 36 | |
| 37 | if len(sys.argv) < 2: |
| 38 | print("Usage: crc64_ref.py <action> [data...]", file=sys.stderr) |
| 39 | print(" checksum <hexstring> - compute CRC64 of hex data", file=sys.stderr) |
| 40 | print(" table - print first 16 table entries", file=sys.stderr) |
| 41 | sys.exit(1) |
| 42 | |
| 43 | action = sys.argv[1] |
| 44 | |
| 45 | if action == "table": |
| 46 | print("CRC64_ECMA table (first 16):") |
| 47 | for i in range(16): |
| 48 | print(f" [{i:2d}] = 0x{crc.table[i]:016x}") |
| 49 | return 0 |
| 50 | |
| 51 | if action == "checksum": |
| 52 | hexstr = sys.argv[2] if len(sys.argv) > 2 else "" |
| 53 | try: |
| 54 | data = binascii.unhexlify(hexstr) if hexstr else b"" |
| 55 | result = crc.checksum(data) |
| 56 | print(f"{result:016x}") |
| 57 | return 0 |
| 58 | except (binascii.Error, ValueError) as e: |
| 59 | print(f"Error: invalid hex input: {e}", file=sys.stderr) |
| 60 | sys.exit(1) |
| 61 | |
| 62 | print(f"Error: unknown action '{action}'", file=sys.stderr) |
| 63 | sys.exit(1) |
| 64 | |
| 65 | |
| 66 | if __name__ == "__main__": |
| 67 | main() |
| 68 | |
| 69 | |