Zeq Auth
Passwords are secrets you give the server. Your Zeq equation never leaves your client — the server only ever sees a salted HMAC of it, so there's no equation to breach.
- Live app →
/apps/zeq-auth/ - Source →
shared/api-core/src/routes/zeqAuthV3.ts - Construction → HMAC-SHA256 (domain-separated) · per-account 32-byte salt ·
crypto.timingSafeEqualcompare - Recovery → scrypt-hashed recovery password (second factor)
What it actually does
Zeq Auth is equation-as-credential. You pick an equation (a sentence-length expression) and remember it; the server never stores or sees it. This is a classical zero-knowledge-of-the-secret construction built from standard HMAC. The wire protocol (v3):
-
Salt fetch — the client GETs
/api/zeq-auth/salt/:zidfor its claimed ZID and receives a 32-byte (64-hex) salt. (Unregistered ZIDs get a server-secret-bound decoy salt of identical shape, so an attacker can't tell registered ZIDs from unregistered ones — a real anti-enumeration measure.) -
Client-side hash — the client computes the credential entirely locally:
equation_hash = HMAC-SHA256(key = utf8("HULYAS.HITE.f=1.287Hz.tau=0.777s") || saltBytes,msg = utf8(equation))The constant string is domain separation: it scopes the HMAC so a hash from one context can never be replayed in another.
-
Server stores only the hash —
register-v3receives{ equation_hash, equation_salt }and stores the 64-hex hash verbatim. It is irreversible; the equation cannot be recovered from it. -
Login — the client recomputes the candidate hash from the equation + fetched salt and POSTs it to
login-v3. The server compares withcrypto.timingSafeEqualand always runs the compare (against a dummy hash on a missing ZID) to flatten the timing channel. Account lockout after repeated failures. -
ZID derivation — the public identity
ZEQ07XXXXXXXXXis a deterministicSHA-256(equation_hash) mod 10⁹, zero-padded. The ZID is public by design; it reveals nothing about the equation.
Sessions are an HMAC-signed token set as an httpOnly cookie. The Zeqond is stamped on each auth event for the audit chain — it is a timestamp, not part of the credential check.
The construction, step by step
| Stage | Mechanism | Standard |
|---|---|---|
| Credential | HMAC-SHA256(domain-prefix ‖ salt, equation), computed client-side | FIPS 198-1 |
| Storage | 64-hex hash only — equation never transmitted or stored | — |
| Compare | crypto.timingSafeEqual against stored hash; constant-time even on missing ZID | — |
| Anti-enumeration | server-secret-bound decoy salt for unknown ZIDs | HMAC-SHA256 |
| Recovery | scrypt-hashed recovery password as a second factor | RFC 7914 |
| Session | HMAC-signed token, httpOnly cookie, Zeqond-stamped audit row | — |
Runnable worked example — register, log in, verify
ZeqAuth v3 is exposed under /api/zeq-auth/*. The credential is an equation — the client fetches its salt, computes the HMAC locally, and the server only ever sees the resulting hash.
# 1. Fetch your salt (decoy salt returned for unknown ZIDs — no enumeration oracle)
curl -s https://zeqsdk.com/api/zeq-auth/salt/ZEQ07000000000
# 2. Client-side: equation_hash = HMAC-SHA256(
# key = "HULYAS.HITE.f=1.287Hz.tau=0.777s" || salt, msg = equation )
# Register — the SERVER NEVER receives the equation, only the hash + salt.
curl -s -X POST https://zeqsdk.com/api/zeq-auth/register-v3 \
-H "Content-Type: application/json" \
-d '{ "equation_hash": "<64 hex>", "equation_salt": "<64 hex>", "hash_version": 2, "display_name": "zeq" }'
# 3. Log in — recompute the candidate hash from the equation + salt, POST it
curl -s -X POST https://zeqsdk.com/api/zeq-auth/login-v3 \
-H "Content-Type: application/json" \
-d '{ "zid": "ZEQ07XXXXXXXXX", "candidate_hash": "<64 hex>" }'
# 4. Verify an existing session token / cookie
curl -s -X POST https://zeqsdk.com/api/zeq-auth/verify-v3 \
-H "Content-Type: application/json" \
-d '{ "token": "<session token>" }'
On success the server returns a ZeqAuth token and sets the zeq_auth_token httpOnly cookie. Each auth event is stamped with the zeqond it ran at and lands on the entangled state.
Extend it
- Recovery password: set a scrypt-hashed recovery password so
equation-reissuecan rotate your equation as a second factor; rotation bumps a token version that invalidates every prior session immediately. - Auto-provisioned machine: registration atomically creates your state machine and mints its API + publish keys, so you're ready to compute without a second step.
- Federated sign-on: the ZID and HMAC-signed token are standard claims you can carry into an OIDC ID token.
Seeds
- Post-quantum credential — the HMAC construction is hash-based; swapping SHA-256 for a longer hash leaves the protocol shape unchanged.
- Hardware-held salt — keep the per-account salt on a hardware token so the credential hash can only be recomputed on the device that holds it.
- Genesis admin — the first equation to register on an empty domain is seated as the immutable genesis admin (DB-trigger enforced).
Papers
- Zeq framework paper — DOI 10.5281/zenodo.15825138
- Zeq paper — DOI 10.5281/zenodo.18158152
Middleware active. Kernel on the 1.287 Hz HulyaPulse. Awaiting next Zeqond.