From cfab3d0b8f63f81e52ef4ff6ee6e4a477e3b9476 Mon Sep 17 00:00:00 2001
From: Zoe <62722391+juls0730@users.noreply.github.com>
Date: Mon, 17 Nov 2025 16:12:26 +0000
Subject: [PATCH] Initial commit
Once again a weird place to commit, I have already done a lot of work, but I am just bad at using git, okay.
---
.gitignore | 0
.vscode/settings.json | 6 +
.vscode/tasks.json | 10 +
LICENSE | 23 +
NOTES.md | 7 +
README.md | 19 +
example-app/.example.env | 1 +
example-app/.gitignore | 5 +
example-app/.vscode/settings.json | 6 +
example-app/README.md | 50 +
example-app/app/app.vue | 17 +
example-app/app/pages/index.vue | 411 +
example-app/app/pages/widget.vue | 38 +
example-app/app/plugins/pow-captcha.ts | 3 +
example-app/app/utils/worker-name.ts | 6 +
example-app/app/utils/worker.ts | 170 +
example-app/bun.lock | 2283 +++++
example-app/config.toml | 7 +
example-app/nuxt.config.ts | 57 +
example-app/package-lock.json | 8722 +++++++++++++++++
example-app/package.json | 27 +
example-app/server/api/pow/challenge.get.ts | 44 +
example-app/server/api/pow/challenge.post.ts | 45 +
example-app/server/api/pow/difficulty.get.ts | 19 +
example-app/server/api/pow/difficulty.put.ts | 35 +
.../server/middleware/secure-context.ts | 10 +
example-app/server/utils/config.ts | 42 +
example-app/server/utils/pow.ts | 6 +
example-app/tsconfig.json | 17 +
example-app/uno.config.ts | 11 +
justfile | 26 +
packages/lib/.gitignore | 2 +
packages/lib/README.md | 60 +
packages/lib/package-lock.json | 2498 +++++
packages/lib/package.json | 39 +
packages/lib/src/index.ts | 28 +
packages/lib/src/solver.ts | 92 +
packages/lib/src/validator.ts | 172 +
packages/lib/src/vite-env.d.ts | 1 +
packages/lib/tsconfig.json | 27 +
packages/lib/vite.config.ts | 29 +
packages/widget/.gitignore | 2 +
packages/widget/index.html | 12 +
packages/widget/package-lock.json | 2576 +++++
packages/widget/package.json | 35 +
packages/widget/src/entry.ts | 1 +
packages/widget/src/pow-captcha.ts | 458 +
packages/widget/src/solver-worker.ts | 91 +
packages/widget/src/types/worker.ts | 60 +
packages/widget/src/vite-env.d.ts | 1 +
packages/widget/tsconfig.json | 27 +
packages/widget/vite.config.ts | 29 +
solver/.gitignore | 2 +
solver/build.zig | 46 +
solver/src/hasher.zig | 31 +
solver/src/kctf.zig | 7 +
solver/src/solver.zig | 159 +
solver/src/validator.zig | 81 +
58 files changed, 18689 insertions(+)
create mode 100644 .gitignore
create mode 100644 .vscode/settings.json
create mode 100644 .vscode/tasks.json
create mode 100644 LICENSE
create mode 100644 NOTES.md
create mode 100644 README.md
create mode 100644 example-app/.example.env
create mode 100644 example-app/.gitignore
create mode 100644 example-app/.vscode/settings.json
create mode 100644 example-app/README.md
create mode 100644 example-app/app/app.vue
create mode 100644 example-app/app/pages/index.vue
create mode 100644 example-app/app/pages/widget.vue
create mode 100644 example-app/app/plugins/pow-captcha.ts
create mode 100644 example-app/app/utils/worker-name.ts
create mode 100644 example-app/app/utils/worker.ts
create mode 100644 example-app/bun.lock
create mode 100644 example-app/config.toml
create mode 100644 example-app/nuxt.config.ts
create mode 100644 example-app/package-lock.json
create mode 100644 example-app/package.json
create mode 100644 example-app/server/api/pow/challenge.get.ts
create mode 100644 example-app/server/api/pow/challenge.post.ts
create mode 100644 example-app/server/api/pow/difficulty.get.ts
create mode 100644 example-app/server/api/pow/difficulty.put.ts
create mode 100644 example-app/server/middleware/secure-context.ts
create mode 100644 example-app/server/utils/config.ts
create mode 100644 example-app/server/utils/pow.ts
create mode 100644 example-app/tsconfig.json
create mode 100644 example-app/uno.config.ts
create mode 100644 justfile
create mode 100644 packages/lib/.gitignore
create mode 100644 packages/lib/README.md
create mode 100644 packages/lib/package-lock.json
create mode 100644 packages/lib/package.json
create mode 100644 packages/lib/src/index.ts
create mode 100644 packages/lib/src/solver.ts
create mode 100644 packages/lib/src/validator.ts
create mode 100644 packages/lib/src/vite-env.d.ts
create mode 100644 packages/lib/tsconfig.json
create mode 100644 packages/lib/vite.config.ts
create mode 100644 packages/widget/.gitignore
create mode 100644 packages/widget/index.html
create mode 100644 packages/widget/package-lock.json
create mode 100644 packages/widget/package.json
create mode 100644 packages/widget/src/entry.ts
create mode 100644 packages/widget/src/pow-captcha.ts
create mode 100644 packages/widget/src/solver-worker.ts
create mode 100644 packages/widget/src/types/worker.ts
create mode 100644 packages/widget/src/vite-env.d.ts
create mode 100644 packages/widget/tsconfig.json
create mode 100644 packages/widget/vite.config.ts
create mode 100644 solver/.gitignore
create mode 100644 solver/build.zig
create mode 100644 solver/src/hasher.zig
create mode 100644 solver/src/kctf.zig
create mode 100644 solver/src/solver.zig
create mode 100644 solver/src/validator.zig
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0f1c9a4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "workbench.colorCustomizations": {
+ "minimap.background": "#00000000",
+ "scrollbar.shadow": "#00000000"
+ }
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..ea06169
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,10 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "shell",
+ "label": "Build",
+ "command": "just build",
+ }
+ ],
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/NOTES.md b/NOTES.md
new file mode 100644
index 0000000..00e61f4
--- /dev/null
+++ b/NOTES.md
@@ -0,0 +1,7 @@
+# Notes
+
+Ideas:
+
+- plugable solvers: users can implement their own solvers and use them with the
+ widget. This would allow easily changing the PoW algorithm, or even using
+ different PoW algorithms for different challenges.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5fece17
--- /dev/null
+++ b/README.md
@@ -0,0 +1,19 @@
+# Impost
+
+Impost /ˈimˌpōst/ _noun_ a tax or compulsory payment
+
+Impost is a PoW anti-spam solution, or for short, a PoW captcha. Instead of
+spying on your users and using heavy captchas, Impost uses PoW to impose a cost
+on sending requests. To a single user, this is a negligable few seconds, but at
+scale, it can be a significant deterrent to spam.
+
+This is the impost monorepo, containing the following packages:
+
+- `@impost/widget`: A web component that can be used to embed an Impost widget
+ in your website.
+- `@impost/lib`: A library that can be used to generate, solve, and verify
+ proofs.
+
+It also contains a `solver` package, which is the PoW solver written in Zig,
+`@impost/lib` is built on top of, an example of how to use the solver in a
+nuxt 3 project.
diff --git a/example-app/.example.env b/example-app/.example.env
new file mode 100644
index 0000000..771536b
--- /dev/null
+++ b/example-app/.example.env
@@ -0,0 +1 @@
+YAPTCHA_HMAC_SECRET=xxx # openssl rand -base64 32
diff --git a/example-app/.gitignore b/example-app/.gitignore
new file mode 100644
index 0000000..03960be
--- /dev/null
+++ b/example-app/.gitignore
@@ -0,0 +1,5 @@
+node_modules/
+.output/
+.nuxt/
+.env
+*.wasm
diff --git a/example-app/.vscode/settings.json b/example-app/.vscode/settings.json
new file mode 100644
index 0000000..0f1c9a4
--- /dev/null
+++ b/example-app/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "workbench.colorCustomizations": {
+ "minimap.background": "#00000000",
+ "scrollbar.shadow": "#00000000"
+ }
+}
diff --git a/example-app/README.md b/example-app/README.md
new file mode 100644
index 0000000..c605814
--- /dev/null
+++ b/example-app/README.md
@@ -0,0 +1,50 @@
+# YAPTCHA
+
+Yet Another Pow capTCHA.
+
+## What is this
+
+YAPTCHA is a proof of work based challenge-response system that is designed to
+ward off spam and abuse.
+
+
+
+## Basic configuration notes
+
+Leading zeroes takes in a difficulty from 1 to 64, this indicates the number of
+leading hexidecimal zeroes that are required for a problem to be solved. The
+probability for a digit to be a zero is 1/16^$D$ where $D$ is the difficulty.
+
+The following chart is provided for a baseline of the theoretical expected
+average iterations it would take to solve challenge of difficulty $D$.
+
+| $D$ | expected average iterations |
+| --- | --------------------------- |
+| 1 | 16 |
+| 2 | 256 |
+| 3 | 4,096 |
+| 4 | 65,536 |
+| 5 | 1,048,576 |
+| 6 | 16,777,216 |
+| 7 | 268,435,456 |
+| 8 | 4,294,967,296 |
+
+Target Number takes in a max number of iterations, $M$, to be solved. The
+probability that a solution is solved will be 1/targetNumber. This provides a
+more preciese way of determining the difficulty of a challenge. With leading
+zeroes, there is only a theoretical chance that a solution is found within a
+certain number of iterations. With target number, there is a gurantee that a
+solution will be found in, at most, $M$ iterations.
+
+## Interesting links and blogs I used while writing this
+
+- [Anubis](https://github.com/TecharoHQ/anubis) for inspiration. (once again, I
+ have some strong opinions on Anubis, but thats is still neithehrere nor there)
+- ["Proof of Mutex: Outspeeding Anubis with Valid PoW" by yumechi](https://yumechi.jp/en/blog/2025/proof-of-mutex-outspeeding-anubis-with-valid-pow/)
+- https://www.arkoselabs.com/blog/proof-of-work-invisible-security-visible-results/
+ for giving me hope that PoW is not a fruitless endeavor for captchas.
+- [ALTCHA](https://github.com/altcha-org/altcha) purely to see how another
+ option in the space works. (I have some choice words about the implementation
+ of ALTCHA, but I digress. **No code from ALTCHA was used in this project.**)
+- [The monero project](https://www.getmonero.org/) for its list of algorithms
+ they use in xmrig, and some inspiration.
diff --git a/example-app/app/app.vue b/example-app/app/app.vue
new file mode 100644
index 0000000..8f5df02
--- /dev/null
+++ b/example-app/app/app.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example-app/app/pages/index.vue b/example-app/app/pages/index.vue
new file mode 100644
index 0000000..e1609f6
--- /dev/null
+++ b/example-app/app/pages/index.vue
@@ -0,0 +1,411 @@
+
+
+
+
+ Your average Hashrate: {{ number_formatter.format(hashrate) }} H/s
+ You have solved {{ total_solved }} {{ pluralize(total_solved, "challenge") }} in
+ {{ number_formatter.format(total_solving_for / 1000) }}s
+ Your Hashrate on the last challenge: {{ number_formatter.format(hashrate_array.at(-1)!) }} H/s
+