mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
Cache the in-flight xxhash-wasm initialization so concurrent calls reuse the same promise before the raw hash function is available. This avoids redundant loader work and prevents races during early CCH computations.
50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
/**
|
|
* Claude Code CCH (Client Content Hash) signing.
|
|
*
|
|
* Real Claude Code uses Bun/Zig to compute an xxHash64 integrity token over
|
|
* the serialized request body. The server verifies this to confirm the request
|
|
* came from a genuine Claude Code client.
|
|
*
|
|
* Algorithm:
|
|
* 1. Serialize request body with cch=00000 placeholder
|
|
* 2. xxHash64(body_bytes, seed) & 0xFFFFF
|
|
* 3. Zero-padded 5-char lowercase hex
|
|
* 4. Replace cch=00000 with computed value
|
|
*/
|
|
|
|
import xxhashInit from "xxhash-wasm";
|
|
|
|
const CCH_SEED = 0x6e52736ac806831en;
|
|
const CCH_PATTERN = /\bcch=([0-9a-f]{5});/;
|
|
|
|
let xxhashPromise: Promise<void> | null = null;
|
|
let xxhash64Fn: ((input: Uint8Array, seed: bigint) => bigint) | null = null;
|
|
|
|
async function ensureXxhash() {
|
|
if (xxhash64Fn) return;
|
|
if (!xxhashPromise) {
|
|
xxhashPromise = (async () => {
|
|
const hasher = await xxhashInit();
|
|
xxhash64Fn = hasher.h64Raw;
|
|
})();
|
|
}
|
|
return xxhashPromise;
|
|
}
|
|
|
|
export async function computeCCH(bodyBytes: Uint8Array): Promise<string> {
|
|
await ensureXxhash();
|
|
const hash = xxhash64Fn!(bodyBytes, CCH_SEED);
|
|
const masked = hash & 0xfffffn;
|
|
return masked.toString(16).padStart(5, "0");
|
|
}
|
|
|
|
export async function signRequestBody(bodyString: string): Promise<string> {
|
|
if (!CCH_PATTERN.test(bodyString)) return bodyString;
|
|
const encoder = new TextEncoder();
|
|
const bodyBytes = encoder.encode(bodyString);
|
|
const token = await computeCCH(bodyBytes);
|
|
return bodyString.replace(CCH_PATTERN, `cch=${token};`);
|
|
}
|
|
|
|
export { CCH_PATTERN };
|