Orphograph

फ़ाइल के SHA-256 फ़िंगरप्रिंट को OpenTimestamps के माध्यम से Bitcoin से जोड़ें — फ़ाइल कभी भी डिवाइस से बाहर नहीं जाती।

दस्तावेज़

orphograph

Bitcoin-anchored receipts that a relying party can verify without the issuer. Checking a file against its saved proof needs only the MIT verifier in this repository, with no account and no network call; confirming the timestamp against Bitcoin needs any OpenTimestamps client and a Bitcoin node, not Orphograph. The service can be unreachable or gone. It is for photographers, journalists, indie creators, and developers who need to prove a file existed before a given moment, especially before an AI model saw it, and anchoring a file takes about ten seconds. Files never leave the browser: only their fingerprints are sent, and only the 32-byte SHA-256 is committed to Bitcoin. Free tier (3 anchors every 24 hours), $5 Writer Pack (25 anchors), $20 Pack of Two Hundred (200 anchors), $9/mo Standing Order (unrestricted anchoring, private receipts, vault, API).


Quick demo

Four steps a developer can run from a terminal, no signup, no install beyond curl and shasum.

  1. Compute the SHA-256 of any file on disk:

    shasum -a 256 ~/Pictures/my-photo.jpg
    # → 3f8c1b...  my-photo.jpg
    
  2. Submit the hash to the public anchor endpoint:

    curl -sS -X POST https://orphograph.com/api/anchor \
         -H "Content-Type: application/json" \
         -d '{"hash_hex":"<paste the 64-char hex digest>"}'
    

    The response is a JSON receipt with a receipt_id and a list of the OpenTimestamps calendars that accepted the submission.

  3. Pull the receipt back later by ID (or visit /r/<id>):

    curl -sS https://orphograph.com/api/verify/<receipt_id>
    
  4. Verify offline against the original file with the standalone verifier (no orphograph code, MIT, ~100 lines of stdlib Python):

    # Single file with an inclusion proof:
    python3 dist/orphograph-verify/verify.py file \
        --file ~/Pictures/my-photo.jpg \
        --proof receipts/<receipt_id>/proof.json
    # Whole folder against its manifest:
    python3 dist/orphograph-verify/verify.py folder \
        --dir ~/Pictures/evidence \
        --manifest receipts/<receipt_id>/manifest.json
    

    The verifier re-hashes the file (or walks the folder) locally and confirms the result reproduces the manifest's root. Add --ots <path>.ots to also invoke the OpenTimestamps client and check the chain witness references the same root.


MCP server (Model Context Protocol)

Orphograph ships an MCP server: a single stdlib-only Python file (682 lines, MIT) that implements the Model Context Protocol — JSON-RPC 2.0 over stdio, protocol version 2024-11-05, with the initialize, tools/list, and tools/call methods implemented directly, no SDK — so AI agents and MCP hosts (Claude Code, Claude Desktop, or any MCP client) can anchor and verify files as tool calls.

Listed in the official MCP registry as io.github.Orphograph/orphograph.

MCP tools exposed (full JSON Schemas in mcp/manifest.json):

ToolWhat it does
orphograph_anchor_fileHash a local file (SHA-256/SHA-512 computed in-process) and anchor the fingerprints to Bitcoin via OpenTimestamps. The file body never leaves the machine.
orphograph_anchor_folderBuild an RFC-6962 Merkle manifest over a folder and anchor one root that covers every file.
orphograph_anchor_outputAnchor an AI agent's generated output at creation time — provenance receipts for agent actions.
orphograph_verify_receiptLook up what this office recorded for a receipt: anchored hashes, calendar attestation counts, and when the Bitcoin pin was observed. A lookup, not an independent chain check — run ots verify for that. No API key required.
orphograph_verify_lineageWalk an edit-lineage chain back through its committed parents and report the ordering the anchors establish.
orphograph_list_vaultList the authenticated subscriber's anchored receipts.
orphograph_anchor_runAnchor every step of an agent run under one receipt; each step stays provable on its own. Only digests are sent.
orphograph_verify_outputFor the agent receiving an output: does this receipt cover it? Trusts only the anchored hash.

Quickstart (stdio transport):

Also on PyPI: pip install orphograph-mcp (stdlib-only; same server).

curl -sSL https://orphograph.com/mcp/orphograph_mcp.py -o orphograph_mcp.py
claude mcp add orphograph -- python3 orphograph_mcp.py

The free tier needs no API key; set ORPHO_API_KEY to use vault features. An MCPB bundle is attached to release mcp-v0.1.1, and mcp/Dockerfile builds a minimal container for MCP directory crawlers — the server starts and answers MCP introspection with no configuration. Full tool schemas and options: mcp/README.md.


Architecture

Python 3.11+ stdlib only on the server (http.server, urllib, hashlib, json, secrets, fcntl) — zero pip dependencies in the anchor engine. Vanilla HTML + CSS + JS on the client, hashing via WebCrypto SubtleCrypto.digest so file bytes never leave the browser. Each anchor fans out a single 32-byte POST to five OpenTimestamps calendar servers (a.pool, b.pool, alice, finney, btc.catallaxy — the two pools are aggregators for alice and bob, so four distinct calendars); the calendars batch many users' hashes into a single Merkle root and write the root to Bitcoin roughly hourly, which is why our marginal on-chain cost is effectively zero. The .ots proofs are stored per-receipt and verify against the public Bitcoin chain forever, with or without us. Orphograph holds no Bitcoin and takes no on-chain payments: the direct receive-only rail was retired on 2026-09-19 and its routes answer 410 Gone. Payment is by card (Stripe) or through a hosted crypto processor, which settles to the processor and never to an address of ours. No signing keys — and now no addresses — live on production hosts.


Why this exists

By spring 2026 a large share of new images circulating online are AI-generated or AI-modified. Watermarks can be stripped, C2PA labels can be re-signed, EXIF is one shell command away from being anything you want. What survives that is cryptographic proof — a Bitcoin block that already existed at a known time, with the hash of your file committed inside it. Orphograph is the cheapest, most boring way to put a fingerprint of your work into that block before anyone disputes it. Long-form on the thesis: /blog/written-by-an-ai.


Privacy properties

What touches what, in one table.

DatumStays on your machineSent to serverSubmitted to OTS calendarsNotes
File bytesyesneverneverWebCrypto hashes locally
SHA-256 (32 bytes)yesyesyesThe only thing on-chain
SHA-512 sibling (64 bytes)yesyesnoQuantum hedge; OPTIONAL (client-supplied), stored in receipt only, never anchored
Filename / labelyesopt-innoOff by default; pass --label (CLI) or the label argument (MCP tools) to include. The web page sends a fixed source tag (v2-homepage), never the file name
Email addressyesonly when needednoRequired only for Pack delivery + Personal subscriptions
IP addressn/atruncated to /24 (IPv4) or /48 (IPv6)noFull IPs are never persisted

Repo structure

orphograph/
├── server/                       Python stdlib HTTP server + anchor engine
│   ├── engine.py                anchor + verify core (the file in this README)
│   ├── app.py                   ThreadingHTTPServer with /api/anchor /api/verify
│   ├── verify_cli.py            standalone receipt verifier (no engine imports)
│   ├── auth.py                  magic-link tokens + HttpOnly session cookies
│   ├── credits.py               append-only Pack claim-code ledger
│   ├── stripe_webhook.py        HMAC signature verify + idempotent handler
│   ├── subscriptions.py         Personal-tier state derived from Stripe
│   ├── mailer.py                Resend HTTP send (inert when key unset)
│   ├── rate_limit.py            persistent token bucket
│   ├── file_lock.py             fcntl.flock helper for ledger atomicity
│   ├── upgrade_worker.py        OTS upgrade fetcher (cron)
│   ├── expire_worker.py         free-tier receipt pruner (cron)
│   └── gdpr.py                  /api/me/export + /api/me/delete
│
├── web/                          vanilla HTML/CSS/JS — no bundler, no framework
│   ├── index.html, app.js       landing + drop zone + verify section
│   ├── account.html, account.js Personal-tier dashboard
│   ├── signin.html, signin.js   magic-link request form
│   ├── receipt.html, receipt.js print-friendly receipt at /r/<id>
│   ├── style.css                dark glassmorphism, neon-green accent
│   └── terms.html, privacy.html legal pages
│
├── content/blog/                 markdown blog posts (SEO + manifesto)
│   ├── written-by-an-ai.md
│   └── prove-photo-existed-before-ai.md
│
├── tests/                        pytest suite (~98 cases, all stdlib)
│   └── test_*.py                engine / verifier / credits / rate_limit /
│                                 auth / stripe / subscriptions / gdpr / ui
│
├── marketplace/orphograph-plugin/  Claude Code plugin
│   ├── README.md
│   └── skills/anchor, skills/verify
│
├── lightroom-plugin/             Adobe Lightroom Classic plugin (Lua)
│
├── capture/                      desktop capture daemon
│
├── dist/orphograph-verify/       MIT standalone verifier (vendorable)
│
├── scripts/                      operational helpers
│   ├── smoke_test.sh            end-to-end live OTS calendar test
│   ├── dev_setup.sh             fresh-clone sanity check
│   ├── init_volume.sh           container entrypoint (Fly)
│   ├── upgrade_cron.sh          OTS upgrade scheduler
│   ├── expire_cron.sh           free-tier expiry scheduler
│   └── refund_pack.py           zero a claim code after a Stripe refund
│
└── deploy/                       deploy + ops docs
    ├── FLY_PREFLIGHT.md
    ├── SLO.md
    └── SUPPORT_FAQ.md

Local dev

git clone https://github.com/orphograph/orphograph ~/orphograph
cd ~/orphograph
bash scripts/dev_setup.sh           # offline checks + verifier roundtrip
python3 server/app.py               # serves http://127.0.0.1:8989

Run the test suite at any time:

python3 -m pytest tests/ -q

The smoke test hits live OTS calendars and requires network:

bash scripts/smoke_test.sh

Production deploy

Single-container Fly.io with a mounted volume for receipts/ and the JSONL ledgers; Stripe webhook verification, Resend for transactional email, CSP default-src 'self'. Step-by-step in deploy/FLY_PREFLIGHT.md.


Pricing

TierPriceWhat's included
Free$03 anchors per 24 hours per IP-prefix
Writer Pack$5 one-time25 anchors, claim code by email, never expires, skips rate limit
Pack of Two Hundred$20 one-time200 anchors, claim code by email, never expires, skips rate limit
Standing Order$9/moUnlimited anchors, email delivery, account dashboard, anchor history, API key

There is no annual plan and no Creator tier on sale; pricing is the live list.

The $5 / $9 price points are set deliberately low. The wedge is browser-based UX plus the open-source verifier — not the cryptography, which is the public OpenTimestamps protocol.


License

  • dist/orphograph-verify/ — MIT. Vendor it, ship it, audit it. This is the trust artifact: a receipt produced today must verify against Bitcoin five years from now even if orphograph.com no longer exists.
  • marketplace/orphograph-plugin/ — MIT.
  • Everything else — private until launch decisions settle. The founder retains the option to open-source after six months of customer signal.

On the guarantee

The privacy contract of Orphograph is structural, not promissory. Files are hashed in the user's browser; only the SHA-256 (and SHA-512) fingerprint is transmitted. The server cannot reconstruct, identify, or retransmit the file, because it never receives the file. This property holds independently of who maintains the code.