How Ankorith works
A technical description for CTOs, IT architects and security teams. It describes the service as it runs today on ankorith.com — the same code our own web application uses. Numbers marked "in our tests" come from our internal measurements, not from an external audit.
Patent pending — European patent application EP26209596.1. The technology described on this page is protected by a filed European patent application. This description is provided so that you can understand, evaluate and integrate the service; it does not grant any licence under the patent application or any other intellectual property right.
- Architecture
- The seal and the label in the file
- Robust appearance fingerprint and change localisation
- Public log and Bitcoin anchor
- Verified issuer
- Quantum resistance
- API
- Security and privacy
- What a seal does not do
1. Architecture: the file never leaves the device
All work on the file itself happens in the browser of the person who seals or verifies it (Web Crypto and canvas, no plug-ins). The file is never uploaded. The server receives only derived values:
| Sent to the server | When | What it is |
|---|---|---|
| SHA-256 of the file | sealing and verification | Exact fingerprint (64 hex characters). |
| Appearance fingerprint | sealing and verification (images) | 64-bit difference hash of the image's brightness — finds the seal again after recompression or resizing. |
| Change-localisation grid | sealing only (images) | A coarse 48 × 48 grid of tile statistics (about 18 kB) — enough to show where an image was changed, far too coarse to reconstruct it. |
| Declaration, optional tool and title | sealing only | What the issuer declares about the origin of the content. |
Verification returns the seal to the browser, and the browser checks it itself: it verifies the signature of the public log, recomputes the inclusion proof and compares the image against the sealed grid. A verifier does not have to trust our server for the result.
2. The seal and the label inside the file
A seal binds a file fingerprint to a verified issuer, a declaration of origin and a time, and writes this binding to the public log. Seal identifiers are 96-bit random values.
For JPEG and PNG, the browser also writes a machine-readable label into the file itself — an XMP packet (an APP1 segment in JPEG, an iTXt chunk in PNG) that replaces any previous XMP packet. It carries:
Iptc4xmpExt:DigitalSourceType— the IPTC Digital Source Type vocabulary, the machine-readable marking that Article 50 of the EU AI Act asks for (guide);ankorith:Seal,ankorith:Verify,ankorith:Issuer,ankorith:Declarationand optionallyankorith:Toolin the namespacehttps://ankorith.com/ns/seal/1.0/.
| Declaration | IPTC Digital Source Type |
|---|---|
| photo — photograph taken with a camera | digitalCapture |
| human — made by a human, without generative AI | humanEdits |
| ai-edited — edited with AI | compositeWithTrainedAlgorithmicMedia |
| ai-generated — generated by AI | trainedAlgorithmicMedia |
The label is written before the final fingerprint is taken (reserve → embed → issue), so the sealed file is exactly the labelled file. Optionally, a visible swirl mark encoding the seal id can be drawn into a corner of the image. Other file types (PDF, video, audio, documents) are sealed by their SHA-256 fingerprint without a label inside the file.
3. Robust appearance fingerprint and change localisation
Social networks and messengers recompress and resize images and usually strip their metadata. An exact hash then no longer matches and the label inside the file is gone. Ankorith therefore seals images with two additional, robust structures:
Robust identifier — finding the seal
A 64-bit difference hash of the image's brightness. The service indexes it in four 16-bit bands, so a recompressed copy is found by a single lookup; candidates within 10 differing bits are returned, closest first.
Grid of regions — showing where the image was changed
The image is divided into 48 × 48 = 2,304 tiles. Each tile carries eight statistics: mean brightness, two colour components, the brightness of its four quarters and an edge-energy measure. To make results identical across browsers, the image is downsampled by our own deterministic code (integer averaging followed by Lanczos-3), not by the browser's canvas scaler.
At verification, global changes that platforms apply to the whole image — brightness, contrast, colour shifts — are estimated with a robust linear fit and removed; each tile's deviation is then measured relative to its own texture and to the noise level measured on the copy. Tiles that differ beyond the threshold are marked red. Heavily compressed copies, and copies whose shorter side is below 500 px, are evaluated in a conservative mode: clear changes are still red, and areas that cannot be reliably told apart from compression noise are marked yellow rather than declared changed. A copy whose global brightness relation to the original is implausible is treated as a different image. The grid itself is stored with the seal and only its SHA-256 goes into the public log; the browser checks that the grid it received is the sealed one.
In our tests
40 test photographs, each recompressed in 7 ways (Facebook, Instagram, WhatsApp, sharing twice, darkening followed by Facebook, hard JPEG compression, a small copy) — 280 unmodified copies — and 1,692 tampered copies (replaced patch of 2 % and 1 % of the image, covered area 1.5 %, rewritten text 3 %, recoloured area 3 %, each published through Facebook and Instagram):
| Result | In our tests |
|---|---|
| Unmodified copies marked as changed (red) | 0 of 280 |
| Red tiles outside the edited area | 0 |
| Tampered copies with red at the place of the edit | 1,288 of 1,692 |
| — covered area 1.5 % (standard copies / copies evaluated in conservative mode) | 276 of 280 / 118 of 120 |
| — replaced patch 2 % | 246 of 262 / 75 of 110 |
| — rewritten text 3 % | 220 of 254 / 56 of 86 |
| — replaced patch 1 % | 164 of 256 / 27 of 112 |
| — recoloured area 3 % | 76 of 122 / 30 of 90 |
The design goal is no false accusation: in these tests the grid never marked an unmodified copy, or an untouched area, as changed. Covered or replaced areas from roughly 2 % of the image are found in the large majority of cases; subtle recolouring and very small edits are harder, and edits below that size cannot be ruled out.
4. Public log and Bitcoin anchor
Every issued seal and every verified issuer is appended to a public, append-only log. The log is a Merkle tree built exactly as in RFC 6962 (Certificate Transparency): leaves are hashed as SHA-256(0x00 ‖ entry), inner nodes as SHA-256(0x01 ‖ left ‖ right), entries are canonical JSON with sorted keys, and log positions are written only if they do not exist yet, so an entry cannot be overwritten.
- Signed tree head. The tree size, root hash and time are signed with ML-DSA-65 (NIST FIPS 204). The verification page checks this signature in the browser against a public key whose fingerprint is pinned in the page code — if the server ever presented a different key, the page reports it.
- Inclusion proofs. For any seal, the browser downloads the entry and its RFC 6962 audit path and recomputes the signed root itself.
- Bitcoin anchor. Twice a day, the signed tree head is timestamped through OpenTimestamps (several independent calendar servers) and, typically within hours, committed to a Bitcoin block. The proof is a standard
.otsfile that anyone can check with the official OpenTimestamps tools — without us. From that point, not even the operator can rewrite history without it being detectable. - Minimal content. The log holds the file fingerprint, appearance fingerprint, issuer domain, declaration, optional tool name, time and the SHA-256 of the grid and of the title — never the title itself and never the file.
Public endpoints (JSON): /api/zaznam/hlava (signed tree head), /api/zaznam/klic (log public key), /api/zaznam/polozka?i= (entry), /api/zaznam/dukaz?i=&n= (inclusion proof), /api/zaznam/kotvy and /api/zaznam/kotva?velikost= (Bitcoin anchors and .ots files).
SHA-256 fingerprint of the pinned log public key: b520ba5df9401613cbbdd1a12f3af33a95038be9142dd627b43af9a704533fac
5. Verified issuer
The issuer of a seal is not free text — it is an internet domain whose control has been proven:
- a DNS TXT record
_ankorith.yourcompany.comwith the valueankorith-verify=<token>, checked through two independent DNS-over-HTTPS resolvers, or - a file
https://yourcompany.com/.well-known/ankorith.txtwith the same value.
The token is valid for 7 days. A successful verification is written to the public log and issues the company's primary API key. Verifying the domain again issues a new primary key and immediately invalidates the old one.
6. Quantum resistance
Seals are meant to be verifiable for decades, longer than today's public-key algorithms are expected to stay safe against quantum computers. Ankorith therefore builds its long-term evidence on post-quantum and hash-based cryptography:
| Component | Cryptography | Quantum outlook |
|---|---|---|
| Signature of the public log | ML-DSA-65 (module lattices, FIPS 204) | Post-quantum standard |
| Merkle tree, file fingerprints | SHA-256 | Hash-based; quantum search gives only a square-root speed-up |
| Bitcoin anchor (OpenTimestamps) | Chain of SHA-256 operations into a block header | Hash-based; relies on Bitcoin's proof of work, not on signatures |
| Signatures from the mobile capture app | P-256 and ML-DSA-65 (hybrid) | The server accepts a photo only if both signatures verify |
| Transport (HTTPS) and domain verification (DNS, HTTPS) | Classical | Protects the moment of issuance, not the long-term evidence |
7. API
A REST API at https://ankorith.com/seal/api/ with bearer keys (ak_…, 256 random bits): bulk sealing of up to 100 fingerprints per request, the two-step reserve/issue flow for labels inside files, public verification by id, SHA-256 or appearance fingerprint, named sub-keys per system or department, usage per month and key, and webhooks signed with HMAC-SHA256. Our own web application uses the same interface. Full reference: API documentation; a step-by-step integration guide: pilot program.
8. Security and privacy
- Data minimisation by design. Files are never transmitted. The public log holds fingerprints only; titles are stored outside the log and only their hash is public.
- Keys. API keys are shown once and stored by us only as SHA-256 fingerprints. Only the primary key can issue and revoke sub-keys or configure webhooks. Webhooks are delivered only to public HTTPS addresses.
- Accounts. Sign-in with Google, Microsoft, GitHub, a one-time e-mail link or a passkey — no passwords stored.
- GDPR. The operator is GP novum s.r.o., a company established in the Czech Republic (EU). A Data Processing Agreement is available; see the Privacy Policy.
- Hosting. The website, server functions and storage run on Netlify, Inc. (USA); the transfer is based on the EU-US Data Privacy Framework and, where that does not apply, the European Commission's standard contractual clauses. Sign-in e-mails are sent by Brevo within the EU. Because files never leave the device, no customer content is transferred at all — only fingerprints and account data.
- Security questionnaires and responsible disclosure: info@gpnovum.cz.
9. What a seal does not do
- It does not prove that the content is true. It proves who (a verified domain) declared what about the file, when, and whether the file has changed since. The issuer is responsible for its declaration.
- Exact match versus appearance match. Only images get appearance matching and change localisation. Other files match only bit for bit.
- Small edits. Edits smaller than roughly 2 % of the image's shorter side cannot be ruled out; on heavily compressed or small copies some areas are reported as uncertain (yellow) instead.
- Cropping, rotation and mirroring. The appearance fingerprint is built for recompression and resizing; heavily cropped, rotated or mirrored copies may not be found.
- Seals issued without the grid (for example bulk sealing of fingerprints only) can be found again by appearance, but cannot show where an image was changed.
- Metadata can be removed. The XMP label disappears when a platform strips metadata — that is exactly why the seal can be found again from the image itself.
- No C2PA manifest. The current version writes an IPTC/XMP label; it does not embed a C2PA manifest.
- Permanence. Entries in the public log cannot be deleted — that is the point of the log. Do not put personal data into seal titles.