@naughtbot/sdk 0.0.1
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/README.md +22 -0
- package/dist/ble-fragmentation.d.ts +22 -0
- package/dist/ble-fragmentation.d.ts.map +1 -0
- package/dist/ble-fragmentation.js +89 -0
- package/dist/ble-fragmentation.js.map +1 -0
- package/dist/ble.d.ts +20 -0
- package/dist/ble.d.ts.map +1 -0
- package/dist/ble.js +278 -0
- package/dist/ble.js.map +1 -0
- package/dist/captcha.d.ts +35 -0
- package/dist/captcha.d.ts.map +1 -0
- package/dist/captcha.js +264 -0
- package/dist/captcha.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +41 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +112 -0
- package/dist/verify.js.map +1 -0
- package/dist/widget.d.ts +24 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +398 -0
- package/dist/widget.js.map +1 -0
- package/package.json +62 -0
package/dist/captcha.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core captcha session logic.
|
|
3
|
+
*
|
|
4
|
+
* Handles ephemeral key generation, QR code URL creation, relay polling,
|
|
5
|
+
* E2E encrypted challenge/response exchange, and SAS computation.
|
|
6
|
+
*/
|
|
7
|
+
import { generateKeyPair, deriveRequestKey, deriveResponseKey, encrypt, decrypt, requestIdToBytes, } from "@ackagent/web-sdk";
|
|
8
|
+
import { base64urlEncode } from "@ackagent/web-sdk";
|
|
9
|
+
import { computeSAS } from "@ackagent/web-sdk";
|
|
10
|
+
import { DEFAULT_TIMEOUT_MS, DEFAULT_LOGIN_URL } from "./types.js";
|
|
11
|
+
/** Polling interval for checking phone connection (ms) */
|
|
12
|
+
const POLL_INTERVAL_MS = 1_500;
|
|
13
|
+
/** Create a new captcha session */
|
|
14
|
+
export async function createSession(options) {
|
|
15
|
+
const { nonce, relayUrl, loginUrl = DEFAULT_LOGIN_URL, timeoutMs = DEFAULT_TIMEOUT_MS, debug = false, } = options;
|
|
16
|
+
if (!relayUrl) {
|
|
17
|
+
throw new Error("relayUrl is required for QR mode");
|
|
18
|
+
}
|
|
19
|
+
const log = debug ? (...args) => console.debug("[NaughtBot]", ...args) : () => { };
|
|
20
|
+
// Generate ephemeral P-256 key pair (not persisted)
|
|
21
|
+
const ephemeralKeyPair = await generateKeyPair();
|
|
22
|
+
let currentState = "initializing";
|
|
23
|
+
let currentSas = null;
|
|
24
|
+
let cancelled = false;
|
|
25
|
+
const stateCallbacks = [];
|
|
26
|
+
function setState(newState, sas) {
|
|
27
|
+
currentState = newState;
|
|
28
|
+
if (sas !== undefined) {
|
|
29
|
+
currentSas = sas;
|
|
30
|
+
}
|
|
31
|
+
for (const cb of stateCallbacks) {
|
|
32
|
+
cb(currentState, currentSas);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Create session on relay — server generates session ID
|
|
36
|
+
const sessionResult = await createRelaySession(relayUrl, ephemeralKeyPair.publicKey, log);
|
|
37
|
+
if (!sessionResult) {
|
|
38
|
+
setState("error");
|
|
39
|
+
throw new Error("Failed to create captcha session on relay");
|
|
40
|
+
}
|
|
41
|
+
const sessionId = sessionResult.sessionId;
|
|
42
|
+
const requestIdBytes = requestIdToBytes(sessionId);
|
|
43
|
+
log("Session created:", sessionId);
|
|
44
|
+
// Build QR code URL using server-returned session ID
|
|
45
|
+
const publicKeyB64 = base64urlEncode(ephemeralKeyPair.publicKey);
|
|
46
|
+
const qrCodeUrl = `${loginUrl}/link/captcha?sid=${sessionId}&pk=${publicKeyB64}`;
|
|
47
|
+
log("QR URL:", qrCodeUrl);
|
|
48
|
+
setState("waiting_for_scan");
|
|
49
|
+
const session = {
|
|
50
|
+
get sessionId() {
|
|
51
|
+
return sessionId;
|
|
52
|
+
},
|
|
53
|
+
get qrCodeUrl() {
|
|
54
|
+
return qrCodeUrl;
|
|
55
|
+
},
|
|
56
|
+
get state() {
|
|
57
|
+
return currentState;
|
|
58
|
+
},
|
|
59
|
+
get sas() {
|
|
60
|
+
return currentSas;
|
|
61
|
+
},
|
|
62
|
+
async waitForResult() {
|
|
63
|
+
const domain = typeof window !== "undefined" ? window.location.hostname : "unknown";
|
|
64
|
+
const deadline = Date.now() + timeoutMs;
|
|
65
|
+
// Phase 1: Poll for phone connection (phone posts its ephemeral public key)
|
|
66
|
+
const phonePublicKey = await pollForPhoneConnection(relayUrl, sessionId, deadline, () => cancelled, log);
|
|
67
|
+
if (cancelled)
|
|
68
|
+
throw new Error("Session cancelled");
|
|
69
|
+
setState("phone_connected");
|
|
70
|
+
// Compute SAS from both public keys
|
|
71
|
+
const approverKey = {
|
|
72
|
+
encryptionPublicKeyHex: hexEncode(phonePublicKey),
|
|
73
|
+
publicKey: phonePublicKey,
|
|
74
|
+
};
|
|
75
|
+
const sasResult = computeSAS(ephemeralKeyPair.publicKey, [approverKey]);
|
|
76
|
+
setState("sas_verification", sasResult);
|
|
77
|
+
log("SAS:", sasResult.wordString);
|
|
78
|
+
// Phase 1.5: Wait for phone to confirm SAS match (relay-mediated)
|
|
79
|
+
await pollForSASConfirmation(relayUrl, sessionId, deadline, () => cancelled, log);
|
|
80
|
+
if (cancelled)
|
|
81
|
+
throw new Error("Session cancelled");
|
|
82
|
+
// Phase 2: Send encrypted captcha challenge
|
|
83
|
+
const challenge = {
|
|
84
|
+
type: "captcha",
|
|
85
|
+
domain,
|
|
86
|
+
nonce,
|
|
87
|
+
timestamp: Date.now(),
|
|
88
|
+
};
|
|
89
|
+
const challengeBytes = new TextEncoder().encode(JSON.stringify(challenge));
|
|
90
|
+
const requestKey = await deriveRequestKey(ephemeralKeyPair.privateKey, phonePublicKey, requestIdBytes);
|
|
91
|
+
const { ciphertext, nonce: encNonce } = encrypt(requestKey, challengeBytes, requestIdBytes);
|
|
92
|
+
await postEncryptedChallenge(relayUrl, sessionId, ciphertext, encNonce, log);
|
|
93
|
+
setState("verifying");
|
|
94
|
+
// Phase 3: Poll for encrypted response
|
|
95
|
+
const encryptedResponse = await pollForResponse(relayUrl, sessionId, deadline, () => cancelled, log);
|
|
96
|
+
if (cancelled)
|
|
97
|
+
throw new Error("Session cancelled");
|
|
98
|
+
// Decrypt response (fields are hex-encoded from relay)
|
|
99
|
+
const responseKey = await deriveResponseKey(ephemeralKeyPair.privateKey, phonePublicKey, requestIdBytes);
|
|
100
|
+
const decrypted = decrypt(responseKey, hexDecodeBytes(encryptedResponse.nonce), hexDecodeBytes(encryptedResponse.ciphertext), requestIdBytes);
|
|
101
|
+
const response = JSON.parse(new TextDecoder().decode(decrypted));
|
|
102
|
+
if (!response.approved) {
|
|
103
|
+
setState("error");
|
|
104
|
+
throw new Error("Verification declined by user");
|
|
105
|
+
}
|
|
106
|
+
const result = {
|
|
107
|
+
proof: response.attestation
|
|
108
|
+
? base64urlEncode(new TextEncoder().encode(JSON.stringify(response.attestation)))
|
|
109
|
+
: "",
|
|
110
|
+
nonce,
|
|
111
|
+
domain,
|
|
112
|
+
};
|
|
113
|
+
setState("verified");
|
|
114
|
+
log("Verification complete");
|
|
115
|
+
return result;
|
|
116
|
+
},
|
|
117
|
+
confirmSAS() {
|
|
118
|
+
// No-op for QR mode — SAS confirmation happens on the phone side
|
|
119
|
+
},
|
|
120
|
+
cancel() {
|
|
121
|
+
cancelled = true;
|
|
122
|
+
setState("error");
|
|
123
|
+
},
|
|
124
|
+
onStateChange(callback) {
|
|
125
|
+
stateCallbacks.push(callback);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
return session;
|
|
129
|
+
}
|
|
130
|
+
// --- Relay communication helpers ---
|
|
131
|
+
// All endpoints target the naughtbot-relay service (separate from AckAgent relay).
|
|
132
|
+
// Session creation is IP rate-limited; all other endpoints are unauthenticated.
|
|
133
|
+
// Phone-initiated endpoints (connect, confirm-sas, respond) use BBS+ anonymous auth.
|
|
134
|
+
/** Create a captcha session on the naughtbot-relay server */
|
|
135
|
+
async function createRelaySession(relayUrl, ephemeralPublicKey, log) {
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(`${relayUrl}/api/v1/captcha-sessions`, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: { "Content-Type": "application/json" },
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
requesterEphemeralKeyHex: hexEncode(ephemeralPublicKey),
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
const body = await response.text().catch(() => "");
|
|
146
|
+
log("Failed to create session:", response.status, body);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
const data = await response.json();
|
|
150
|
+
return { sessionId: data.sessionId };
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
log("Error creating session:", error);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Poll relay for phone connection (phone's ephemeral public key) */
|
|
158
|
+
async function pollForPhoneConnection(relayUrl, sessionId, deadline, isCancelled, log) {
|
|
159
|
+
while (Date.now() < deadline && !isCancelled()) {
|
|
160
|
+
try {
|
|
161
|
+
const response = await fetch(`${relayUrl}/api/v1/captcha-sessions/${sessionId}`);
|
|
162
|
+
if (response.ok) {
|
|
163
|
+
const data = await response.json();
|
|
164
|
+
if (data.approverEphemeralKeyHex) {
|
|
165
|
+
log("Phone connected");
|
|
166
|
+
return hexDecodeBytes(data.approverEphemeralKeyHex);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Network error, retry
|
|
172
|
+
}
|
|
173
|
+
await sleep(POLL_INTERVAL_MS);
|
|
174
|
+
}
|
|
175
|
+
if (isCancelled()) {
|
|
176
|
+
throw new Error("Session cancelled");
|
|
177
|
+
}
|
|
178
|
+
throw new Error("Session expired waiting for phone connection");
|
|
179
|
+
}
|
|
180
|
+
/** Poll relay until phone confirms SAS match */
|
|
181
|
+
async function pollForSASConfirmation(relayUrl, sessionId, deadline, isCancelled, log) {
|
|
182
|
+
while (Date.now() < deadline && !isCancelled()) {
|
|
183
|
+
try {
|
|
184
|
+
const response = await fetch(`${relayUrl}/api/v1/captcha-sessions/${sessionId}`);
|
|
185
|
+
if (response.ok) {
|
|
186
|
+
const data = await response.json();
|
|
187
|
+
if (data.status === "sas_confirmed" ||
|
|
188
|
+
data.status === "challenged" ||
|
|
189
|
+
data.status === "responded") {
|
|
190
|
+
log("Phone confirmed SAS match");
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Network error, retry
|
|
197
|
+
}
|
|
198
|
+
await sleep(POLL_INTERVAL_MS);
|
|
199
|
+
}
|
|
200
|
+
if (isCancelled()) {
|
|
201
|
+
throw new Error("Session cancelled");
|
|
202
|
+
}
|
|
203
|
+
throw new Error("Session expired waiting for SAS confirmation");
|
|
204
|
+
}
|
|
205
|
+
/** Post encrypted captcha challenge to relay */
|
|
206
|
+
async function postEncryptedChallenge(relayUrl, sessionId, ciphertext, nonce, log) {
|
|
207
|
+
const response = await fetch(`${relayUrl}/api/v1/captcha-sessions/${sessionId}/challenge`, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
headers: { "Content-Type": "application/json" },
|
|
210
|
+
body: JSON.stringify({
|
|
211
|
+
encryptedChallenge: hexEncode(ciphertext),
|
|
212
|
+
challengeNonce: hexEncode(nonce),
|
|
213
|
+
}),
|
|
214
|
+
});
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
throw new Error(`Failed to post challenge: ${response.status}`);
|
|
217
|
+
}
|
|
218
|
+
log("Challenge posted");
|
|
219
|
+
}
|
|
220
|
+
/** Poll unified status endpoint for encrypted response from phone */
|
|
221
|
+
async function pollForResponse(relayUrl, sessionId, deadline, isCancelled, log) {
|
|
222
|
+
while (Date.now() < deadline && !isCancelled()) {
|
|
223
|
+
try {
|
|
224
|
+
const response = await fetch(`${relayUrl}/api/v1/captcha-sessions/${sessionId}`);
|
|
225
|
+
if (response.ok) {
|
|
226
|
+
const data = await response.json();
|
|
227
|
+
if (data.status === "responded" && data.encryptedResponse && data.responseNonce) {
|
|
228
|
+
log("Response received");
|
|
229
|
+
return {
|
|
230
|
+
ciphertext: data.encryptedResponse,
|
|
231
|
+
nonce: data.responseNonce,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Network error, retry
|
|
238
|
+
}
|
|
239
|
+
await sleep(POLL_INTERVAL_MS);
|
|
240
|
+
}
|
|
241
|
+
if (isCancelled()) {
|
|
242
|
+
throw new Error("Session cancelled");
|
|
243
|
+
}
|
|
244
|
+
throw new Error("Session expired waiting for response");
|
|
245
|
+
}
|
|
246
|
+
function sleep(ms) {
|
|
247
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
248
|
+
}
|
|
249
|
+
/** Hex-encode bytes (lowercase) */
|
|
250
|
+
export function hexEncode(data) {
|
|
251
|
+
return Array.from(data, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
252
|
+
}
|
|
253
|
+
/** Hex-decode string to bytes */
|
|
254
|
+
function hexDecodeBytes(hex) {
|
|
255
|
+
if (hex.length % 2 !== 0) {
|
|
256
|
+
throw new Error("hex string must have even length");
|
|
257
|
+
}
|
|
258
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
259
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
260
|
+
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
261
|
+
}
|
|
262
|
+
return bytes;
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=captcha.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captcha.js","sourceRoot":"","sources":["../src/captcha.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NaughtBot SDK — cryptographic proof of human interaction via biometric verification.
|
|
3
|
+
*
|
|
4
|
+
* Provides a captcha replacement that uses E2E encrypted communication with
|
|
5
|
+
* a user's mobile device for biometric verification and BBS+ anonymous attestation.
|
|
6
|
+
*/
|
|
7
|
+
export type { CaptchaOptions, CaptchaResult, CaptchaSessionState, CaptchaWidgetOptions, SASDisplay, } from "./types.js";
|
|
8
|
+
export { createSession } from "./captcha.js";
|
|
9
|
+
export type { CaptchaSession } from "./captcha.js";
|
|
10
|
+
export { createWidget } from "./widget.js";
|
|
11
|
+
export type { CaptchaWidget } from "./widget.js";
|
|
12
|
+
export { verifyCaptchaProof } from "./verify.js";
|
|
13
|
+
export type { VerificationResult, IssuerPublicKey } from "./verify.js";
|
|
14
|
+
export { createBLESession, isBLESupported } from "./ble.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACV,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGvE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NaughtBot SDK — cryptographic proof of human interaction via biometric verification.
|
|
3
|
+
*
|
|
4
|
+
* Provides a captcha replacement that uses E2E encrypted communication with
|
|
5
|
+
* a user's mobile device for biometric verification and BBS+ anonymous attestation.
|
|
6
|
+
*/
|
|
7
|
+
// Core session API
|
|
8
|
+
export { createSession } from "./captcha.js";
|
|
9
|
+
// Widget API
|
|
10
|
+
export { createWidget } from "./widget.js";
|
|
11
|
+
// Verification
|
|
12
|
+
export { verifyCaptchaProof } from "./verify.js";
|
|
13
|
+
// BLE transport
|
|
14
|
+
export { createBLESession, isBLESupported } from "./ble.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,aAAa;AACb,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,eAAe;AACf,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGjD,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for NaughtBot captcha sessions.
|
|
3
|
+
*/
|
|
4
|
+
/** Options for creating a captcha session */
|
|
5
|
+
export interface CaptchaOptions {
|
|
6
|
+
/** Server-generated nonce for replay protection */
|
|
7
|
+
nonce: string;
|
|
8
|
+
/** Relay server URL (e.g., "https://relay.naughtbot.com"). Required for QR mode. */
|
|
9
|
+
relayUrl?: string;
|
|
10
|
+
/** Login/identity service URL for QR code links (e.g., "https://login.naughtbot.com") */
|
|
11
|
+
loginUrl?: string;
|
|
12
|
+
/** Transport mode */
|
|
13
|
+
mode?: "qr" | "ble" | "auto";
|
|
14
|
+
/** Session timeout in milliseconds (default: 300000 = 5 min) */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
/** Enable debug logging */
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Options for the captcha widget */
|
|
20
|
+
export interface CaptchaWidgetOptions extends CaptchaOptions {
|
|
21
|
+
/** Callback when verification completes successfully */
|
|
22
|
+
onVerified: (result: CaptchaResult) => void;
|
|
23
|
+
/** Callback when an error occurs */
|
|
24
|
+
onError?: (error: Error) => void;
|
|
25
|
+
/** Callback when the session expires */
|
|
26
|
+
onExpired?: () => void;
|
|
27
|
+
/** Callback when session state changes */
|
|
28
|
+
onStateChange?: (state: CaptchaSessionState) => void;
|
|
29
|
+
}
|
|
30
|
+
/** Result of a successful captcha verification */
|
|
31
|
+
export interface CaptchaResult {
|
|
32
|
+
/** BBS+ anonymous proof (base64url) */
|
|
33
|
+
proof: string;
|
|
34
|
+
/** Original nonce (for server-side correlation) */
|
|
35
|
+
nonce: string;
|
|
36
|
+
/** Domain that was verified (e.g., "example.com") */
|
|
37
|
+
domain: string;
|
|
38
|
+
}
|
|
39
|
+
/** State of a captcha session */
|
|
40
|
+
export type CaptchaSessionState = "initializing" | "waiting_for_scan" | "phone_connected" | "sas_verification" | "verifying" | "verified" | "expired" | "error";
|
|
41
|
+
/** SAS (Short Authentication String) for visual verification */
|
|
42
|
+
export interface SASDisplay {
|
|
43
|
+
words: string[];
|
|
44
|
+
emojis: string[];
|
|
45
|
+
wordString: string;
|
|
46
|
+
emojiString: string;
|
|
47
|
+
}
|
|
48
|
+
/** Internal: captcha challenge sent from browser to phone */
|
|
49
|
+
export interface CaptchaChallenge {
|
|
50
|
+
type: "captcha";
|
|
51
|
+
domain: string;
|
|
52
|
+
nonce: string;
|
|
53
|
+
timestamp: number;
|
|
54
|
+
}
|
|
55
|
+
/** Internal: captcha response from phone to browser */
|
|
56
|
+
export interface CaptchaResponse {
|
|
57
|
+
approved: boolean;
|
|
58
|
+
plaintextHash?: string;
|
|
59
|
+
attestation?: {
|
|
60
|
+
"@context": string[];
|
|
61
|
+
type: string[];
|
|
62
|
+
proof: {
|
|
63
|
+
type: string;
|
|
64
|
+
cryptosuite: string;
|
|
65
|
+
proofValue: string;
|
|
66
|
+
created?: string;
|
|
67
|
+
verificationMethod?: string;
|
|
68
|
+
proofPurpose?: string;
|
|
69
|
+
};
|
|
70
|
+
ackagentAnonymousAttestation: {
|
|
71
|
+
pseudonym: string;
|
|
72
|
+
scope: string;
|
|
73
|
+
presentationHeader: string;
|
|
74
|
+
revealedMessages: {
|
|
75
|
+
attestationType: string;
|
|
76
|
+
deviceType: string;
|
|
77
|
+
expiresAt: number;
|
|
78
|
+
};
|
|
79
|
+
issuerPublicKeyId: string;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Default timeout for captcha sessions (5 minutes) */
|
|
84
|
+
export declare const DEFAULT_TIMEOUT_MS = 300000;
|
|
85
|
+
/** Default login URL for QR code links */
|
|
86
|
+
export declare const DEFAULT_LOGIN_URL = "https://login.naughtbot.com";
|
|
87
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IAEd,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,qBAAqB;IACrB,IAAI,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;IAE7B,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,qCAAqC;AACrC,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,wDAAwD;IACxD,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5C,oCAAoC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAEjC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAEvB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;CACtD;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IAEd,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IAEd,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,MAAM,mBAAmB,GAC3B,cAAc,GACd,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAClB,WAAW,GACX,UAAU,GACV,SAAS,GACT,OAAO,CAAC;AAEZ,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE;QACZ,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,KAAK,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;YACb,WAAW,EAAE,MAAM,CAAC;YACpB,UAAU,EAAE,MAAM,CAAC;YACnB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;YAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;QACF,4BAA4B,EAAE;YAC5B,SAAS,EAAE,MAAM,CAAC;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,kBAAkB,EAAE,MAAM,CAAC;YAC3B,gBAAgB,EAAE;gBAChB,eAAe,EAAE,MAAM,CAAC;gBACxB,UAAU,EAAE,MAAM,CAAC;gBACnB,SAAS,EAAE,MAAM,CAAC;aACnB,CAAC;YACF,iBAAiB,EAAE,MAAM,CAAC;SAC3B,CAAC;KACH,CAAC;CACH;AAED,uDAAuD;AACvD,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAE1C,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,gCAAgC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for NaughtBot captcha sessions.
|
|
3
|
+
*/
|
|
4
|
+
/** Default timeout for captcha sessions (5 minutes) */
|
|
5
|
+
export const DEFAULT_TIMEOUT_MS = 300_000;
|
|
6
|
+
/** Default login URL for QR code links */
|
|
7
|
+
export const DEFAULT_LOGIN_URL = "https://login.naughtbot.com";
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0GH,uDAAuD;AACvD,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C,0CAA0C;AAC1C,MAAM,CAAC,MAAM,iBAAiB,GAAG,6BAA6B,CAAC"}
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side BBS+ proof verification for captcha results.
|
|
3
|
+
*
|
|
4
|
+
* This provides a convenience wrapper around @ackagent/web-sdk's BBS+ verification
|
|
5
|
+
* for verifying NaughtBot captcha proofs in the browser. Server-side verification
|
|
6
|
+
* is recommended for production use.
|
|
7
|
+
*/
|
|
8
|
+
import type { CaptchaResult } from "./types.js";
|
|
9
|
+
/** Issuer public key for verifying BBS+ proofs */
|
|
10
|
+
export interface IssuerPublicKey {
|
|
11
|
+
/** Key ID matching the proof's issuerPublicKeyId */
|
|
12
|
+
keyId: string;
|
|
13
|
+
/** BLS12-381 G2 public key (96 bytes, base64url) */
|
|
14
|
+
publicKey: string;
|
|
15
|
+
}
|
|
16
|
+
/** Result of verifying a captcha proof */
|
|
17
|
+
export interface VerificationResult {
|
|
18
|
+
/** Whether the proof is valid */
|
|
19
|
+
valid: boolean;
|
|
20
|
+
/** Error message if verification failed */
|
|
21
|
+
error?: string;
|
|
22
|
+
/** Revealed attestation attributes */
|
|
23
|
+
attestation?: {
|
|
24
|
+
attestationType: string;
|
|
25
|
+
deviceType: string;
|
|
26
|
+
expiresAt: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Verify a NaughtBot captcha proof.
|
|
31
|
+
*
|
|
32
|
+
* This performs client-side verification of the BBS+ anonymous attestation
|
|
33
|
+
* included in the captcha result. For production use, verify server-side
|
|
34
|
+
* using the NaughtBot verification API.
|
|
35
|
+
*
|
|
36
|
+
* @param result - The captcha result to verify
|
|
37
|
+
* @param issuerPublicKey - The issuer's public key for BBS+ verification
|
|
38
|
+
* @returns Verification result
|
|
39
|
+
*/
|
|
40
|
+
export declare function verifyCaptchaProof(result: CaptchaResult, issuerPublicKey: IssuerPublicKey, expectedDomain?: string): Promise<VerificationResult>;
|
|
41
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IAEd,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC;IAEf,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,sCAAsC;IACtC,WAAW,CAAC,EAAE;QACZ,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,eAAe,EAChC,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA+G7B"}
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side BBS+ proof verification for captcha results.
|
|
3
|
+
*
|
|
4
|
+
* This provides a convenience wrapper around @ackagent/web-sdk's BBS+ verification
|
|
5
|
+
* for verifying NaughtBot captcha proofs in the browser. Server-side verification
|
|
6
|
+
* is recommended for production use.
|
|
7
|
+
*/
|
|
8
|
+
import { verifyBbsProofWithPseudonym, base64urlDecode, base64urlEncode } from "@ackagent/web-sdk";
|
|
9
|
+
/** Total number of signer messages in BBS+ credential */
|
|
10
|
+
const BBS_TOTAL_SIGNER_MESSAGES = 4;
|
|
11
|
+
/**
|
|
12
|
+
* Verify a NaughtBot captcha proof.
|
|
13
|
+
*
|
|
14
|
+
* This performs client-side verification of the BBS+ anonymous attestation
|
|
15
|
+
* included in the captcha result. For production use, verify server-side
|
|
16
|
+
* using the NaughtBot verification API.
|
|
17
|
+
*
|
|
18
|
+
* @param result - The captcha result to verify
|
|
19
|
+
* @param issuerPublicKey - The issuer's public key for BBS+ verification
|
|
20
|
+
* @returns Verification result
|
|
21
|
+
*/
|
|
22
|
+
export async function verifyCaptchaProof(result, issuerPublicKey, expectedDomain) {
|
|
23
|
+
if (!result.proof) {
|
|
24
|
+
return { valid: false, error: "No proof in captcha result" };
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// Decode the attestation from the proof field
|
|
28
|
+
const attestationJson = new TextDecoder().decode(base64urlDecode(result.proof));
|
|
29
|
+
const attestation = JSON.parse(attestationJson);
|
|
30
|
+
const payload = attestation.ackagentAnonymousAttestation;
|
|
31
|
+
if (!payload) {
|
|
32
|
+
return { valid: false, error: "Missing ackagentAnonymousAttestation in proof" };
|
|
33
|
+
}
|
|
34
|
+
// Verify the issuer key ID matches
|
|
35
|
+
if (payload.issuerPublicKeyId !== issuerPublicKey.keyId) {
|
|
36
|
+
return {
|
|
37
|
+
valid: false,
|
|
38
|
+
error: `Issuer key mismatch: expected ${issuerPublicKey.keyId}, got ${payload.issuerPublicKeyId}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Verify scope is non-empty (it should be the sessionId)
|
|
42
|
+
if (!payload.scope) {
|
|
43
|
+
return { valid: false, error: "Missing scope in attestation" };
|
|
44
|
+
}
|
|
45
|
+
// Verify domain if expected domain is provided
|
|
46
|
+
// Domain binding comes from the presentation header (challenge-bound), not the scope
|
|
47
|
+
if (expectedDomain && result.domain !== expectedDomain) {
|
|
48
|
+
return {
|
|
49
|
+
valid: false,
|
|
50
|
+
error: `Domain mismatch: expected ${expectedDomain}, got ${result.domain}`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Verify BBS+ proof with pseudonym
|
|
54
|
+
const proofValue = attestation.proof?.proofValue;
|
|
55
|
+
if (!proofValue) {
|
|
56
|
+
return { valid: false, error: "Missing proofValue in attestation" };
|
|
57
|
+
}
|
|
58
|
+
// Strip multibase "u" prefix from proofValue (iOS produces "u" + base64url(proof))
|
|
59
|
+
const rawProofValue = proofValue.startsWith("u") ? proofValue.slice(1) : proofValue;
|
|
60
|
+
// Build disclosed messages map from revealed attributes
|
|
61
|
+
// Signer indices: 0=attestationType, 1=deviceType, 3=expiresAt
|
|
62
|
+
const disclosed = payload.revealedMessages;
|
|
63
|
+
const disclosedMessages = new Map();
|
|
64
|
+
if (disclosed.attestationType) {
|
|
65
|
+
disclosedMessages.set(0, new TextEncoder().encode(disclosed.attestationType));
|
|
66
|
+
}
|
|
67
|
+
if (disclosed.deviceType) {
|
|
68
|
+
disclosedMessages.set(1, new TextEncoder().encode(disclosed.deviceType));
|
|
69
|
+
}
|
|
70
|
+
if (disclosed.expiresAt) {
|
|
71
|
+
const buf = new ArrayBuffer(8);
|
|
72
|
+
new DataView(buf).setBigInt64(0, BigInt(disclosed.expiresAt));
|
|
73
|
+
disclosedMessages.set(3, new Uint8Array(buf));
|
|
74
|
+
}
|
|
75
|
+
// Recompute expected presentation header from result nonce + domain
|
|
76
|
+
// This binds the proof to the specific challenge (sha256(nonce || 0x00 || domain))
|
|
77
|
+
const phMessage = new Uint8Array([
|
|
78
|
+
...new TextEncoder().encode(result.nonce),
|
|
79
|
+
0x00,
|
|
80
|
+
...new TextEncoder().encode(result.domain),
|
|
81
|
+
]);
|
|
82
|
+
const phDigest = new Uint8Array(await crypto.subtle.digest("SHA-256", phMessage));
|
|
83
|
+
// iOS passes base64urlEncode(digest) as a String to generateRelayAuthProof,
|
|
84
|
+
// which UTF-8 encodes it internally. Match that encoding here.
|
|
85
|
+
const phBytes = new TextEncoder().encode(base64urlEncode(phDigest));
|
|
86
|
+
const bbsResult = await verifyBbsProofWithPseudonym(base64urlDecode(issuerPublicKey.publicKey), base64urlDecode(rawProofValue), base64urlDecode(payload.pseudonym), new TextEncoder().encode("ackagent-anonymous-attestation-v2"), phBytes, new TextEncoder().encode(payload.scope), disclosedMessages, BBS_TOTAL_SIGNER_MESSAGES, new Map(), // disclosed committed messages
|
|
87
|
+
[]);
|
|
88
|
+
if (!bbsResult.verified) {
|
|
89
|
+
return { valid: false, error: bbsResult.error || "BBS+ proof verification failed" };
|
|
90
|
+
}
|
|
91
|
+
// Check credential expiry
|
|
92
|
+
const revealed = payload.revealedMessages;
|
|
93
|
+
if (revealed.expiresAt && revealed.expiresAt < Math.floor(Date.now() / 1000)) {
|
|
94
|
+
return { valid: false, error: "Credential has expired" };
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
valid: true,
|
|
98
|
+
attestation: {
|
|
99
|
+
attestationType: revealed.attestationType,
|
|
100
|
+
deviceType: revealed.deviceType,
|
|
101
|
+
expiresAt: revealed.expiresAt,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
valid: false,
|
|
108
|
+
error: error instanceof Error ? error.message : "Verification failed",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"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"}
|
package/dist/widget.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QR code widget for NaughtBot captcha.
|
|
3
|
+
* Renders a QR code, shows SAS words/emojis, handles lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* Uses safe DOM APIs (createElement, textContent) instead of innerHTML.
|
|
6
|
+
*/
|
|
7
|
+
import { type CaptchaSession } from "./captcha.js";
|
|
8
|
+
import type { CaptchaWidgetOptions } from "./types.js";
|
|
9
|
+
/** Widget instance that can be destroyed */
|
|
10
|
+
export interface CaptchaWidget {
|
|
11
|
+
/** Destroy the widget and clean up */
|
|
12
|
+
destroy(): void;
|
|
13
|
+
/** Get the underlying session */
|
|
14
|
+
readonly session: CaptchaSession | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a captcha widget in the specified container.
|
|
18
|
+
*
|
|
19
|
+
* @param container - CSS selector or DOM element
|
|
20
|
+
* @param options - Widget options
|
|
21
|
+
* @returns Widget instance
|
|
22
|
+
*/
|
|
23
|
+
export declare function createWidget(container: string | HTMLElement, options: CaptchaWidgetOptions): Promise<CaptchaWidget>;
|
|
24
|
+
//# sourceMappingURL=widget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EACV,oBAAoB,EAIrB,MAAM,YAAY,CAAC;AAEpB,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,OAAO,IAAI,IAAI,CAAC;IAEhB,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CACzC;AAKD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,GAAG,WAAW,EAC/B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CAwGxB"}
|