@cap.js/widget 0.0.11 → 0.0.12
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 +1 -1
- package/src/cap.js +71 -17
package/package.json
CHANGED
package/src/cap.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
});
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
// MARK: Widget
|
|
22
23
|
class CapWidget extends HTMLElement {
|
|
23
24
|
#workerUrl = "";
|
|
24
25
|
#resetTimer = null;
|
|
@@ -127,11 +128,7 @@
|
|
|
127
128
|
method: "POST",
|
|
128
129
|
})
|
|
129
130
|
).json();
|
|
130
|
-
const solutions = await this.solveChallenges(
|
|
131
|
-
challenge,
|
|
132
|
-
target,
|
|
133
|
-
token,
|
|
134
|
-
});
|
|
131
|
+
const solutions = await this.solveChallenges(challenge);
|
|
135
132
|
|
|
136
133
|
const resp = await (
|
|
137
134
|
await fetch(`${apiEndpoint}redeem`, {
|
|
@@ -168,7 +165,7 @@
|
|
|
168
165
|
}
|
|
169
166
|
}
|
|
170
167
|
|
|
171
|
-
async solveChallenges(
|
|
168
|
+
async solveChallenges(challenge) {
|
|
172
169
|
const total = challenge.length;
|
|
173
170
|
let completed = 0;
|
|
174
171
|
|
|
@@ -239,7 +236,7 @@
|
|
|
239
236
|
this.#div.setAttribute("role", "button");
|
|
240
237
|
this.#div.setAttribute("tabindex", "0");
|
|
241
238
|
this.#div.setAttribute("disabled", "true");
|
|
242
|
-
this.#div.innerHTML = `<div class="checkbox"></div><p>I'm a human</p><a href="
|
|
239
|
+
this.#div.innerHTML = `<div class="checkbox"></div><p>I'm a human</p><a href="https://cap.tiagorangel.com/" class="credits" target="_blank" rel="follow noopener"><span>Secured by </span>Cap</a>`;
|
|
243
240
|
this.#shadow.innerHTML = `<style>.captcha{background-color:var(--cap-background);border:1px solid var(--cap-border-color);border-radius:var(--cap-border-radius);width:var(--cap-widget-width);display:flex;align-items:center;padding:var(--cap-widget-padding);gap:var(--cap-gap);cursor:pointer;transition:filter var(--cap-transition-duration),transform var(--cap-transition-duration);position:relative;-webkit-tap-highlight-color:rgba(255,255,255,0);overflow:hidden;color:var(--cap-color)}.captcha:hover{filter:var(--cap-hover-filter)}.captcha:not([disabled]):active{transform:scale(var(--cap-active-scale))}.checkbox{width:var(--cap-checkbox-size);height:var(--cap-checkbox-size);border:var(--cap-checkbox-border);border-radius:var(--cap-checkbox-border-radius);background-color:var(--cap-checkbox-background);transition:opacity var(--cap-transition-duration);margin-top:var(--cap-checkbox-margin);margin-bottom:var(--cap-checkbox-margin)}.captcha *{font-family:var(--cap-font)}.captcha p{margin:0;font-weight:500;font-size:15px;user-select:none;transition:opacity var(--cap-transition-duration)}.captcha[data-state=verifying] .checkbox{background: none;display:flex;align-items:center;justify-content:center;transform: scale(1.1);border: none;border-radius: 50%;background: conic-gradient(var(--cap-spinner-color) 0%, var(--cap-spinner-color) var(--progress, 0%), var(--cap-spinner-background-color) var(--progress, 0%), var(--cap-spinner-background-color) 100%);position: relative;}.captcha[data-state=verifying] .checkbox::after {content: "";background-color: var(--cap-background);width: calc(100% - var(--cap-spinner-thickness));height: calc(100% - var(--cap-spinner-thickness));border-radius: 50%;margin:calc(var(--cap-spinner-thickness) / 2)}.captcha[data-state=done] .checkbox{border:1px solid transparent;background-image:var(--cap-checkmark);background-size:cover}.captcha[data-state=error] .checkbox{border:1px solid transparent;background-image:var(--cap-error-cross);background-size:cover}.captcha[disabled]{
|
|
244
241
|
cursor:not-allowed}.captcha[disabled][data-state=verifying]{cursor:progress}.captcha[disabled][data-state=done]{cursor:default}.captcha .credits{position:absolute;bottom:10px;right:10px;font-size:var(--cap-credits-font-size);color:var(--cap-color);opacity:var(--cap-opacity-hover)}.captcha .credits span{display:none;text-decoration:underline}.captcha .credits:hover span{display:inline-block}</style>`;
|
|
245
242
|
|
|
@@ -370,6 +367,7 @@
|
|
|
370
367
|
}
|
|
371
368
|
}
|
|
372
369
|
|
|
370
|
+
// MARK: Invisible
|
|
373
371
|
class Cap {
|
|
374
372
|
constructor(config = {}, el) {
|
|
375
373
|
let widget = el || document.createElement("cap-widget");
|
|
@@ -410,21 +408,81 @@
|
|
|
410
408
|
);
|
|
411
409
|
document.adoptedStyleSheets.push(sheet);
|
|
412
410
|
|
|
411
|
+
// MARK: Solver worker
|
|
413
412
|
const workerFunct = function () {
|
|
414
413
|
let hasher;
|
|
415
414
|
|
|
416
415
|
self.onmessage = async ({ data: { salt, target } }) => {
|
|
417
|
-
if (!hasher) {
|
|
418
|
-
hasher = await hashwasm.createSHA256();
|
|
419
|
-
}
|
|
420
|
-
|
|
421
416
|
let nonce = 0;
|
|
422
417
|
const batchSize = 50000;
|
|
423
|
-
const reportInterval = 500000;
|
|
424
418
|
let processed = 0;
|
|
419
|
+
const encoder = new TextEncoder();
|
|
420
|
+
|
|
421
|
+
// Alternative solver in case WASM is not available
|
|
422
|
+
if (
|
|
423
|
+
!(
|
|
424
|
+
typeof WebAssembly === "object" &&
|
|
425
|
+
typeof WebAssembly.instantiate === "function"
|
|
426
|
+
)
|
|
427
|
+
) {
|
|
428
|
+
console.log("[cap] WASM not enabled, falling back to crypto.subtle\nThis is significanty slower than the WASM implementation");
|
|
429
|
+
|
|
430
|
+
const targetBytes = new Uint8Array(target.length / 2);
|
|
431
|
+
for (let k = 0; k < targetBytes.length; k++) {
|
|
432
|
+
targetBytes[k] = parseInt(target.substring(k * 2, k * 2 + 2), 16);
|
|
433
|
+
}
|
|
434
|
+
const targetBytesLength = targetBytes.length;
|
|
435
|
+
|
|
436
|
+
while (true) {
|
|
437
|
+
try {
|
|
438
|
+
for (let i = 0; i < batchSize; i++) {
|
|
439
|
+
const inputString = salt + nonce;
|
|
440
|
+
const inputBytes = encoder.encode(inputString);
|
|
441
|
+
|
|
442
|
+
const hashBuffer = await crypto.subtle.digest(
|
|
443
|
+
"SHA-256",
|
|
444
|
+
inputBytes
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
const hashBytes = new Uint8Array(
|
|
448
|
+
hashBuffer,
|
|
449
|
+
0,
|
|
450
|
+
targetBytesLength
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
let matches = true;
|
|
454
|
+
for (let k = 0; k < targetBytesLength; k++) {
|
|
455
|
+
if (hashBytes[k] !== targetBytes[k]) {
|
|
456
|
+
matches = false;
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (matches) {
|
|
462
|
+
self.postMessage({ nonce, found: true });
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
nonce++;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
processed += batchSize;
|
|
470
|
+
} catch (error) {
|
|
471
|
+
console.error("[cap] fallback worker error", error);
|
|
472
|
+
self.postMessage({
|
|
473
|
+
found: false,
|
|
474
|
+
error: error.message,
|
|
475
|
+
});
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (!hasher) {
|
|
482
|
+
hasher = await hashwasm.createSHA256();
|
|
483
|
+
}
|
|
425
484
|
|
|
426
485
|
const buffer = new Uint8Array(128);
|
|
427
|
-
const encoder = new TextEncoder();
|
|
428
486
|
|
|
429
487
|
while (true) {
|
|
430
488
|
try {
|
|
@@ -446,10 +504,6 @@
|
|
|
446
504
|
}
|
|
447
505
|
|
|
448
506
|
processed += batchSize;
|
|
449
|
-
if (processed >= reportInterval) {
|
|
450
|
-
self.postMessage({ nonce, found: false });
|
|
451
|
-
processed = 0;
|
|
452
|
-
}
|
|
453
507
|
} catch (error) {
|
|
454
508
|
self.postMessage({ found: false, error: error.message });
|
|
455
509
|
return;
|