功能说明
该示例计算 CRC32 校验和,用于检测数据在传输或存储过程中是否损坏。它接受字符串或 Uint8Array,字符串会按 UTF-8 编码后再计算,结果是一个 32 位无符号整数。crc32Hex 输出八位小写十六进制,便于放进文件名、协议字段或日志。CRC32 速度快,适合校验和不适合安全场景。
关键代码
buildTable 在模块加载时生成 256 项查找表,使用反射多项式 0xedb88320,对每个字节做八次移位与条件异或。crc32 先把种子与全一异或,再对每个字节执行查表与右移组合,最后再次异或全一得到结果。所有中间结果都用 >>> 0 转成无符号 32 位,避免出现负数。crc32Hex 用 padStart 补齐八位。
使用注意
CRC32 不是加密哈希,攻击者可以轻易构造出相同校验和的不同内容,不能用于签名或密码存储。它能发现随机错误,但对恶意篡改没有防护能力。字符串必须先约定编码,同一文本在不同编码下校验和不同。seed 参数用于分段计算,普通调用保持默认零即可。超过 4GB 的数据仍可分块累计。
验证方式
断言 hello 的校验和为 3610a686,字符串与 UTF-8 字节数组得到相同结果。对 The quick brown fox 断言已知值 414fa339。测试空字符串、含中文的字符串与分段累计结果一致,并验证十六进制输出始终为八位。
代码示例
const TABLE = buildTable();
export function crc32(input: string | Uint8Array, seed = 0): number {
const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
if (!(bytes instanceof Uint8Array)) throw new TypeError("input must be a string or Uint8Array");
if (!Number.isInteger(seed)) throw new TypeError("seed must be an integer");
let crc = (seed ^ 0xffffffff) >>> 0;
for (const byte of bytes) {
crc = (TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8)) >>> 0;
}
return (crc ^ 0xffffffff) >>> 0;
}
export function crc32Hex(input: string | Uint8Array): string {
return crc32(input).toString(16).padStart(8, "0");
}
function buildTable(): Uint32Array {
const table = new Uint32Array(256);
for (let index = 0; index < 256; index += 1) {
let value = index;
for (let bit = 0; bit < 8; bit += 1) {
value = (value & 1) === 1 ? (value >>> 1) ^ 0xedb88320 : value >>> 1;
}
table[index] = value >>> 0;
}
return table;
}
console.log(crc32Hex("hello"));
console.log(crc32Hex(new TextEncoder().encode("hello")));
console.log(crc32Hex("The quick brown fox jumps over the lazy dog"));