mirror of
https://github.com/sigmasternchen/axowall
synced 2025-03-15 08:38:55 +00:00
reduce size
This commit is contained in:
parent
52309a8e21
commit
c32124b3fc
6 changed files with 43 additions and 61 deletions
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"algo": "SHA-256",
|
"algo": "SHA-256",
|
||||||
"prefixBits": "15",
|
"prefixBits": 15,
|
||||||
"input": "challenge:"
|
"input": "challenge:"
|
||||||
}
|
}
|
|
@ -5,6 +5,5 @@ export type Challenge = {
|
||||||
input: string,
|
input: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateChallenge(challenge: Challenge): boolean {
|
export const validateChallenge = (challenge: Challenge): boolean =>
|
||||||
return !!challenge.algo && challenge.prefixBits > 0 && !!challenge.input;
|
!!challenge.algo && challenge.prefixBits > 0 && !!challenge.input;
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
const suffixCharset = [
|
|
||||||
"0123456789",
|
|
||||||
"abcdefghijklmnopqrstuvwxyz",
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
||||||
"+-",
|
|
||||||
].flatMap(set => set.split(""));
|
|
||||||
const suffixCharsetBits = 6;
|
|
||||||
|
|
||||||
export function makeSuffix(index: number): string {
|
|
||||||
let result = "";
|
|
||||||
|
|
||||||
while (index > 0) {
|
|
||||||
result += suffixCharset[index & ((1 << suffixCharsetBits) - 1)];
|
|
||||||
index >>= suffixCharsetBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -2,7 +2,7 @@
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
padding: 19px;
|
padding: 19px;
|
||||||
border: 1px solid grey;
|
border: 1px solid #888;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
|
@ -19,18 +19,18 @@
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: white;
|
background-color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid black;
|
border: 1px solid #000;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.captcha .checkbox:hover {
|
.captcha .checkbox:hover {
|
||||||
background-color: lightgrey;
|
background-color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.captcha .checkbox.checked {
|
.captcha .checkbox.checked {
|
||||||
background-color: #2196F3;
|
background-color: #29F;
|
||||||
}
|
}
|
||||||
|
|
||||||
.captcha .checkbox.checked::before {
|
.captcha .checkbox.checked::before {
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
height: 15px;
|
height: 15px;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
left: 9px;
|
left: 9px;
|
||||||
border: white solid;
|
border: #fff solid;
|
||||||
border-width: 0 5px 5px 0;
|
border-width: 0 5px 5px 0;
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
@ -59,11 +59,11 @@
|
||||||
height: 17px;
|
height: 17px;
|
||||||
border: 4px solid;
|
border: 4px solid;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-color: black transparent black transparent;
|
border-color: #000 transparent #000 transparent;
|
||||||
animation: captchaLoading infinite 1s;
|
animation: _aw_l infinite 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes captchaLoading {
|
@keyframes _aw_l {
|
||||||
to {
|
to {
|
||||||
transform: rotate(.5turn)
|
transform: rotate(.5turn)
|
||||||
}
|
}
|
||||||
|
|
10
src/hash.ts
10
src/hash.ts
|
@ -1,6 +1,3 @@
|
||||||
const hexCharset = "0123456789abcdef".split("");
|
|
||||||
|
|
||||||
export const sha256: AlgorithmIdentifier = "SHA-256";
|
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Uint8Array {
|
interface Uint8Array {
|
||||||
|
@ -10,7 +7,7 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8Array.prototype.toHex = function(): string {
|
Uint8Array.prototype.toHex = function(): string {
|
||||||
return [...this].map(c => hexCharset[c >> 4] + hexCharset[c & 15]).join("");
|
return [...this].map(c => (c >> 4).toString(16) + (c & 15).toString(16)).join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
Uint8Array.prototype.hasPrefix = function(prefix: Uint8Array, bits: number): boolean {
|
Uint8Array.prototype.hasPrefix = function(prefix: Uint8Array, bits: number): boolean {
|
||||||
|
@ -27,6 +24,5 @@ Uint8Array.prototype.hasPrefix = function(prefix: Uint8Array, bits: number): boo
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function digest(algo: AlgorithmIdentifier, input: string): Promise<Uint8Array> {
|
export const digest = async (algo: AlgorithmIdentifier, input: string): Promise<Uint8Array> =>
|
||||||
return new Uint8Array(await crypto.subtle.digest(algo, new TextEncoder().encode(input)));
|
new Uint8Array(await crypto.subtle.digest(algo, new TextEncoder().encode(input)));
|
||||||
}
|
|
||||||
|
|
51
src/main.ts
51
src/main.ts
|
@ -1,16 +1,19 @@
|
||||||
import {makeSuffix} from "./content";
|
import {digest} from "./hash";
|
||||||
import {digest, sha256} from "./hash";
|
|
||||||
|
|
||||||
import "./default-styles.css";
|
import "./default-styles.css";
|
||||||
import {Challenge, validateChallenge} from "./challenge";
|
import {Challenge, validateChallenge} from "./challenge";
|
||||||
|
|
||||||
async function findHashWithPrefix(hashPrefixBits: number, inputPrefix: string): Promise<string> {
|
const CLASS_CHECKBOX = "checkbox";
|
||||||
|
const CLASS_LOADING = "loading";
|
||||||
|
const CLASS_CHECKED = "checked";
|
||||||
|
|
||||||
|
const findHashWithPrefix = async (algo: string, hashPrefixBits: number, inputPrefix: string): Promise<string> => {
|
||||||
const hashPrefix = new Uint8Array(Array(Math.ceil(hashPrefixBits / 8)).map(_ => 0));
|
const hashPrefix = new Uint8Array(Array(Math.ceil(hashPrefixBits / 8)).map(_ => 0));
|
||||||
let iteration = 0;
|
let iteration = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
var message = inputPrefix + makeSuffix(iteration++);
|
var message = inputPrefix + (iteration++).toString(36);
|
||||||
var hash = await digest(sha256, message);
|
var hash = await digest(algo, message);
|
||||||
} while (!hash.hasPrefix(hashPrefix, hashPrefixBits));
|
} while (!hash.hasPrefix(hashPrefix, hashPrefixBits));
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
|
@ -18,54 +21,56 @@ async function findHashWithPrefix(hashPrefixBits: number, inputPrefix: string):
|
||||||
|
|
||||||
function initCaptchaContentAndGetCheckbox(captcha: Element): Element {
|
function initCaptchaContentAndGetCheckbox(captcha: Element): Element {
|
||||||
const checkbox = document.createElement("div");
|
const checkbox = document.createElement("div");
|
||||||
checkbox.classList.add("checkbox");
|
checkbox.classList.add(CLASS_CHECKBOX, CLASS_LOADING);
|
||||||
captcha.append(checkbox);
|
|
||||||
|
|
||||||
const text = document.createElement("span");
|
const text = document.createElement("span");
|
||||||
text.innerText = "I am not a robot";
|
text.innerText = "I am not a robot";
|
||||||
captcha.append(text);
|
|
||||||
|
captcha.append(checkbox, text);
|
||||||
|
|
||||||
return checkbox;
|
return checkbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleChecked = (checkbox: Element) =>
|
||||||
|
checkbox.classList.toggle(CLASS_CHECKED);
|
||||||
|
|
||||||
|
const toggleLoading = (checkbox: Element) =>
|
||||||
|
checkbox.classList.toggle(CLASS_LOADING);
|
||||||
|
|
||||||
function prepareChallengeExecution(challenge: Challenge): () => Promise<void> {
|
function prepareChallengeExecution(challenge: Challenge): () => Promise<void> {
|
||||||
return async function() {
|
return async function() {
|
||||||
console.log("Calculating...");
|
console.log("Calculating...");
|
||||||
|
|
||||||
this.classList.add("loading");
|
toggleLoading(this);
|
||||||
|
|
||||||
const response = await findHashWithPrefix(challenge.prefixBits, challenge.input);
|
const response = await findHashWithPrefix(challenge.algo, challenge.prefixBits, challenge.input);
|
||||||
console.log("Challenge Response: " + response);
|
console.log("Challenge Response: " + response);
|
||||||
|
|
||||||
this.classList.remove("loading");
|
toggleLoading(this);
|
||||||
this.classList.add("checked");
|
toggleChecked(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function prepareCaptcha(captcha: Element) {
|
const prepareCaptcha = async (captcha: Element) => {
|
||||||
const challengeUrl = captcha.getAttribute("data-challenge-url");
|
const challengeUrl = captcha.getAttribute("data-challenge-url");
|
||||||
if (!challengeUrl) {
|
if (!challengeUrl) {
|
||||||
console.warn("No challenge URL found.");
|
throw "No challenge URL found.";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkbox = initCaptchaContentAndGetCheckbox(captcha);
|
const checkbox = initCaptchaContentAndGetCheckbox(captcha);
|
||||||
checkbox.classList.add("loading");
|
|
||||||
|
|
||||||
const challengeResponse = await fetch(challengeUrl);
|
const challengeResponse = await fetch(challengeUrl);
|
||||||
const challenge = await challengeResponse.json() as Challenge;
|
const challenge = await challengeResponse.json() as Challenge;
|
||||||
|
|
||||||
if (!validateChallenge(challenge)) {
|
if (!validateChallenge(challenge)) {
|
||||||
console.warn("Challenge is invalid.");
|
throw "Challenge is invalid.";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox.classList.remove("loading");
|
toggleLoading(checkbox);
|
||||||
|
|
||||||
checkbox.addEventListener("click", prepareChallengeExecution(challenge));
|
checkbox.addEventListener("click", prepareChallengeExecution(challenge));
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () =>
|
||||||
console.log("load");
|
[...document.getElementsByClassName("captcha")].forEach(prepareCaptcha)
|
||||||
[...document.getElementsByClassName("captcha")].forEach(prepareCaptcha);
|
);
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in a new issue