commit 44f96fffe9aeebf83438a389448dcd63cf4225b3 Author: overflowerror Date: Thu Aug 15 22:48:04 2024 +0200 demo & proof of concept diff --git a/index.html b/index.html new file mode 100644 index 0000000..6035072 --- /dev/null +++ b/index.html @@ -0,0 +1,106 @@ + + + + + + + + +
+
+ I am not a robot. +
+
+ + diff --git a/main.js b/main.js new file mode 100644 index 0000000..53e4f48 --- /dev/null +++ b/main.js @@ -0,0 +1,53 @@ +const hexCharset = "0123456789abcdef".split(""); +const suffixCharset = [ + "0123456789", + "abcdefghijklmnopqrstuvwxyz", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "+-", +].flatMap(set => set.split("")); +const suffixCharsetBits = 6; + +const sha256 = "SHA-256"; + +Uint8Array.prototype.toHex = function() { + return [...this].map(c => hexCharset[c >> 4] + hexCharset[c & 15]).join(""); +}; + +Uint8Array.prototype.hasPrefix = function(array, bits) { + for(let i = 0; i < array.length && i * 8 < bits; i++) { + const bitsForByte = Math.min(8, bits - i * 8); + const bitMask = ((1 << bitsForByte) - 1) << (8 - bitsForByte); + + if ((this[i] & bitMask) != (array[i] & bitMask)) { + return false; + } + } + return true; +}; + +async function digest(algo, input) { + return new Uint8Array(await crypto.subtle.digest(algo, new TextEncoder().encode(input))); +} + +function makeSuffix(index) { + let result = ""; + + while (index > 0) { + result += suffixCharset[index & ((1 << suffixCharsetBits) - 1)]; + index >>= suffixCharsetBits; + } + + return result; +} + +async function findHashWithPrefix(hashPrefixBits, inputPrefix) { + const hashPrefix = new Uint8Array(Array(Math.ceil(hashPrefixBits / 8)).map(c => 0)); + let iteration = 0; + + do { + var message = inputPrefix + makeSuffix(iteration++) + var hash = await digest(sha256, message); + } while (!hash.hasPrefix(hashPrefix, hashPrefixBits)); + + return message; +}