How it works

A BitGraph proves a simple order: a position came first, then your file filled it. What fills it is your file plus a commitment to the position, and nothing made before the position can contain that commitment. Your original file stays unchanged. This page explains the operation, what crosses the enclave boundary, how the commitment is carried, where time comes from, and how epochs contain a compromise.

1. One operation, two states

BitGraph does one thing. It allocates a position in a signed sequence inside a trusted execution environment, which in production is an AWS Nitro enclave. Your device derives a commitment to that position and combines it with your file to produce new bytes. The enclave then binds the SHA-256 fingerprint of those bytes to the position and consumes it.

The protocol calls the fingerprint the digest and the allocated position a slot. Allocation comes first and the commit comes later; between them, your device builds the bytes that connect the two. Every BitGraph made on this site, in the SDK and in the MCP server is made this way.

YOUR DEVICEENCLAVE / TEE2. Open a positionfrom an empty request: nothing of the filea signed slot record: nonce, counter, epochposition held, unspent4. Commit under the positionthe digest bound, signed and attestedthe position consumed, once, in one stepYour fileany bytes3. New bytesthe file + a commitment derived here from the slot recordbuilt on your device, never uploaded1. ask for a positionsigned slot recorddigest of the new bytes + the slot recordProofwith the file,verifies offline
The bytes name the position, and the position names the bytes. The position was open before the new bytes were final, so they could not have been finished before it. The commit spends the position on exactly those bytes in one indivisible step, so it can never name any others.

Allocation. The enclave draws 32 bytes from its hardware random number generator, advances a counter, and signs a small record: the nonce, the counter, the epoch identifier, its own public key and the latest Ethereum anchor it has authenticated. This is the slot record. It has no field that could hold a digest and is signed before any digest reaches the enclave. The slot is kept in enclave memory as unused.

The new bytes. From the signed slot record your device derives a 32-byte commitment, builds the new bytes with it, and hashes them. Section 3 covers where the commitment goes in different kinds of file.

Commit. The new bytes’ digest arrives together with the slot’s identifier. In one atomic step the enclave deletes the slot from its table, binds the digest to it, records both counters and the hash of the slot record in a signed body, signs the body with its Ed25519 key, and obtains a hardware attestation over that exact body. There is no partial state: if any part fails, no proof exists and the slot is simply lost. A slot is consumed once and never reused. Storing BitGraph’s public copy happens afterwards, outside that step.

The proof. What comes back is a JSON document: the digest, the commit fields, the signature, the enclave’s measurement and attestation, the slot record itself, and a signed marker naming the original’s digest. It is returned to whoever asked and travels with the original. BitGraph also keeps a public copy, indexed by digest, for retrieval. Verification uses the proof you hold and does not require contacting the service.

Why the order matters

Signatures, timestamps and blockchain commitments all work on a file that already exists, so any of them can be applied to a file made an hour earlier. The commitment reverses that: it makes the finished bytes depend on the slot. Because the slot contains fresh randomness drawn at allocation, bytes carrying its commitment could not have been finished before it existed. Committing their digest then binds that exact version to the same slot.

That bound applies to the new bytes. The original inside them can be any age: making a BitGraph today does not establish when its content was created.

This is still worth having for a file that already exists. From the commit on, its exact bytes hold a fixed place in the sequence: they existed no later than the commit, and any later BitGraph of the same bytes can only take a later place. The commitment in the new bytes and the fingerprint in the proof point at each other, so changing either breaks the pair, and the proof cannot be moved onto other bytes.

2. What crosses the boundary

The file itself never crosses. On the public site, in the MCP server and in the SDK, the new bytes are built and hashed where the file is, and the commit request carries only their digest, the slot record and the signed marker with the original’s digest. That is a property of each client rather than of the protocol: a client can send whatever it likes, and a verifier should read the client’s source if it matters. The service sees the requester’s address and those two digests, and publishes them with the position and the anchors. It never sees the file.

The enclave is a measured environment. Its image is identified by a hash, PCR0, that AWS computes at boot and that anyone can reproduce from the published source. The enclave’s signing key is generated inside it and never leaves. Every proof carries an attestation document, signed by the Nitro hardware, whose user data is the hash of that proof’s signed body. A verifier who pins the published PCR0 is therefore checking not only that some key signed the proof but that the key belonged to that specific code.

What the producer can and cannot choose

A position stays open for up to 120 seconds, and a caller can hold several at once, choose which file fills which, or leave one unused. What a caller does not choose is the order of the positions: the enclave issues them one after another on a single counter, each proof naming the one before it, and a position left unused is lost rather than returned. The choice is which file takes a position, never where that position sits in the sequence.

Every workflow uses the same rules. An audit record and a photograph pass through the same measured enclave, with no customer-specific build. Workflow context is bound into the signed proof alongside the file’s digest: a policy digest, a key identifying the actor, an attribution. The enclave seals that context without reading it, so it never changes how a position is issued or bound. A verifier can pin the published measurement and confirm that proofs from different workflows came from the same expected implementation.

3. Carrying the position inside the bytes

For a file that already exists, the new bytes wrap it: the commitment is added after the last byte for formats whose decoders ignore trailing data, such as JPEG and PNG, and for everything else the file goes first into a small container that holds the commitment. The original is never modified, and the new file need not be kept: the original plus the proof rebuilds it byte for byte, and checking that reconstruction against the committed digest is the evidence.

original fileunchanged, any age+slot #4,201commitment32 bytes, from the slot record=the new fileoriginal, then the commitment48 BBuilt on your device. The new bytes could not have been finished beforethe slot existed, because they contain a value derived from it.SHA-256 fingerprint of the new filecommitted under slot #4,201,the slot the commitment names
original fileunchanged, any age+commitment to slot #4,20132 bytes, derived here from the slot record=the new fileoriginal, then the commitment48 BSHA-256 fingerprint of the new filecommitted under slot #4,201the slot the commitment names
The commitment is SHA-256 over a fixed label, the hash of the signed slot record and the slot’s nonce. It is derived on your device and only the commitment enters the new file, never the nonce. For formats whose decoders ignore trailing bytes (JPEG, PNG, GIF, TIFF, BMP, WebP) the commitment rides in a 48-byte trailer; for everything else the original is wrapped, unchanged, in a small tar container. Either way the original plus the proof rebuilds the new file byte for byte, so the new file need not be kept.

A format you produce yourself, such as an AI system’s audit record, can carry the commitment in a field of its own. Then there is nothing to rebuild: the record with its commitment is the file you keep.

Either way, the new bytes name the slot and the slot names the new bytes, and the anchor signed into the slot record puts a public time under them. The proof’s signed attribution field carries the marker: the label bitgraph-fuse/1, the placement used and, for a wrapped file, the digest of the original.

Two or more files made together become one set under one slot, with each file a member that keeps its own row and inclusion path. The proof format page has the byte-level placements.

4. Where time comes from

Nothing inside the sequence is a clock. Counters and previous-proof hashes give a total order within an epoch, and that order needs no time to be checked. Wall-clock statements come from outside, from Ethereum, which BitGraph reads and never writes to.

An anchor is an ordinary position whose file is the hash of a recent Ethereum block, committed by the same enclave, on the same sequence, with the same key. The enclave accepts an anchor only from an anchor service whose signature it verifies against a key baked into its image, and it records the block number and hash in the signed body. A block hash cannot be known before its block is mined, so an anchor, and everything the sequence placed after it, came after that block.

ETHEREUM · public blocks, read onlyblock 25,984,342mined 17:25:47 UTCblock 25,984,343mined 17:25:59 UTCblock 25,984,344mined 17:26:11 UTCthe block hash, committed as a fileTHE BITGRAPH SEQUENCEanchor #4,190slot #4,201 · commit #4,202anchor #4,210anchor #4,230floor: after 17:25:47 UTCceiling: before position 4,210
SEQUENCEETHEREUM BLOCKSblock 25,984,342mined 17:25:47 UTCblock 25,984,343mined 17:25:59 UTCblock 25,984,344mined 17:26:11 UTCanchor #4,190slot #4,201commit #4,202anchor #4,210anchor #4,230floorceiling
Illustrative numbers. An anchor is made after the block it carries, so an anchor’s position is later than its block’s time. That is why the floor is exact (the block was mined before the slot was allocated, and the slot record says which block) and why the next anchor’s block time is not an upper bound: the record can sit after that block was mined and still before the anchor took its position. The ceiling is the anchor’s position, which is a fact about the sequence, not about the clock.

The floor. Every slot record on the anchored sequence names the latest anchor at the moment of allocation (since enclave version 7), and since version 8 the enclave refuses to sign a proof whose slot carries none. The block that anchor names had been mined before the slot existed, so its time is a lower bound on the position that nobody involved chose. A verifier reads the block’s time from its header, which an export ships as a witness, and can confirm the same block on any Ethereum explorer.

The ceiling. The next anchor the sequence took is the position’s ceiling: the record was committed before that anchor took its place. That is a fact about order in the sequence and it does not convert to a clock reading. An anchor is made after the block it carries, so a record can sit after that block was mined and still before the anchor. No field in a proof is a trusted timestamp, and BitGraph makes no wall-clock upper-bound claim.

The anchor cadence is a deployment setting, as frequent as one anchor per Ethereum block. Anchors are not confirmation-delayed: a chain reorganisation near an anchor can orphan the block it names, in which case the witness check fails and that temporal bound is lost rather than silently wrong. Ordering within the sequence is untouched by anything that happens to Ethereum.

5. Compromise and containment

BitGraph assumes the boundary can be compromised and bounds the damage rather than claiming it cannot happen. The signing key exists only in enclave memory. Every restart destroys it and begins a new epoch with a fresh key and a counter at zero; in production the enclave restarts every day at 23:59 UTC, so an epoch is one UTC day.

ETHEREUM BLOCKS NAMED BY THE ANCHORSEpoch: 14 Sep 2026 (UTC)key A · counter restarts at 0#2#12,40625,970,12025,977,300Epoch: 15 Sep 2026 (UTC)key B · counter restarts at 0#2#12,40625,977,30225,984,480Epoch: 16 Sep 2026 (UTC)key C · counter restarts at 0#2#12,40625,984,48225,991,66023:59 UTCkey destroyed23:59 UTCkey destroyedincreasing left to right: the public order of the epochs
Epoch: 14 Sep 2026 (UTC)key A · counter restarts at 0block 25,970,120block 25,977,300#2#12,406Epoch: 15 Sep 2026 (UTC)key B · counter restarts at 0block 25,977,302block 25,984,480#2#12,406Epoch: 16 Sep 2026 (UTC)key C · counter restarts at 0block 25,984,482block 25,991,660#2#12,40623:59 UTC: key destroyed23:59 UTC: key destroyedblock numbers increase down the page
Each compartment is one enclave lifetime: a fresh key generated in enclave memory and a counter starting at zero. In production the enclave restarts every day at 23:59 UTC, so an epoch is one calendar day. When it ends, its key is destroyed and cannot sign again; that is what makes a closed epoch fixed rather than merely append-only. Counters mean nothing across epochs. What relates one epoch to the next is public: each anchor names an Ethereum block, and the blocks increase.

Proofs from a closed epoch were signed by a key that no longer exists anywhere, so a compromise cannot reach backward. Forgery within the live epoch requires more than stealing a key: every proof carries an attestation whose user data is the hash of that exact proof, and only the enclave’s hardware module can produce one, so a useful breach must execute inside the running enclave and dies at the next restart. Every proof names its epoch permanently, so a suspect window is identified exactly: the affected epoch is published as quarantined and every other epoch is untouched. What this does not give is detection: a perfect forger inside the enclave during its epoch mints proofs that verify. The trust model lists what is prevented, what is detected, and what is neither.

Epochs cannot be chained by signature, because no key ever witnesses both sides of the boundary; the old key is destroyed on purpose. What relates one epoch to another is Ethereum. An epoch’s anchors give it a floor that anyone can check without trusting either enclave: it ran no earlier than the blocks they cite. They do not prove on their own that it ended before a later epoch began, because an enclave can be handed an old block hash; that side comes from observation, such as the write times of BitGraph’s public copy or anyone who saw the anchors land. Two enclaves run by different operators would be two unrelated sequences, related to each other in the same way and no other.

What a proof contains

FieldWhat it establishes
artifact.digestB64The committed new bytes: your file plus the commitment. Any change to either changes the digest.
slotAllocationThe slot record: nonce, counter, epoch, key, signature. Made before any digest was received.
commit.slotCounter, commit.counterThe slot’s position and the commit’s. The first is always smaller.
commit.slotHashB64Hash of the slot record, inside the signed body, so the slot cannot be swapped.
commit.prevB64Hash of the previous proof on the sequence: the link that makes the order checkable.
commit.slotAnchorThe Ethereum block the floor rests on, signed into the slot record.
signer, environmentThe enclave’s key and signature, its PCR0 measurement, and its hardware attestation over this body.
attributionSigned. The marker, the placement and, for a wrapped file, the original’s digest.
metadata, timestampsUnsigned and advisory. Never evidence.

Every field, its encoding and what is and is not signed: proof format. The same account in formal terms, with the invariants: the protocol.

Where next

  • Make a BitGraphDrop any file in your browser. Only its fingerprint leaves your machine, and the proof comes back to you.
  • Integration guideThe same operation from the SDK, the CLI, or two HTTP calls.
  • VerificationWhat a verifier checks, in order, and what each result means.
  • LimitsTruth, authorship, first creation, exact time, a universal order.