From 7f33c431698f6416a9d72ea8a97e812d62ad620c Mon Sep 17 00:00:00 2001 From: jbb01 <32650546+jbb01@users.noreply.github.com> Date: Fri, 12 Sep 2025 11:19:05 +0200 Subject: [PATCH] add challenge scripts --- js/01_welcome.js | 7 + js/02_these_numbers_are_big.js | 21 +++ js/03_are_you_still_doing_this_by_hand.js | 33 +++++ js/04_broken_proof_of_work.js | 10 ++ js/05_what_the_bf.js | 11 ++ js/06_automation_is_not_enough.js | 14 ++ js/07_weird_assembly_machine.js | 15 +++ js/07_weird_assembly_machine.wasm | Bin 0 -> 2202 bytes js/08_revisit_everything.js | 59 +++++++++ js/common_v=2.js | 151 ++++++++++++++++++++++ 10 files changed, 321 insertions(+) create mode 100644 js/01_welcome.js create mode 100644 js/02_these_numbers_are_big.js create mode 100644 js/03_are_you_still_doing_this_by_hand.js create mode 100644 js/04_broken_proof_of_work.js create mode 100644 js/05_what_the_bf.js create mode 100644 js/06_automation_is_not_enough.js create mode 100644 js/07_weird_assembly_machine.js create mode 100644 js/07_weird_assembly_machine.wasm create mode 100644 js/08_revisit_everything.js create mode 100644 js/common_v=2.js diff --git a/js/01_welcome.js b/js/01_welcome.js new file mode 100644 index 0000000..f9f5dbb --- /dev/null +++ b/js/01_welcome.js @@ -0,0 +1,7 @@ +function onClick() { + if(n >= 10000n) { + return; + } + n++; + x = n % 7n; +} diff --git a/js/02_these_numbers_are_big.js b/js/02_these_numbers_are_big.js new file mode 100644 index 0000000..214f8b4 --- /dev/null +++ b/js/02_these_numbers_are_big.js @@ -0,0 +1,21 @@ +const m = 14004392365098131090160062970945115111185775413941111064876648140973294115502980816410773368597517292734034227298996122159833675150497554142801209096513652073059992938078366061434391648276904643753267405058183481162693381822800709938988762923n; +let h; + +async function prepare() { + if(n == 10000n) { + h = await sha256(name); + } +} + +function onClick() { + if(n >= 20000n) { + return; + } + if(n == 10000n) { + x += h; + } + n++; + for(let i = 0; i < 100; i++) { + x = pow(x, 65537n, m); + } +} diff --git a/js/03_are_you_still_doing_this_by_hand.js b/js/03_are_you_still_doing_this_by_hand.js new file mode 100644 index 0000000..bbb6623 --- /dev/null +++ b/js/03_are_you_still_doing_this_by_hand.js @@ -0,0 +1,33 @@ +const p = 12345679943n; + +function onClick() { + if(n >= 30000n) { + return; + } + n++; + x = log(42n, 1n + (x+n) % (p-1n), p); +} + +function log(g, b, m) { + const s = Math.ceil(Number(m)**.5); + const r = new Map(); + let a = b % m; + if(a == 1n) { + return 0n; + } + for(let i = 0; i < s; i++) { + r.set(a, i); + a *= g; + a %= m; + } + const gs = pow(g, BigInt(s), m); + a = gs; + for(let j = 1; j <= s; j++) { + const i = r.get(a); + if(i !== undefined) { + return BigInt(j*s-i); + } + a *= gs; + a %= m; + } +} diff --git a/js/04_broken_proof_of_work.js b/js/04_broken_proof_of_work.js new file mode 100644 index 0000000..da588f4 --- /dev/null +++ b/js/04_broken_proof_of_work.js @@ -0,0 +1,10 @@ +function onClick() { + if(n >= 10n**8n) { + return; + } + n++; + for(let i = 0; i < 10000; i++) { + x += 41n; + x ^= 42n; + } +} diff --git a/js/05_what_the_bf.js b/js/05_what_the_bf.js new file mode 100644 index 0000000..dc4e311 --- /dev/null +++ b/js/05_what_the_bf.js @@ -0,0 +1,11 @@ +const f = ((ο)=>((o)=>o(((o(((ο*o([!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]))+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]](-[+!+[]]+[!+[]+!+[]]))*o([+!+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]-([+!+[]]+[+!+[]]))+o([+!+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]-+!+[]))+[])[(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]](+[],-[+!+[]]+[!+[]+!+[]])))(BigInt)); + +function onClick() { + if(n >= 10n**12n) { + return; + } + n++; + for(let i = 0; i < 100; i++) { + x = f(x); + } +} diff --git a/js/06_automation_is_not_enough.js b/js/06_automation_is_not_enough.js new file mode 100644 index 0000000..ff9f15a --- /dev/null +++ b/js/06_automation_is_not_enough.js @@ -0,0 +1,14 @@ +const m = 14004392365098131090160062970945115111185775413941111064876648140973294115502980816410773368597517292734034227298996122159833675150497554142801209096513652073059992938078366061434391648276904643753267405058183481162693381822800709938988762923n; + +function onClick() { + if(n >= 10n**16n) { + return; + } + n++; + const a = pow(n, 65537n, m); + if(a % 1466928606874115117499939299261n == 49119078231137394008451554322n) { + x += x; + } + x += a; + x %= m; +} diff --git a/js/07_weird_assembly_machine.js b/js/07_weird_assembly_machine.js new file mode 100644 index 0000000..114d52d --- /dev/null +++ b/js/07_weird_assembly_machine.js @@ -0,0 +1,15 @@ +let f; + +async function prepare() { + const get = fetch('07_weird_assembly_machine.wasm'); + const obj = await WebAssembly.instantiateStreaming(get); + f = obj.instance.exports.f; +} + +function onClick() { + if(n >= 10n**18n) { + return; + } + n++; + x = BigInt.asUintN(64, f(x, n)); +} diff --git a/js/07_weird_assembly_machine.wasm b/js/07_weird_assembly_machine.wasm new file mode 100644 index 0000000000000000000000000000000000000000..cfd16f6a3dd6dd9ff45cfb42857b83ea05459017 GIT binary patch literal 2202 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 10n**20n) { + return; + } + n++; + const w = x % 42n; + let y = x / 42n; + for(let i = 0; i < 100; i++) { + y = pow(y, 65537n, m[w]); + } + x = 42n * y + w; +} + +/* Lbh pna punatr gur pbybe bs lbhe anzr jvgubhg punatvat lbhe anzr. */ diff --git a/js/common_v=2.js b/js/common_v=2.js new file mode 100644 index 0000000..25e1211 --- /dev/null +++ b/js/common_v=2.js @@ -0,0 +1,151 @@ +/* + NOTE: this just contains user interface logic; + there is probably not much interesting stuff here +*/ + +let name, n, x, n_old, n_last; + +async function init() { + const params = (new URL(document.URL)).searchParams; + if(params.has('name')) { + name = params.get('name'); + } else { + /* missing name, redirect to start screen */ + location.replace('.'); + return; + } + /* people can do more than 2^53 button clicks, so we need big integers */ + if(params.has('n') && params.has('x')) { + n = BigInt(params.get('n')); + x = BigInt(params.get('x')); + } else { + n = 0n; + x = 0n; + } + n_old = 0n; + n_last = -1n; + if(typeof prepare == 'function') { + await prepare(); + } + const button = document.querySelector('button'); + button.textContent = n; + button.addEventListener('click', onClick); + setInterval(() => { + if(n > n_last) { + /* to spare the browser, we do this at most 10 times per second */ + const params = new URLSearchParams({name, n, x}); + history.replaceState(null, '', '?' + params); + button.textContent = n; + n_last = n; + } + }, 100); + communicate(); +} + +document.addEventListener('DOMContentLoaded', init); + +async function communicate() { + const error = document.querySelector('#error'); + try { + /* only submit increased click counts, otherwise just fetch scores */ + const path = 'server.php' + ((n_last > n_old) ? location.search : ''); + const result = await fetch(path); + if(!result.ok) { + throw new Error(`${result.status} ${result.statusText}`); + } + if(n_last > n_old) { + n_old = n_last; + } + const json = await result.json(); + if(json.flag && !location.pathname.endsWith('/' + json.flag)) { + /* advance to next level */ + location.replace(json.flag + location.search); + return; + } + if(json.scores) { + displayScores(json.scores, json.time); + } + if(json.error) { + throw new Error(json.error); + } + const timeStr = new Date(json.time * 1000).toLocaleTimeString('de-DE'); + error.textContent = `Zuletzt aktualisiert: ${timeStr}`; + } catch(e) { + console.warn(e); + error.textContent = e; + } + setTimeout(communicate, 1000); +} + +function displayScores(scores, time) { + const table = document.querySelector('table'); + while(table.rows.length > 1) { + table.deleteRow(-1); + } + scores.sort((a, b) => { + const n_a = BigInt(a.n); + const n_b = BigInt(b.n); + if(n_a > n_b) { + return -1; + } + if(n_a < n_b) { + return 1; + } + if(a.time < b.time) { + return -1; + } + if(a.time > b.time) { + return 1; + } + return 0; + }); + scores.forEach((entry) => { + const row = table.insertRow(); + + const nameCell = row.insertCell(); + /* protect against unicode bidi control characters */ + const bdi = document.createElement('bdi'); + bdi.textContent = entry.name; + nameCell.appendChild(bdi); + nameCell.title = entry.name; + + const timeCell = row.insertCell(); + const date = new Date(entry.time * 1000); + if(time - entry.time < 86400) { + timeCell.textContent = date.toLocaleTimeString('de-DE'); + } else { + timeCell.textContent = date.toLocaleDateString('de-DE'); + } + timeCell.title = date.toLocaleString('de-DE'); + + const nCell = row.insertCell(); + nCell.textContent = entry.n; + nCell.title = entry.n; + }); +} + +/* compute SHA-256 digest represented as integer (big endian) */ +async function sha256(str) { + const msg = new TextEncoder().encode(str); + const buffer = await crypto.subtle.digest('SHA-256', msg); + const bytes = new Uint8Array(buffer); + let val = 0n; + for(const b of bytes) { + val = (val << 8n) | BigInt(b); + } + return val; +} + +/* compute a^k modulo m */ +function pow(a, k, m) { + let b = 1n; + for(; k; k >>= 1n) { + if(k & 1n) { + b *= a; + b %= m; + } + a *= a; + a %= m; + } + return b; +}