// Synthetic bundle for raycast_api.discovery tests. // // Structurally mirrors Raycast's bundle: a rot13+rot5 function, an async // 4-param HMAC signer that .map()s through the rot fn, and a couple of decoys // the extractor must reject. Identifier names are intentionally NOT the // minified ones from real Raycast (Sur, Nkt) — we use longer names to prove // the extractor matches structurally, not by name. // --- decoy 1: 1-param but missing the rot triplets ---------------------- function decoyOneParam(t) { return t.toUpperCase(); } // --- decoy 2: 4-param HMAC-ish but with no .map(rot) call -------------- async function decoyHmac(a, b, c, d) { // Mentions HMAC + SHA-256 + importKey but never calls .map(rotFn). let key = await crypto.subtle.importKey("raw", a, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); return crypto.subtle.sign("HMAC", key, b); } // --- the real rot fn ---------------------------------------------------- function RotXform(s) { let out = ""; for (let ch of s) { let r = ch.charCodeAt(0); if (r >= 65 && r <= 90) { out += String.fromCharCode((r - 65 + 13) % 26 + 65); } else if (r >= 97 && r <= 122) { out += String.fromCharCode((r - 97 + 13) % 26 + 97); } else if (r >= 48 && r <= 57) { out += String.fromCharCode((r - 48 + 5) % 10 + 48); } else { out += ch; } } return out; } // --- duplicate rot (real bundle has two byte-identical copies) --------- function RotXform2(s) { let out = ""; for (let ch of s) { let r = ch.charCodeAt(0); if (r >= 65 && r <= 90) { out += String.fromCharCode((r - 65 + 13) % 26 + 65); } else if (r >= 97 && r <= 122) { out += String.fromCharCode((r - 97 + 13) % 26 + 97); } else if (r >= 48 && r <= 57) { out += String.fromCharCode((r - 48 + 5) % 10 + 48); } else { out += ch; } } return out; } // --- the real signing fn ----------------------------------------------- async function SignReq(secret, timestamp, deviceId, body) { let enc = new TextEncoder().encode(body); let h = await crypto.subtle.digest("SHA-256", enc); let bodyHash = Array.from(new Uint8Array(h)).map(b => b.toString(16).padStart(2, "0")).join(""); let canonical = [timestamp, deviceId, bodyHash].map(RotXform).join("."); let keyBytes = new TextEncoder().encode(secret); let canonBytes = new TextEncoder().encode(canonical); let key = await crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); let sig = await crypto.subtle.sign("HMAC", key, canonBytes); return Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, "0")).join(""); } // Decoy: looks like a string-handling function but with a `/` inside a // regex literal — exercises the regex-aware brace matcher. function noiseFn(input) { return input.replace(/\}/g, "_"); } export { SignReq, RotXform };