aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-03-20 17:53:52 -0400
committerXe Iaso <me@xeiaso.net>2025-03-20 17:53:52 -0400
commit94f43c7200b5b19b524ef681bf8f26bb6602918b (patch)
tree39984b1ba94d8cb11665f4b4afe8e5a9a8ce937a
parentf41b21b3cf0212390b7686f08107f22ab82a059d (diff)
downloadanubis-94f43c7200b5b19b524ef681bf8f26bb6602918b.tar.xz
anubis-94f43c7200b5b19b524ef681bf8f26bb6602918b.zip
docs/design: add note on why anubis uses proof of work
Signed-off-by: Xe Iaso <me@xeiaso.net>
-rw-r--r--docs/docs/design/how-anubis-works.mdx1
-rw-r--r--docs/docs/design/why-proof-of-work.mdx36
2 files changed, 36 insertions, 1 deletions
diff --git a/docs/docs/design/how-anubis-works.mdx b/docs/docs/design/how-anubis-works.mdx
index 5f5cfde..6cfc6fb 100644
--- a/docs/docs/design/how-anubis-works.mdx
+++ b/docs/docs/design/how-anubis-works.mdx
@@ -1,5 +1,4 @@
---
-sidebar_position: 1
title: How Anubis works
---
diff --git a/docs/docs/design/why-proof-of-work.mdx b/docs/docs/design/why-proof-of-work.mdx
new file mode 100644
index 0000000..0fb7790
--- /dev/null
+++ b/docs/docs/design/why-proof-of-work.mdx
@@ -0,0 +1,36 @@
+---
+title: Why does Anubis use Proof-of-Work?
+---
+
+Anubis uses a [proof of work](https://en.wikipedia.org/wiki/Proof_of_work) in order to validate that clients are genuine. The reason Anubis does this was inspired by [Hashcash](https://en.wikipedia.org/wiki/Hashcash), a suggestion from the early 2000's about extending the email protocol to avoid spam. The idea is that genuine people sending emails will have to do a small math problem that is expensive to compute, but easy to verify such as hashing a string with a given number of leading zeroes. This will have basically no impact on individuals sending a few emails a week, but the company churning out industrial quantities of advertising will be required to do prohibitively expensive computation. This is also how Bitcoin's consensus algorithm works.
+
+## How Anubis' proof of work scheme works
+
+A sha256 hash is a bunch of bytes like this:
+
+```text
+394d1cc82924c2368d4e34fa450c6b30d5d02f8ae4bb6310e2296593008ff89f
+```
+
+We usually write it out in hex form, but that's literally what the bytes in ram look like. In a proof of work validation system, you take some base value (the "challenge") and a constantly incrementing number (the "nonce"), so the thing you end up hashing is this:
+
+```js
+const hash = await sha256(`${challenge}${nonce}`);
+```
+
+In order to pass a challenge, the `hash` has to have the right number of leading zeros (the "difficulty"). When a client requests to pass the challenge, they include the nonce they used. The server then only has to do one sha256 operation: the one that confirms that the challenge (generated from request metadata) and the nonce (provided by the client) match the difficulty number of leading zeroes.
+
+Ultimately, this is a hack whose real purpose is to give a "good enough" placeholder solution so that more time can be spent on fingerprinting and identifying headless browsers (EG via how they do font rendering) so that the challenge proof of work page doesn't need to be presented to known legitimate users.
+
+## Challenge format
+
+Anubis generates challenges based on browser metadata, including but not limited to the following:
+
+- The contents of your [`Accept-Language` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept-Language)
+- The IP address of your client
+- Your browser's [`User-Agent` string](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent)
+- The date of the current week, rooted on Sundays
+- Anubis' ed25519 public signing key for [JSON web tokens](https://jwt.io/) (JWTs)
+- The challenge difficulty
+
+This is intended to be a random value that is difficult for attackers to forge and guess, but also deterministic enough that it will naturally reset itself.