BitGraph Actor
A recording made at bitgraph.ing/actor is an ordinary BitGraph plus one thing: an authorization for that exact file, made with a passkey you control and verified inside the enclave, against a nonce of its own, before anything is recorded. Same slot, same order, same anchors. Only the who differs.
BitGraph never learns who you are. The proof carries a key. Who holds it is a question for whoever reads the proof, answered from a source they choose.
How it works
- Once, per browser: register a passkey. Touch ID, Face ID or Windows Hello creates a passkey for bitgraph.ing. The private key stays with your platform's passkey provider or authenticator, which may sync it across your devices; it is never exposed to BitGraph. The passkey is scoped to bitgraph.ing: your authenticator will not use it for another site. What the proof will carry is the public key and its
keyId, the SHA-256 of that public key. - Drop a file, as on home. It is hashed in your browser and the ledger is read. A file already on record comes back as the positions it holds, and nothing is signed: a lookup is not a recording.
- For files not yet on record, the enclave issues a nonce. Its own, from its hardware random source, kept for 60 seconds and accepted once. A nonce the caller chose would prove nothing about when the caller chose it.
- One touch. Your authenticator signs that nonce: a WebAuthn assertion over the authenticator data and the client data, which carries the nonce. Nothing else is signed by the key. Around that signature goes an envelope naming the key, the file's digest, the purpose and the moment; the signature is what makes the envelope's nonce yours, and the enclave is what binds the rest.
- The enclave checks before it allocates anything. The nonce is its own and still pending; the purpose is
bitgraph/commit-authorize/v1; the digest named is the digest being committed; thekeyIdis the hash of the public key; the moment is inside the window; the authenticator reported the user present and verified; the signature verifies under that key over that nonce. Then it consumes the nonce and binds the file's hash into its slot with the actor inside the signed body. - A batch is one touch. One full authorization, on the first file of a run, opens a batch context inside the enclave: this actor, the list of digests the run declared, 60 seconds. The rest of the run inherits the actor only for digests on that list and only inside that window. Forty photos ask once.
What a declared proof carries
One object beside the rest of the proof. actor is inside the body the enclave signs, so it cannot be attached to a proof afterwards or removed from one. The authorization's own P-256 signature is checkable on its own, with no enclave involved.
"agency": {
"actor": {
"keyId": "ee0c6517…", // hex SHA-256 of the public key (SPKI DER)
"publicKeyB64": "MFkwEwYHKoZI…", // P-256 public key
"algorithm": "ES256",
"provider": "passkey"
},
"authorization": {
"purpose": "bitgraph/commit-authorize/v1",
"format": "webauthn",
"actorKeyId": "ee0c6517…", // must equal actor.keyId
"artifactHash": "<digestB64>", // must equal artifact.digestB64
"challenge": "<the enclave's nonce>",
"timestamp": 1755620000000,
"authenticatorDataB64": "…", // flags: user present, user verified
"clientDataJSON": "{…\"challenge\":…}",
"signatureB64": "…" // P-256 over authenticatorData ‖ SHA-256(clientDataJSON)
},
"batchContext": { // present on a run of more than one file
"batchSize": 40, "batchIndex": 0, "batchDigests": ["…"]
}
}The rest of the format is on Proof Format.
What it establishes
That this key authorized this recording at this position: a passkey controlled through the holder's authenticator signed the enclave's nonce, with the user present and verified, and the enclave checked the authorization before it allocated the slot.
Not authorship. Anyone can act on a file they downloaded. The proof fixes which key authorized the recording, never who made the bytes or when.
Not a name. BitGraph never learns one. On a proof page the Actor card prints a name only when the browser reading it holds that very key; beside anyone else's key it reads “Not established here”, which is the claim shown rather than asserted. Any mapping from a key to a person comes from a source the reader chooses. A published register, when one exists, will be one such source, and the card will say so rather than present it as BitGraph's.
Actor is an authorization attached to a BitGraph proof. It is not an identity check, not a certificate of authorship, and not proof that a human made the file.
The cost
Every recording made under one key can be linked to every other. That is the feature, and it is the price. When the who is not the point, record from home instead: the same slot, the same order and the same anchors, with no key on the proof. An enrolled browser can still do that, and should.
There is one chain. Declared recordings are not kept on a ledger of their own, so the anonymity set of an anonymous recording is every recording ever made. BitGraph needs the key for none of this; it never needs the person.
Reading one
On a proof page, the Actor card shows the name (when it can), the key, and what signed: a passkey, or the actor's own key.
Offline, bitgraph-verify re-checks the authorization from the proof alone: that keyId is the SHA-256 of the public key, that actorKeyId and artifactHash match the actor and the artifact, that the client data is a webauthn.get over this nonce, that the origin the client data names agrees with the RP ID the authenticator scoped the passkey to (its rpIdHash), that the authenticator reported presence and verification, and that the P-256 signature verifies over the authenticator data and the hash of the client data. A verifier's policy can require an actor on every proof, accept only named keys or providers, or accept only named origins (requireActor, allowedActorKeyIds, allowedActorProviders, allowedOrigins).
Forgetting a device
Forget this device removes the key from this browser. The passkey itself stays with your passkey provider until you delete it there, and registering again makes a new key: recordings made under the old one keep it, which is the honest account of what happened. There is no rename. The label beside the key is this browser's own and never enters a proof.