Proof of Work

Stateless HMAC-SHA256 proof-of-work protocol, client Web Worker solver, and O(1) server verification.

Execution Strategy:
Est. ~0.82s on standard browser
Ready to verify (18 bits)...
0%
Real-Time Solver Telemetry Web Worker
Hashrate
--
Total Hashes
--
Elapsed Time
--
Verified Nonce
--
Compliant Server API & Inspector Local callApi()
Waiting for callApi() challenge generation...

Visual Design Language & Components

UI components and visual states for client-side proof-of-work verification.

Pattern 1: Embedded CTA Button Gate

For compact cards and modal dialogs. The progress shimmer is embedded directly on the button edge so the interface stays clean and clutter-free.

برای فرم‌های فشرده و پنجره‌های پاپ‌آپ. نوار پیشرفت دقیقا در لبه دکمه اصلی قرار گرفته و رابط کاربری خلوت و مدرن باقی می‌ماند.

Pattern 2: Docked Form Gate Card

For high-trust flows like checkout, invoice generation, or account creation. Transparently displays verification progress and cryptographic telemetry.

برای فرآیندهای مالی و حساس مانند پرداخت و ایجاد حساب کاربری. پیشرفت اثبات کار و وضعیت امنیتی را با شفافیت کامل نمایش می‌دهد.

Verifying invoice.create... 75%

Technical Specification & Architecture

Cryptographic HMAC tokens, context fingerprinting, replay resistance, and multi-tenant sharding.

1. The Stateless HMAC Challenge Token

HMAC-SHA256

Servers do not store active challenges in Redis or databases. Puzzles are distributed as cryptographically signed stateless tokens verified in O(1) time:

سرورها چالش‌های فعال را در دیتابیس یا ردیس ذخیره نمی‌کنند. معماها به عنوان توکن‌های بدون حالت و امضاشده صادر می‌شوند که در زمان O(1) تأیید می‌گردند:

token-format.txt
1Token = Base64Url(Payload) + "." + HMAC_SHA256(SecretKey, Base64Url(Payload))

2. Context Binding & Swapping Prevention

Every challenge binds cryptographically to the exact form context: ctx = SHA256(form_fields). A bot cannot pre-compute a proof for account A and reuse it for account B or an invoice.

هر چالش به صورت رمزنگاری‌شده به زمینه فرم متصل است. بات‌ها نمی‌توانند اثبات حل‌شده را از یک حساب به حساب یا عملیات دیگر منتقل کنند.

3. Dynamic Difficulty & Subnet Escalation

Clean residential traffic receives effortless baseline difficulty (14–16 bits, ~0.8s). Datacenter/Tor subnets generating rapid requests face scaled difficulty (18–22 bits), exhausting automated bot servers.

کاربران عادی سختی پایه (۰.۸ ثانیه) دریافت می‌کنند؛ در حالی که دیتاسنترها و بات‌های مشکوک با سختی‌های تصاعدی مواجه شده و توان سرورشان مسدود می‌شود.

4. Compliant Server Trust Model & Anti-Spoofing Architecture

Server Secret

Unlike third-party CAPTCHAs where trust is delegated to Google or Cloudflare, in Mehr PoW your backend server is the Root of Trust. The client never chooses difficulty or validates its own tokens:

  • Cryptographic Tamper-Proofing: The target difficulty (e.g. 18 or 21 bits), timestamp, and context are signed into the HMAC token with SERVER_SECRET_KEY. If a client tampers with difficulty in DevTools, the HMAC fails upon form submission.
  • Rogue Server Immunity: If an attacker redirects the PoW library to a fake server issuing trivial 4-bit challenges, the final application server rejects the submission in O(1) time because the signature was not signed with the real SERVER_SECRET_KEY.
  • Dynamic Server Policy: The backend challenge endpoint (POST /pow/challenge) inspects the client's IP, TLS/JA4 fingerprint, request velocity, and risk tier to dynamically assign difficulty before signing.

برخلاف کپچاهای شخص‌ثالث که به گوگل یا کلودفلر وابسته هستند، در اثبات کار مهر سرور اصلی برنامه شما مرجع نهایی امنیت است. کلاینت هرگز درجه سختی را مشخص نمی‌کند:

  • غیرقابل دستکاری: درجه سختی (مثلاً ۱۸ یا ۲۱ بیت)، زمان صدور و زمینه فرم درون توکن با کلید محرمانه سرور امضا می‌شوند. هرگونه تغییر در مرورگر باعث خطای فوری HMAC می‌گردد.
  • مصونیت از جعل سرور: اگر مهاجم کلاینت را به یک سرور جعلی هدایت کند تا سختی ناچیز بگیرد، سرور مقصد فرم نهایی را بلافاصله رد می‌کند زیرا امضای آن با کلید سرور اصلی همخوانی ندارد.
  • سیاست‌گذاری پویا: سرور بر اساس آدرس IP، فینگرپرینت TLS و نرخ درخواست، سختی متغیر تعیین کرده و سپس آن را امضا می‌کند.

5. Standard HTTP API & Cross-Origin (domain) Contract

REST / JSON

For decoupled frontends (e.g. static website on example.com and API on api.example.com), the client accepts an optional domain option. The backend enables standard CORS headers (Access-Control-Allow-Origin):

برای سامانه‌هایی که فرانت‌اند (مثلاً روی example.com) و سرور بک‌اند (روی api.example.com) دامنه‌های مجزا دارند، کلاینت فیلد اختیاری domain را می‌پذیرد:

POST /pow/challenge
1// Request Payload
2{ "action": "account.register", "context": "usr_4f81" }
3 
4// Response (HTTP 200 OK)
5{
6  "token": "eyJ2IjoxLCJz...8f9b2c",
7  "salt": "a1f9d287c4b03e1a",
8  "difficulty": 18,
9  "context": "usr_4f81",
10  "exp": 1729000180
11}
POST /pow/verify (or Form Submit)
1// Form Submission / JSON Payload
2{
3  "pow_token": "eyJ2IjoxLCJz...8f9b2c",
4  "pow_nonce": 268412,
5  ...formData
6}
7 
8// Result (O(1) Verification)
9{ "valid": true, "action": "account.register" }

Implementation Guide & Architecture Flow

Cryptographic sequence flow, browser drop-in client, and backend verification middleware.

End-to-End Protocol Flowchart

This interactive architecture sequence illustrates the trust lifecycle between the client browser (untrusted environment), the challenge gateway (stateless HMAC issuer), and your protected backend API. Solving runs non-blockingly inside background Web Workers, while the server verifies solutions in < 0.05ms without database state.

این فلوچارت تعاملی معماری، چرخه اعتماد میان مرورگر کلاینت (محیط غیرقابل‌اعتماد)، گیت‌وی صادرکننده چالش (امضای بدون دیتابیس) و سرور مقصد برنامه شما را نشان می‌دهد. محاسبات در پس‌زمینه کلاینت اجرا شده و اعتبارسنجی سرور در کمتر از ۰.۰۵ میلی‌ثانیه بدون بار دیتابیس انجام می‌گیرد.

Trust Boundary:
Client Browser (Untrusted)
Challenge Gateway (HMAC Issuer)
Destination Backend API (O(1) Gate)
01 Challenge Request
Client POST /pow/challenge

Client requests a proof-of-work challenge on initial form load (background mode) or when primary submission is initiated. Sends action name and request context fingerprint.

مرورگر کاربر در پس‌زمینه بارگذاری صفحه یا هنگام آغاز ثبت فرم، درخواست دریافت چالش را ارسال می‌کند. نام عملیات و فینگرپرینت زمینه ارسال می‌گردد.

02 Stateless Challenge Token
Gateway HMAC-SHA256

Gateway evaluates IP reputation, rate velocity, and endpoint tier, then returns salt, expiration, and assigned difficulty (14–24 bits) sealed with SERVER_SECRET_KEY.

سرور چالش بر اساس رتبه آدرس IP و حساسیت عملیات، سالت، زمان انقضا و درجه سختی را مشخص کرده و با کلید محرمانه سرور بدون ذخیره در دیتابیس امضا می‌کند.

03 Background Web Worker Hash Loop
Web Worker SHA-256(salt:nonce:ctx)

An off-thread Web Worker computes nonces without blocking the browser UI thread.

یک وب‌ورکر مستقل خارج از ترد اصلی رابط کاربری، نانس‌های متوالی را بررسی می‌کند تا تعداد بیت‌های صفر معین تولید شود؛ رابط کاربری با ۶۰ فریم بر ثانیه کاملاً روان می‌ماند.

04 Protected Action Dispatch
Client X-Mehr-PoW-Headers

The user submits the form or API request. MehrPoW transparently attaches X-Mehr-PoW-Token and X-Mehr-PoW-Nonce headers alongside the form payload.

کاربر فرم یا درخواست نهایی را ارسال می‌کند. کتابخانه مهر به صورت خودکار هدرهای توکن امضاشده و نانس محاسبه‌شده را همراه با اطلاعات فرم ارسال می‌نماید.

05 Stateless O(1) Verification Gate
Backend Gate verifySolution()

Destination backend verifies HMAC signature with its private secret, checks expiration, and re-computes a single SHA-256 hash to confirm proof in under 0.05ms.

سرور مقصد امضای HMAC را با کلید محرمانه بررسی کرده، انقضا و سیاست سختی را می‌سنجد و با یک بار هش SHA-256 در کمتر از ۰.۰۵ میلی‌ثانیه اعتبار اثبات کار را تأیید می‌کند.

1. HMAC Signature Valid
2. Not Expired (< 180s)
3. Action Scope Matches
4. Meets minDifficulty
5. Context Hash Binds Form
6. Nonce Leading Zero Bits
Cryptographic Gate Outcome
Pass Gate HTTP 200 OK
Request Approved & Processed

Business transaction executes: user account registered, payment invoice generated, or comment published immediately.

تراکنش بدون معطلی پردازش می‌شود: حساب کاربری ایجاد شده، فاکتور صادر می‌گردد یا یادداشت با موفقیت ثبت می‌شود.

Fail Gate HTTP 403 Forbidden
Tampered / Bot Request Dropped

Forged difficulty, rogue server token, replayed nonce, or expired challenge immediately rejected in O(1) time without DB impact.

سختی دستکاری‌شده، توکن جعلی سرور ناشناس، نانس بازپخش‌شده یا چالش منقضی‌شده در زمان O(1) بلافاصله دفع می‌گردد.

Client & Backend Implementations

Self-contained solvers, drop-in browser client, and verification middleware for Go, JavaScript/TypeScript, Python, PHP, and POSIX Shell.

کتابخانه‌های مستقل کلاینت، سالورهای چندزبانه و میدل‌ورهای اعتبارسنجی برای Go، جاوااسکریپت، پایتون، PHP و POSIX Shell.

index.html (Drop-in Client)
1<!-- 1. Include the drop-in library -->
2<script src="https://pow.mehrnet.com/pow-client.js"></script>
3 
4<!-- 2. Your standard HTML form -->
5<form id="signup-form" action="https://api.example.com/register" method="POST">
6  <input type="email" name="email" required />
7  <input type="password" name="password" required />
8  <button type="submit">Register</button>
9</form>
10 
11<!-- 3. Auto-protect with optional cross-origin domain -->
12<script>
13  MehrPoW.protect('#signup-form', {
14    // Optional: for cross-domain API setups (e.g. api.example.com)
15    domain: 'https://api.example.com',
16    endpoint: '/api/pow/challenge',
17    action: 'account.register',
18    mode: 'background' // Solves non-blockingly while user fills form
19  });
20</script>
pow.go
1package main
2 
3import (
4	"crypto/hmac"
5	"crypto/sha256"
6	"encoding/hex"
7	"fmt"
8	"math/bits"
9	"net/http"
10	"strconv"
11	"strings"
12)
13 
14// VerifyPoW verifies client proof in O(1) time
15func VerifyPoW(secretKey, token string, nonce int64, context string) (bool, error) {
16	parts := strings.Split(token, ".")
17	if len(parts) != 2 {
18		return false, fmt.Errorf("invalid token format")
19	}
20	payloadB64, sig := parts[0], parts[1]
21 
22	// 1. Verify HMAC-SHA256 signature
23	mac := hmac.New(sha256.New, []byte(secretKey))
24	mac.Write([]byte(payloadB64))
25	expectedSig := hex.EncodeToString(mac.Sum(nil))
26	if !hmac.Equal([]byte(sig), []byte(expectedSig)) {
27		return false, fmt.Errorf("signature mismatch")
28	}
29 
30	// 2. Count leading zero bits of candidate hash
31	candidate := fmt.Sprintf("salt:%d:%s", nonce, context)
32	h := sha256.Sum256([]byte(candidate))
33	
34	var zeroBits int
35	for _, b := range h {
36		if b == 0 {
37			zeroBits += 8
38		} else {
39			zeroBits += bits.LeadingZeros8(b)
40			break
41		}
42	}
43	return zeroBits >= 16, nil
44}
worker.js
1// Background Web Worker PoW Solver (worker.js)
2self.onmessage = async (e) => {
3  const { salt, context, difficulty } = e.data;
4  const encoder = new TextEncoder();
5  let nonce = 0;
6  
7  while (true) {
8    const candidate = `${salt}:${nonce}:${context}`;
9    const buf = await crypto.subtle.digest("SHA-256", encoder.encode(candidate));
10    const bytes = new Uint8Array(buf);
11    
12    // Count leading zero bits
13    let zeroBits = 0;
14    for (let i = 0; i < bytes.length; i++) {
15      if (bytes[i] === 0) zeroBits += 8;
16      else { zeroBits += Math.clz32(bytes[i]) - 24; break; }
17    }
18    
19    if (zeroBits >= difficulty) {
20      self.postMessage({ solved: true, nonce });
21      return;
22    }
23    nonce++;
24  }
25};
pow.py
1import hashlib, hmac
2 
3def verify_pow(secret_key: str, token: str, nonce: int, context: str) -> bool:
4    parts = token.split(".")
5    if len(parts) != 2:
6        return False
7    payload_b64, signature = parts
8    
9    # 1. Verify HMAC
10    expected = hmac.new(secret_key.encode(), payload_b64.encode(), hashlib.sha256).hexdigest()
11    if not hmac.compare_digest(signature, expected):
12        return False
13        
14    # 2. Check hash difficulty
15    candidate = f"salt:{nonce}:{context}".encode()
16    digest = hashlib.sha256(candidate).digest()
17    
18    zero_bits = 0
19    for byte in digest:
20        if byte == 0:
21            zero_bits += 8
22        else:
23            zero_bits += (8 - byte.bit_length())
24            break
25            
26    return zero_bits >= 16
pow.php
1<?php
2function verify_pow($secret_key, $token, $nonce, $context) {
3    $parts = explode(".", $token);
4    if (count($parts) !== 2) return false;
5    list($payload_b64, $signature) = $parts;
6 
7    // 1. Verify HMAC
8    $expected = hash_hmac("sha256", $payload_b64, $secret_key);
9    if (!hash_equals($signature, $expected)) return false;
10 
11    // 2. Check hash candidate
12    $candidate = "salt:" . $nonce . ":" . $context;
13    $raw_hash = hash("sha256", $candidate, true);
14 
15    $zero_bits = 0;
16    for ($i = 0; $i < strlen($raw_hash); $i++) {
17        $byte = ord($raw_hash[$i]);
18        if ($byte === 0) {
19            $zero_bits += 8;
20        } else {
21            $zero_bits += (8 - strlen(decbin($byte)));
22            break;
23        }
24    }
25    return $zero_bits >= 16;
26}
pow.sh
1#!/bin/sh
2# POSIX-compliant PoW solver
3SALT="a1b2c3d4e5f67890"
4CTX="job_context_fingerprint"
5 
6nonce=0
7while :; do
8    hash=$(printf "%s:%s:%s" "$SALT" "$nonce" "$CTX" | sha256sum | awk "{print \$1}")
9    case "$hash" in
10        0000*)
11            printf "Solved! Nonce: %s Hash: %s\n" "$nonce" "$hash"
12            break
13            ;;
14    esac
15    nonce=$((nonce + 1))
16done
Copied!