Skip to content

Fingerprints

A fingerprint is a SHA-256 digest over the canonical JSON of every fact a verifier cares about. Change any committed fact — one field, one character of purpose, one entity — and the fingerprint changes.

Computed at grant time over exactly these keys:

{
"share_id": "<share id>",
"client_id": "<recipient public client id>",
"consumer_id": "<subject id>",
"fields": ["<granted field keys, as granted>"],
"purpose": "<purpose string>",
"granted_at": "<ISO-8601 UTC, millisecond precision>",
"expires_at": "<ISO-8601 UTC, millisecond precision>",
"origin_domain":"<capturing domain>",
"terms_version":"<hub terms version identifier>"
}

fingerprint = SHA256(canonical_json(facts)), lowercase hex.

Facts:

{
"share_id": "sh_0000000000000000example0",
"client_id": "pc_example000example000exam",
"consumer_id": "con_0000000000000example00",
"fields": ["email", "first_name", "phone"],
"purpose": "Send the weekly newsletter",
"granted_at": "2026-01-15T12:00:00.000Z",
"expires_at": "2027-01-15T12:00:00.000Z",
"origin_domain": "example.com",
"terms_version": "2026-01-01"
}

Canonical form:

{"client_id":"pc_example000example000exam","consumer_id":"con_0000000000000example00","expires_at":"2027-01-15T12:00:00.000Z","fields":["email","first_name","phone"],"granted_at":"2026-01-15T12:00:00.000Z","origin_domain":"example.com","purpose":"Send the weekly newsletter","share_id":"sh_0000000000000000example0","terms_version":"2026-01-01"}

Fingerprint:

74c4095855e6b83499b92edfd1d620ca4dd3e07219eaaed3635d1235369e484f

Certificates commit to the disclosure and the one-to-one entity list rather than to a subject account. Composition:

{
"cert_id": "<certificate id>",
"business_id": "<recipient id>",
"business_name": "<recipient display name>",
"disclosure_hash": "SHA256(<verbatim disclosure text>)",
"entities": ["<entity list, sorted lexicographically>"],
"origin_domain": "<verified capturing domain>",
"purpose": "<purpose string>",
"subject_hash": "SHA256(canonical_json(<submitted fields>))",
"timestamp": "<ISO-8601 UTC issuance time>"
}

Two deliberate properties:

  • The subject appears only as a hash. The fingerprint is publicly publishable; the submitted values are not derivable from it.
  • entities is sorted before hashing (unlike share fields), so presentation order can’t change the commitment to the one-to-one list.
  • Disclosure text: I agree to be contacted by Example Co about my inquiry.disclosure_hash = 375bcf40f27d2b3be544291533ba63a19439a3bfec0479f5896e16da2b1e3b04
  • Subject fields {"email":"jane@example.com","first_name":"Jane"}subject_hash = a7e5dfb95d663b466e45baf0026f16d13639e5edb111623e1531040ef85fd074
  • With cert_id = cc_example000000example00, business_id = biz_00000000000example000, business_name = Example Co, entities = ["Example Co","Example Partners LLC"], origin_domain = example.com, purpose = Discuss insurance options, timestamp = 2026-01-15T12:00:00.000Z:
fingerprint = 93aa61107cd99019767e16dc82465199f25d17ee33169bb66285c2e081e0cca8

Given a certificate’s public verification record:

  1. Recompute disclosure_hash from the published disclosure text.
  2. Rebuild the composition object from the published facts (sort entities).
  3. SHA256(canonical_json(...)) and compare to the published fingerprint.
  4. Optionally, confirm the fingerprint’s external anchor and its Merkle inclusion proof.

Any mismatch means the record was altered after issuance.