Identity Certificates
Proving something about yourself online usually means trusting whoever is asking with all of it. This defines a certificate where a third party vouches for your details and you choose which of them any particular verifier gets to see.
Summary
- Why
- Verifying a signature proves someone controls a key, but it says nothing about the person behind it, and there was no shared way to attach verifiable, selectively revealable claims to that key.
- What
- BRC-52 defines the identity certificate format: a certifier-signed bundle of encrypted fields tied to a subject's identity key, with keyrings that let the subject reveal chosen fields to chosen verifiers.
- How
- A certifier encrypts and signs a set of fields for a subject's key, hands over a master keyring so the subject can decrypt everything, and the subject later re-encrypts only the requested fields' keys for a specific verifier to reveal just those.
What this lets you do
- Bind verifiable claims to an identity key without exposing them by default
- Reveal only selected certified fields to a chosen verifier
- Verify a certificate's authenticity via the certifier's signature before trusting any field
- Revoke a certificate by spending a designated UTXO
- Package certificates and keyrings in a canonical binary form for wire transport
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
Reference for an AI
Everything an assistant needs to answer questions about BRC-52 accurately, including what it depends on.
The specification
Abstract
This specification defines identity certificates for BRC-100 wallets and peer-to-peer authentication systems. A certificate binds an identity key to encrypted certified fields under a certifier signature, while allowing the holder to reveal selected fields to selected verifiers. The specification covers the core certificate JSON and binary formats, the canonical signature preimage, certificate field encryption, master keyrings, verifier keyrings, and revocation ,[object Object].
This specification is authoritative for certificate primitives used by BRC-100, BRC-103, and BRC-104. Older certificate descriptions in Authrite-era specifications, including BRC-31, BRC-53, and BRC-56, are not normative for BRC-100 certificate behavior.
Motivation
Digital signatures prove control of keys, but applications also need a privacy-preserving way to verify claims about the controller of a key. Identity certificates provide that linkage without requiring the holder to reveal every certified attribute to every verifier. The certifier signs encrypted field values, so the certificate remains tamper-evident even when no fields are revealed. The holder can later provide encrypted field-revelation keys for only the fields a verifier is allowed to inspect.
Terminology
- Subject: The identity key whose holder is certified.
- Certifier: The identity key that signs the certificate.
- Verifier: A party receiving a certificate and optionally receiving keys for selected fields.
- Core certificate: The signed certificate fields, excluding all keyrings.
- Master certificate: A core certificate plus a master keyring that lets the subject or certifier decrypt all certificate fields.
- Verifiable certificate: A core certificate plus a verifier keyring that lets a specific verifier decrypt selected certificate fields.
- Field revelation key: A random 32-byte symmetric key used to encrypt one certificate field value.
- Keyring: A map from field names to encrypted field revelation keys.
The key words "MUST", "MUST NOT", "SHOULD", and "MAY" are to be interpreted as normative requirements.
Primitive Types
| Type | JSON representation | Binary representation | Requirements |
|---|---|---|---|
CertificateTypeID | Base64 string | 32 bytes | Identifies the certificate type. Certificates with the same type are expected to use the same field names and meanings. |
CertificateSerialNumber | Base64 string | 32 bytes | Uniquely identifies a certificate from a certifier. |
PublicKey | Hex string | 33 bytes | Compressed secp256k1 public key. |
RevocationOutpoint | <txid>.<vout> string | 32-byte txid followed by VarInt vout | Identifies the UTXO whose spend revokes the certificate. The disabled sentinel is 0000000000000000000000000000000000000000000000000000000000000000.0. |
Signature | Hex string | DER-encoded ECDSA bytes | Certifier signature over the canonical core certificate preimage. |
CertificateFieldName | UTF-8 string | VarInt length followed by UTF-8 bytes | 1 to 50 UTF-8 bytes. For interoperable signed certificates, field names SHOULD be printable ASCII so all implementations sort them identically. |
CertificateFieldValue | Base64 string | UTF-8 bytes of the Base64 string in CertificateBinary | Encrypted field value, encoded as Base64 for JSON and signed as that Base64 string. |
KeyringValue | Base64 string | Base64-decoded bytes in keyring-map binary encodings | BRC-2 encrypted field revelation key. |
Core Certificate JSON
A core certificate is a JSON object with exactly these signed members:
| Field | Type | Description |
|---|---|---|
type | CertificateTypeID | Certificate type identifier. |
serialNumber | CertificateSerialNumber | Certificate serial number. |
subject | PublicKey | Subject identity key. |
certifier | PublicKey | Certifier identity key. |
revocationOutpoint | RevocationOutpoint | Revocation UTXO reference. |
fields | map of CertificateFieldName to CertificateFieldValue | Encrypted certified fields. |
signature | Signature | Certifier signature. |
Example:
{
"type": "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=",
"serialNumber": "AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI=",
"subject": "024d4b6cd1361032f49d6c5cb7198fdd0458d4fd5f2d0f418da24ff2b63243a6f7",
"certifier": "03531fe6068134503d846f476d6b2e3c000d70bb7c3937c8d537ef7d24c7d9e6c8",
"revocationOutpoint": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef.1",
"fields": {
"email": "uS49rSc3jHRjmE3+/sT1Kf12p2vISiVfDX4SzsqKXWQJdVfuZJcgxjp34MBzEP9PIzK+8j7JqUs=",
"name": "CSDUXeL3aMCSdWGMZmkAPq4iH0K2FfCUvYZZF/7l4hRLIgSJg+gMojGZrXJ+6qKQ"
},
"signature": "304402201f0f2c2d86ad4c2271170cf967f7a9d6106d81e5b7d273decae34d284fcfced9022023cccf38074113a7e8620d9b97b860c7cb7b54805af343c03d3f44ce12da55b8"
}
The signature member MUST NOT be included when computing the signature preimage. Keyrings and decrypted fields MUST NOT be included in the core certificate signature.
There is no validationKey field in this specification. Implementations MUST verify certificates using the certifier identity key and the BRC-100 signature derivation described below.
Certificate Binary Format
CertificateBinary is the canonical binary form of the core certificate and the canonical signature preimage source. It is serialized in this exact order:
| Order | Field | Encoding |
|---|---|---|
| 1 | type | 32 bytes, Base64-decoded from JSON. |
| 2 | serialNumber | 32 bytes, Base64-decoded from JSON. |
| 3 | subject | 33 bytes, hex-decoded from JSON. |
| 4 | certifier | 33 bytes, hex-decoded from JSON. |
| 5 | revocationOutpoint.txid | 32 bytes, hex-decoded txid. |
| 6 | revocationOutpoint.vout | VarInt output index. |
| 7 | fields.count | VarInt number of fields. |
| 8 | each field | Field entries sorted by field name, each as VarInt nameLength, name UTF-8 bytes, VarInt valueLength, value UTF-8 bytes. |
| 9 | signature | DER signature bytes, only when serializing with the signature included. |
Field entries MUST be ordered lexicographically by field name before serialization. For current SDK interoperability, field values in CertificateBinary are the UTF-8 bytes of the Base64 string, not the Base64-decoded ciphertext bytes.
Because the raw signature is the final field and is not length-prefixed in CertificateBinary, any enclosing binary protocol that appends extension data after a certificate MUST length-prefix the complete CertificateBinary first.
Signature Creation and Verification
The signature preimage is CertificateBinary serialized with includeSignature = false. The preimage MUST be hashed with SHA-256 by the BRC-100 signature method before ECDSA signing.
The certifier signs using:
| BRC-100 signature parameter | Value |
|---|---|
protocolID | [2, "certificate signature"] |
keyID | <type> <serialNumber> using the JSON Base64 strings separated by one U+0020 space |
counterparty | Publicly verifiable signature semantics. In current ts-sdk, this is produced by omitting counterparty, which defaults to anyone. |
data | The preimage bytes from CertificateBinary(false). |
A verifier verifies using:
| BRC-100 verification parameter | Value |
|---|---|
protocolID | [2, "certificate signature"] |
keyID | <type> <serialNumber> |
counterparty | The certificate certifier public key. |
data | The same preimage bytes from CertificateBinary(false). |
signature | DER signature bytes decoded from the certificate signature hex string. |
JSON member ordering is irrelevant for signature verification. Implementations MUST NOT use stable JSON stringification as the certificate signature preimage.
Field Encryption
Each certificate field value is encrypted independently:
- Generate a random 32-byte field revelation key
K_f. - UTF-8 encode the plaintext field value.
- Encrypt the plaintext with AES-256-GCM using
K_f. - Encode the encrypted field value as
Base64(IV || ciphertext || tag).
The IV MUST be 32 bytes. The authentication tag MUST be 16 bytes. No additional authenticated data is used by the current reference implementation.
The certifier signs only the encrypted fields map. Plaintext field values, field revelation keys, keyrings, and decrypted field caches MUST NOT be signed as part of the core certificate.
Keyring Encryption
A keyring value is a BRC-2/BRC-100 encrypted field revelation key. The plaintext is the raw 32-byte K_f. The ciphertext is encoded as Base64(IV || ciphertext || tag) where the IV and tag follow BRC-2 encryption behavior.
All certificate keyring encryption uses:
| BRC-100 encryption parameter | Master keyring | Verifier keyring |
|---|---|---|
protocolID | [2, "certificate field encryption"] | [2, "certificate field encryption"] |
keyID | <fieldName> | <serialNumber> <fieldName> using one U+0020 space |
plaintext | Raw 32-byte field revelation key | Raw 32-byte field revelation key |
For a master keyring, the encrypting party sets counterparty to the other party that must be able to decrypt the keyring value. In direct or certifier-issued flows, this is normally the certifier when the subject creates the encrypted fields, or the subject when the certifier creates the encrypted fields.
For a verifier keyring, the subject decrypts the applicable master keyring entries and re-encrypts the raw field revelation keys with counterparty = verifier. The verifier decrypts those keyring entries with counterparty = subject.
Master Certificates
A master certificate is a core certificate plus a complete keyring that can reveal every field in fields.
Canonical JSON extension:
{
"type": "...",
"serialNumber": "...",
"subject": "...",
"certifier": "...",
"revocationOutpoint": "...",
"fields": {
"name": "..."
},
"signature": "...",
"masterKeyring": {
"name": "..."
}
}
The masterKeyring member MUST contain exactly one non-empty keyring value for every field in fields. SDK and wallet API contexts MAY name the same data keyringForSubject or keyring; those names are aliases for the master keyring in that context and MUST NOT alter signature semantics.
Before storing or accepting a master certificate, a wallet SHOULD verify:
- The core certificate signature is valid.
- The master keyring contains an entry for every field.
- Every master keyring entry decrypts to a field revelation key that decrypts its corresponding encrypted field value.
Verifiable Certificates
A verifiable certificate is a core certificate plus a verifier-specific keyring for zero or more selected fields.
Canonical JSON extension:
{
"type": "...",
"serialNumber": "...",
"subject": "...",
"certifier": "...",
"revocationOutpoint": "...",
"fields": {
"email": "...",
"name": "...",
"organization": "..."
},
"signature": "...",
"keyring": {
"email": "...",
"name": "..."
}
}
The keyring member MUST contain only fields present in fields. It MAY be empty or omitted when no fields are revealed. The verifier MUST verify the core certificate signature before relying on any decrypted field. The verifier MUST decrypt only fields for which keyring entries are present.
The BRC-100 proveCertificate result returns this verifier keyring as keyringForVerifier; a transmitted verifiable certificate uses keyring.
Extension Binary Encodings
The raw CertificateBinary format is the only signed binary format. Extension binary formats are unsigned envelopes for carrying keyrings next to a length-prefixed core certificate.
KeyringMapBinary:
| Order | Field | Encoding |
|---|---|---|
| 1 | entryCount | VarInt. |
| 2 | each entry | VarInt fieldNameLength, field name UTF-8 bytes, VarInt valueLength, Base64-decoded keyring value bytes. |
CertificateWithKeyringBinary:
| Order | Field | Encoding |
|---|---|---|
| 1 | certificateLength | VarInt length of the complete CertificateBinary including signature. |
| 2 | certificate | CertificateBinary. |
| 3 | keyring | KeyringMapBinary. |
The same envelope is used for master certificates and verifiable certificates; the interpretation of the keyring is determined by context. When the keyring is absent, protocols SHOULD transmit the raw CertificateBinary rather than an empty envelope.
BRC-100 wallet-wire methods use method-specific envelopes around the same primitives. For example, proveCertificate submits a core certificate structure and receives a KeyringMapBinary; listCertificates length-prefixes each certificate and may append a keyring flag, keyring map, and verifier value. Those wallet-wire envelopes do not change the BRC-52 core certificate format.
Certificate Acquisition and Revelation
Direct Acquisition
In direct acquisition, a wallet receives a signed core certificate and a master keyring from a certifier or other keyring revealer. The wallet MUST set or confirm subject as its own identity key before storage. The wallet MUST verify the signature and confirm that the master keyring decrypts the fields before storing the certificate.
Issuance Acquisition
In issuance acquisition, the subject prepares encrypted fields and a master keyring for the certifier, then sends the encrypted fields to the certifier for signing. The certifier returns a signed core certificate. The subject stores the returned certificate with the master keyring it generated, after verifying that the returned type, subject, certifier, fields, serial number derivation, revocation outpoint, and signature are acceptable for the issuance protocol being used.
Selective Revelation
To reveal fields to a verifier:
- The subject locates the stored master certificate.
- The subject verifies the requested field names are a subset of the certificate fields.
- The subject decrypts each requested master keyring value to recover
K_f. - The subject re-encrypts each
K_ffor the verifier using the verifier keyring parameters above. - The subject returns the verifier keyring, either as a
keyringForVerifierresult or embedded in a verifiable certificate askeyring.
Revocation
The revocationOutpoint points to a UTXO controlled according to the certifier's revocation policy. If that UTXO has been spent, the certificate MUST be treated as revoked. If the disabled sentinel 0000000000000000000000000000000000000000000000000000000000000000.0 is used, UTXO-based revocation is disabled and verifiers MUST rely on the policy for that certificate type.
Certifiers SHOULD publish clear rules for revocation monitoring, reissuance, and key compromise handling. If a certifier identity key is compromised, the certifier SHOULD revoke affected certificates and reissue under a new certifier identity key.
Implementation Basis
This revision is grounded in the reference behavior of the BSV SDK and Wallet Toolbox certificate implementations, including:
Certificate,MasterCertificate, andVerifiableCertificatebehavior inbsv-blockchain/ts-sdk.- Certificate lifecycle, wallet storage,
acquireCertificate,listCertificates, andproveCertificatebehavior inbsv-blockchain/wallet-toolbox.