Spaces:
Running
Running
File size: 2,106 Bytes
f2f99a3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | /**
* CRC computation for payload integrity verification
* Supports CRC-4, CRC-8, and CRC-16
*/
// CRC-4 polynomial: x^4 + x + 1 (0x13, used bits: 0x03)
const CRC4_POLY = 0x03;
// CRC-8 polynomial: x^8 + x^2 + x + 1 (CRC-8-CCITT)
const CRC8_POLY = 0x07;
// CRC-16 polynomial: x^16 + x^15 + x^2 + 1 (CRC-16-IBM)
const CRC16_POLY = 0x8005;
/**
* Compute CRC over a bit array
* Uses non-zero initial value to prevent all-zeros from having CRC=0
*/
function computeCrc(bits: Uint8Array, poly: number, crcBits: number): number {
const mask = (1 << crcBits) - 1;
let crc = mask; // Non-zero init: all 1s (0xF for CRC-4, 0xFF for CRC-8, 0xFFFF for CRC-16)
for (let i = 0; i < bits.length; i++) {
crc ^= (bits[i] & 1) << (crcBits - 1);
if (crc & (1 << (crcBits - 1))) {
crc = ((crc << 1) ^ poly) & mask;
} else {
crc = (crc << 1) & mask;
}
}
return crc;
}
/**
* Compute CRC and append to bit array
*/
export function crcAppend(bits: Uint8Array, crcBits: 4 | 8 | 16): Uint8Array {
const poly = crcBits === 4 ? CRC4_POLY : crcBits === 8 ? CRC8_POLY : CRC16_POLY;
const crc = computeCrc(bits, poly, crcBits);
const result = new Uint8Array(bits.length + crcBits);
result.set(bits);
// Append CRC bits (MSB first)
for (let i = 0; i < crcBits; i++) {
result[bits.length + i] = (crc >> (crcBits - 1 - i)) & 1;
}
return result;
}
/**
* Verify CRC on a bit array (last crcBits bits are the CRC)
* Returns the payload bits (without CRC) if valid, null otherwise
*/
export function crcVerify(bits: Uint8Array, crcBits: 4 | 8 | 16): Uint8Array | null {
if (bits.length <= crcBits) return null;
const payload = bits.subarray(0, bits.length - crcBits);
const poly = crcBits === 4 ? CRC4_POLY : crcBits === 8 ? CRC8_POLY : CRC16_POLY;
const computed = computeCrc(payload, poly, crcBits);
// Extract received CRC
let received = 0;
for (let i = 0; i < crcBits; i++) {
received |= (bits[bits.length - crcBits + i] & 1) << (crcBits - 1 - i);
}
if (computed === received) {
return new Uint8Array(payload);
}
return null;
}
|