capjs-core 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +11 -1
- package/src/hashwx-load.js +14 -0
- package/src/hashwx-load.workerd.js +5 -0
- package/src/hashwx.js +15 -11
- package/src/hashwx.wasm +0 -0
- package/src/index.d.ts +6 -0
- package/src/index.js +13 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capjs-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Stateless server-side challenge generator and verifier for Cap, a lightweight, modern open-source CAPTCHA alternative. No storage, no filesystem - bring your own.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anti-abuse",
|
|
@@ -33,6 +33,13 @@
|
|
|
33
33
|
"types": "./src/index.d.ts",
|
|
34
34
|
"import": "./src/index.js",
|
|
35
35
|
"default": "./src/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./hashwx.wasm": "./src/hashwx.wasm"
|
|
38
|
+
},
|
|
39
|
+
"imports": {
|
|
40
|
+
"#hashwx-load": {
|
|
41
|
+
"workerd": "./src/hashwx-load.workerd.js",
|
|
42
|
+
"default": "./src/hashwx-load.js"
|
|
36
43
|
}
|
|
37
44
|
},
|
|
38
45
|
"types": "src/index.d.ts",
|
|
@@ -46,6 +53,9 @@
|
|
|
46
53
|
"src/rsw.js",
|
|
47
54
|
"src/hashwx.js",
|
|
48
55
|
"src/hashwx-wasm.js",
|
|
56
|
+
"src/hashwx-load.js",
|
|
57
|
+
"src/hashwx-load.workerd.js",
|
|
58
|
+
"src/hashwx.wasm",
|
|
49
59
|
"README.md",
|
|
50
60
|
"LICENSE"
|
|
51
61
|
],
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HASHWX_WASM_BASE64 } from "./hashwx-wasm.js";
|
|
2
|
+
|
|
3
|
+
function decodeBase64(b64) {
|
|
4
|
+
if (typeof Buffer !== "undefined")
|
|
5
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
6
|
+
const bin = atob(b64);
|
|
7
|
+
const out = new Uint8Array(bin.length);
|
|
8
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function loadHashwxModule() {
|
|
13
|
+
return WebAssembly.compile(decodeBase64(HASHWX_WASM_BASE64));
|
|
14
|
+
}
|
package/src/hashwx.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { loadHashwxModule } from "#hashwx-load";
|
|
3
3
|
|
|
4
4
|
export const HASHWX_SEED_SIZE = 32;
|
|
5
5
|
export const HASHWX_CHALLENGE_SIZE = 32;
|
|
@@ -15,19 +15,23 @@ export const MAX_HASHWX_CHALLENGE_COUNT = 64;
|
|
|
15
15
|
const U64_MAX = (1n << 64n) - 1n;
|
|
16
16
|
const HASHWX_INTERPRETED = 0;
|
|
17
17
|
|
|
18
|
-
function decodeBase64(b64) {
|
|
19
|
-
if (typeof Buffer !== "undefined")
|
|
20
|
-
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
21
|
-
const bin = atob(b64);
|
|
22
|
-
const out = new Uint8Array(bin.length);
|
|
23
|
-
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
18
|
let readyPromise = null;
|
|
19
|
+
let suppliedModule = null;
|
|
20
|
+
|
|
21
|
+
export function setHashwxModule(module) {
|
|
22
|
+
if (!(module instanceof WebAssembly.Module))
|
|
23
|
+
throw new TypeError(
|
|
24
|
+
"[capjs-core] setHashwxModule expects a WebAssembly.Module",
|
|
25
|
+
);
|
|
26
|
+
if (readyPromise)
|
|
27
|
+
throw new Error(
|
|
28
|
+
"[capjs-core] setHashwxModule must be called before HashWX initializes",
|
|
29
|
+
);
|
|
30
|
+
suppliedModule = module;
|
|
31
|
+
}
|
|
28
32
|
|
|
29
33
|
async function init() {
|
|
30
|
-
const mod = await
|
|
34
|
+
const mod = suppliedModule ?? (await loadHashwxModule());
|
|
31
35
|
const instance = new WebAssembly.Instance(mod, {});
|
|
32
36
|
const exports = instance.exports;
|
|
33
37
|
if (typeof exports._initialize === "function") exports._initialize();
|
package/src/hashwx.wasm
ADDED
|
Binary file
|
package/src/index.d.ts
CHANGED
|
@@ -250,6 +250,12 @@ export interface HashwxState {
|
|
|
250
250
|
seedPtr: number;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
+
/** Supplies a precompiled HashWX module for runtimes that forbid compiling
|
|
254
|
+
* wasm at runtime. Cloudflare Workers pick up
|
|
255
|
+
* the bundled `hashwx.wasm` automatically. Must be called before the first
|
|
256
|
+
* verification or `hashwxReady()`. */
|
|
257
|
+
export function setHashwxModule(module: WebAssembly.Module): void;
|
|
258
|
+
|
|
253
259
|
/** Compiles and initializes the embedded HashWX wasm. Called automatically on
|
|
254
260
|
* first verification; await it at boot to move the cost off the first
|
|
255
261
|
* request. Resolves to a state handle reusable with `hashwxHash`. */
|
package/src/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export {
|
|
|
27
27
|
hashwxReady,
|
|
28
28
|
hashwxSeed,
|
|
29
29
|
hashwxTarget,
|
|
30
|
+
setHashwxModule,
|
|
30
31
|
} from "./hashwx.js";
|
|
31
32
|
|
|
32
33
|
import { fnv1a, fnv1aResume, prngFromHash } from "./prng.js";
|
|
@@ -240,9 +241,12 @@ export async function validateChallenge(secret, body, opts = {}) {
|
|
|
240
241
|
}
|
|
241
242
|
|
|
242
243
|
if (body.instr_blocked === true) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
return fail(
|
|
245
|
+
instrMeta.blockAutomatedBrowsers
|
|
246
|
+
? "instr_automated_browser"
|
|
247
|
+
: "instr_failed",
|
|
248
|
+
{ instr_error: true },
|
|
249
|
+
);
|
|
246
250
|
} else if (body.instr_timeout === true) {
|
|
247
251
|
return fail("instr_timeout", { instr_error: true });
|
|
248
252
|
} else if (body.instr) {
|
|
@@ -434,9 +438,12 @@ async function validateChallengeV2(secret, body, payload, opts = {}) {
|
|
|
434
438
|
return fail("instr_expired", { instr_error: true });
|
|
435
439
|
}
|
|
436
440
|
if (s.blocked === true) {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
441
|
+
return fail(
|
|
442
|
+
meta.blockAutomatedBrowsers
|
|
443
|
+
? "instr_automated_browser"
|
|
444
|
+
: "instr_failed",
|
|
445
|
+
{ instr_error: true },
|
|
446
|
+
);
|
|
440
447
|
} else if (s.timeout === true) {
|
|
441
448
|
return fail("instr_timeout", { instr_error: true });
|
|
442
449
|
} else if (s.instr) {
|