package main import ( "html" "log" "text/template" ) var tmpl *template.Template func init() { var err error tmpl, err = template.New("powxy").Parse(` <!DOCTYPE html> <html> <head> <title>Proof of Work Challenge</title> <script> /* @licstart The following is the entire license notice for the JavaScript code in this page. Copyright (C) 2025 Runxi Yu The JavaScript code in this page is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License (GNU GPL) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The code is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. As additional permission under GNU GPL version 3 section 7, you may distribute non-source (e.g., minimized or compacted) forms of that code without the copy of the GNU GPL normally required by section 4, provided you include this license notice and a URL through which recipients can access the Corresponding Source. @licend The above is the entire license notice for the JavaScript code in this page. */ </script> </head> <body> <h1>Proof of Work Challenge</h1> <p>This site is protected by <a href="https://forge.lindenii.runxiyu.org/powxy/:/repos/powxy/">Powxy</a>.</p> <p>You must complete this proof of work challenge before you could access this site.</p> {{- if .Message }} <p><strong>{{ .Message }}</strong></p> {{- end }} <p>Select an nonce shorter than or equal to 32 bytes, such that when it is appended to the decoded form of the following base64 string, and a SHA-256 hash is taken as a whole, the first {{ .NeedBits }} bits of the SHA-256 hash are zeros. Within one octet, higher bits are considered to be in front of lower bits.</p> <p>{{ .UnsignedTokenBase64 }}</p> <form method="POST"> <p> Encode your selected nonce in base64 and submit it below. </p> <p> Please note that if your submission is successful, you will be given a cookie that will allow you to access this site for a period of time without having to complete the challenge again. By pressing the submit button, you agree to be given cookies for this purpose. </p> <input name="powxy" type="text" /> <input type="submit" value="Submit" /> </form> <p id="solver_status"></p> <details> <summary>Offline solver program</summary> <pre>` + html.EscapeString(solverProgram) + `</pre> </details> </body> <script> document.addEventListener("DOMContentLoaded", function() { let challenge_b64 = "{{.UnsignedTokenBase64}}"; let difficulty = {{.NeedBits}}; let form = document.querySelector("form"); let field = form.querySelector("input[name='powxy']"); let status_el = document.getElementById("solver_status"); if (!window.crypto || !window.crypto.subtle) { status_el.textContent = "SubtleCrypto not available. You must solve the challenge externally."; return; } status_el.textContent = "SubtleCrypto detected. Attempting to solve in JS..."; let solver_active = true; form.addEventListener("submit", function() { solver_active = false; }); async function solve_pow() { let token_bytes = Uint8Array.from( atob(challenge_b64), ch => ch.charCodeAt(0) ); let nonce = 0n; let buf = new ArrayBuffer(8); let view = new DataView(buf); while (solver_active) { view.setBigUint64(0, nonce, true); let candidate = new Uint8Array(token_bytes.length + 8); candidate.set(token_bytes, 0); candidate.set(new Uint8Array(buf), token_bytes.length); let digest_buffer = await crypto.subtle.digest("SHA-256", candidate); let digest = new Uint8Array(digest_buffer); if (has_leading_zero_bits(digest, difficulty)) { let nonce_str = String.fromCharCode(...new Uint8Array(buf)); field.value = btoa(nonce_str); status_el.textContent = "Solution found."; return; } nonce++; // Update status every 256 tries if ((nonce & 0x00FFn) === 0n) { status_el.textContent = "Attempting to solve automatically via SubtleCrypto. Tried " + nonce + " candidates so far..."; await new Promise(r => setTimeout(r, 0)); } } } function has_leading_zero_bits(digest, bits) { let full_bytes = bits >>> 3; for (let i = 0; i < full_bytes; i++) { if (digest[i] !== 0) { return false; } } let remainder = bits & 7; if (remainder !== 0) { let mask = 0xFF << (8 - remainder); if ((digest[full_bytes] & mask) !== 0) { return false; } } return true; } solve_pow(); }); </script> </html> `) if err != nil { log.Fatal(err) } }