Skip to content
HN On Hacker News ↗

GitHub - zacharybenson/arken-protocol: Passwordless authentication via DID signatures. No passwords. No sessions. Nothing to breach.

▲ 14 points • 0 comments • by zachbenson817 • 7d ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is AI.

100 %

AI likelihood · overall

AI
0% human-written 100% AI-generated
SEGMENTS · HUMAN 0 of 3
SEGMENTS · AI 3 of 3
WORD COUNT 643
PEAK AI % 100% · §1
Analyzed
Oct 30
backend: pangram/v3.3
Segments scanned
3 windows
avg 214 words each
Distribution
0 / 100%
human / AI fraction
Verdict
AI
Pangram v3.3

Article text · 643 words · 3 segments analyzed

Human AI-generated
§1 AI · 100%

Arken Auth Passwordless authentication for web servers. No passwords. No sessions. Nothing to breach. Live Demo → · npm · PyPI The problem Every auth system today asks your server to hold a secret — a password hash, a session token, an API key. That secret is a liability. It gets breached. It gets phished. It gets rotated on a schedule that nobody follows. Arken Auth flips the model: the user holds the secret, the server holds nothing. How it works Client Server │ │ ├── GET /protected ────────────────▶│ │ │ (no auth header) │◀── 401 { challenge: { nonce } } ──┤ │ │ │ sign(nonce, privateKey) │ │ │ ├── GET /protected ────────────────▶│ │ Authorization: Signature │ │ did="did:key:z...", │ │ nonce="...", │ │ signature="0x..." │ │ │ recover signer from sig │ │ compare to DID pubkey │◀── 200 { did: "did:key:z..." } ───┤ Client requests a protected resource — server issues a one-time nonce Client signs the nonce with their private key (never leaves their device) Client sends the signature + their DID back to the server Server recovers the signer address from the signature and checks it matches the DID No password ever transmitted. No session stored. No database touched. The cryptographic core is written in Rust and called via FFI from Node.js or Python. Quickstart — Node.js npm install arken-auth const express = require('express'); const { arkenAuth } = require('arken-auth'); const app = express(); app.get('/protected', arkenAuth(), (req, res) => { res.json({ message: 'hello', did: req.user.did }); }); That's it. arkenAuth() handles the entire challenge-response cycle. Quickstart — Python pip install arken-auth from fastapi import FastAPI, Depends from arken_auth import ArkenAuth app = FastAPI() arken = ArkenAuth() @app.get("/protected") async def protected(did: str = Depends(arken)): return {"message": "hello", "did": did} Client-side (browser or CLI) Any client that can sign an Ethereum message works. In the browser with ethers.js: // Generate a DID from a wallet const wallet = ethers.Wallet.createRandom(); const did = walletToDid(wallet); // did:key:z... // Step 1: get a challenge const r1 = await fetch('/protected'); const { challenge: { nonce } } = await r1.json(); // 401 // Step 2: sign the nonce const signature = await wallet.signMessage(ethers.utils.toUtf8Bytes(nonce)); // Step 3: authenticate const r2 = await fetch('/protected', { headers: { Authorization: `Signature did="${did}",nonce="${nonce}",signature="${signature}"` } }); What makes it different Username/Password JWT / OAuth WebAuthn Arken Auth Server stores secrets ✗ (hash) ✗ (secret) ✓ ✓ Works without accounts ✗ ✗ ✗ ✓ Portable identity ✗ ✗ ✗ ✓ No JS SDK required ✓ ✓ ✗ ✓ Language agnostic ✓ ✓ ✓ ✓ Phishing resistant ✗ ✗ ✓ ✓ The key difference from WebAuthn: your identity (did:key:z...)

§2 AI · 100%

is portable.

§3 AI · 100%

It travels with you across servers, apps, and devices. A WebAuthn credential is bound to a single origin. A DID is bound to nothing but your key. Architecture packages/ arken-auth/ Node.js middleware (Express) arken-auth-py/ Python middleware (FastAPI) arken-phase1-docker/workspace/ rust-core/ Cryptographic engine (Rust) src/lib.rs Challenge generation + signature verification node-wrapper/ Node.js FFI bindings (koffi) python-wrapper/ Python FFI bindings (ctypes) public/ Interactive demo UI The Rust core exposes two functions over FFI: generate_challenge_into — generates a random nonce, stores it server-side with a 60s TTL, returns JSON verify_request_into — parses the auth header, validates the nonce, recovers the signer, checks against the DID DID format Arken uses did:key with secp256k1 keys (multicodec 0xe7 0x01), encoded as multibase base58btc (z prefix): did:key:z[base58btc(0xe7 0x01 || compressed_pubkey)] This is the W3C DID Key Method spec. Requirements Rust (for building the native library): curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh Node.js ≥ 18 (for the npm package) Python ≥ 3.10 (for the pip package) Status Phase 1 — working middleware for Express and FastAPI. The cryptographic core is complete and tested. What's next: Prebuilt binaries (no Rust required to install) Session/token layer (optional, for stateful apps) did:web and did:pkh support Browser extension wallet License MIT