Identity, Certificates, Discovery, and Personal Trust in Applications
Right now, if an app wants to know who it's talking to, it usually has to make the person create a new account, trust some central ID provider, or hand control of their identity to whichever platform they signed up through. There was no way for a person to publish facts about themselves once and let any app, from any vendor, verify and reuse them on the person's own terms. This makes it possible to address someone by a cryptographic key, pull up what they've chosen to reveal, and ask them directly for more, without a new directory or gatekeeper for every app.
Reference for an AI
Everything an assistant needs to answer questions about BRC-189 accurately, including what it depends on.
Summary
- Why
- Apps need a way to identify and verify users without each one building or depending on its own centralized account and identity-provider system.
- What
- BRC-189 is a specification that ties together certificates, wallet APIs, peer authentication, and discovery so apps can look up, verify, and personally trust a person's identity through their own wallet.
- How
- A user's wallet holds certified attributes and contacts, publishes selected ones through the tm_identity topic, and apps query ls_identity or call BRC-100 discovery methods, with the wallet applying the user's own trust anchors before handing back any result.
What this lets you do
- Look up a person's publicly revealed attributes by their identity key
- Request additional certified fields directly from that person over an authenticated connection
- Publish selected certificate fields publicly while keeping the rest encrypted
- Let users set their own trusted certifiers instead of a fixed registry
- Save personal contacts with a label and photo, independent of any certifier
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
An application can address a person by a cryptographic identity key, discover attributes that the person has chosen to publish, and request further certified information directly from that person. The application need not create another username directory, require an account at a particular wallet vendor, or ask a central identity provider to authorize every interaction. The user's wallet supplies identity operations, applies the user's chosen trust relationships, and preserves personal associations through contacts.
This proposal connects the certificate primitives of BRC-52, the application interface of BRC-100, the peer authentication and disclosure mechanisms of BRC-103, and the descriptive registries of BRC-184. It specifies public attribute revelation, tm_identity admission and withdrawal, ls_identity discovery, the deployed trust calculation, and encrypted contact records. It distinguishes a certifier's assertion, a user's personal assertion, proof of key control, a current revocation assessment, and permission to act. Worked application journeys and reproducible test vectors show how these pieces fit together.
1. Status, scope, and conformance
This is a proposed specification and integration profile for existing identity mechanisms, authored to make their relationships durable and implementable. The words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY have the meanings in RFC 2119 and RFC 8174. Normative requirements apply to an implementation claiming the relevant role in this proposal. Examples, motivation, application journeys, and observations about particular releases are informative.
An implementation may implement a certifier, wallet, application, public-revelation publisher, overlay host, or contacts client. It MUST identify its supported roles and any supported compatibility profiles. This proposal does not claim that every historical release satisfies all requirements. Section 17 identifies concrete differences between the published interfaces and pinned implementations; those differences are not silently promoted into new wire formats.
BRC-52 remains authoritative for the certificate primitive. BRC-100 remains authoritative for wallet method and transport encodings. BRC-103 and BRC-104 govern authenticated exchange and its HTTP transport. This document explains those primitives sufficiently to follow and implement the identity lifecycle, and specifies the public identity and contact conventions surrounding them. It does not replace their interfaces, introduce a new identifier grammar, or allocate a universal human-name namespace.
The public identity output specified here has no version prefix. Protocol names, field names, byte encodings, and script shapes below identify the existing format. An incompatible replacement MUST use an explicitly distinguishable format and documented migration; a registry description or a client option cannot silently change what tm_identity accepts.
2. Identity as a relationship, rather than an application account
2.1 Keys, claims, and participants
An identity key is a valid compressed secp256k1 public key, conventionally 66 lowercase hexadecimal characters. The holder controls the corresponding private key through a wallet. The application obtains its user's current identity key with getPublicKey({ identityKey: true }). It obtains another party's identity key through an authenticated exchange, an independently checked contact, or discovery. A public key is not a legal name, email account, payment address, network endpoint, or proof that one human has only one wallet.
The same key can identify a party across independent applications. A person may also choose different keys or wallet profiles for different contexts. Applications MUST preserve the actual key and its provenance, rather than join identities merely because they share a display name, photograph, email string, or device. Account recovery that preserves the private key preserves this cryptographic identity. Moving to a different key requires an explicit continuity process, new certificates where appropriate, and deliberate contact updates; an equal name is not a rotation proof.
| Participant | Function | Basis of authority |
|---|---|---|
| Subject | The key about which a certificate makes claims | The certificate names the key; a live protocol separately establishes its holder's control |
| Certifier | Checks evidence and signs attributes bound to a subject | The verifier elects to rely on that certifier for an applicable assertion |
| Verifier or relying party | Receives, checks, and uses an assertion | Its own policy and the user's trust choices |
| Wallet | Holds keys and certificates, mediates operations, resolves identities | Delegation from its user, with application permissions |
| Application | Uses identity in a particular interaction | User authorization and the application's disclosed acceptance rules |
| Overlay host | Validates, indexes, and serves public revelations | Its authenticated data and stated collection/availability policy; it does not certify the attributes |
| Registry publisher | Describes protocol, basket, and certificate-type identifiers | Its attributed descriptive statement under BRC-184 |
| Contact author | Saves a personal association between a key and attributes | The saving user's own assertion, authoritative in that user's context |
One entity can perform several roles, but the authorities remain separate. Operating an overlay does not make its host a trusted certifier. Publishing certificate-type metadata does not make the publisher an acceptable issuer. A certificate's subject need not use the certifier's wallet, storage provider, payment processor, or applications.
2.2 Why this belongs beneath applications
Suppose Alice already uses one wallet for a marketplace, a messaging application, and a professional directory. A certifier can attest that Alice's identity key controls an email address. Alice can publish that attribute once. Bob's wallet can discover the assertion through available overlay hosts, recognize its issuer under Bob's trust choices, and return the identity to any authorized application Bob uses. Each application can display Alice, authenticate a session with her, request further evidence, or construct an appropriate payment without importing the certifier's account system.
The certificate provides a reusable claim. Publication provides discoverability. The wallet supplies user-selected interpretation. The application supplies the purpose of the interaction. Separating these functions makes identity useful beyond login: transaction histories can show familiar counterparties; encrypted documents can be addressed to known keys; messages can be attributed without a social platform owning the relationship; and private qualifications can be requested only when needed.
Ty Everett's Computing with Integrity (2020) described wallet-mediated certificate requests and the distinction between revealing a real-world name and proving a useful certified fact without that name. Its identity-verification discussion is conceptual background, not the wire definition for current certificates. BRC-51 supplies useful payment, public-identity, and referral experiences; BRC-89 describes the broader integration of identity, wallets, overlays, and peer communication. This proposal uses the current BRC-52/100/103 mechanisms rather than the earlier Authrite-era certificate formats.
2.3 Five questions that must remain distinct
- Who controls this key now? Establish this through a fresh authenticated exchange or other applicable proof of control.
- What did an issuer assert about that key? Verify the complete certificate signature and the relevant revealed fields.
- Why do I rely on that issuer or association? Apply the user's selected trust anchors or an explicitly saved personal contact.
- Is the assertion suitable and current for this purpose? Check its meaning, scope, expiry where defined, revocation, and relevant changes in the underlying attribute.
- May this operation happen? Obtain the applicable permission or satisfy the application's acceptance policy.
A successful answer to one question MUST NOT be presented as a successful answer to all five. A payment recipient's public identity key is enough to derive an interoperable destination with the appropriate payment protocol; it does not itself authorize spending or establish that the intended human controls that destination.
3. Certificates and their cryptographic meaning
3.1 Core object and identifiers
A certificate binds one subject key to a map of encrypted attribute values under one certifier's signature. Its signed core consists of the following data; the signature is the signature over the other members, not an input to itself.
| Member | Representation and meaning |
|---|---|
type | Canonical Base64 encoding of exactly 32 bytes identifying a field schema and meaning |
serialNumber | Canonical Base64 encoding of exactly 32 bytes identifying this certificate within its issuer's use |
subject | Compressed secp256k1 public key in hexadecimal |
certifier | Compressed secp256k1 public key of the signing issuer |
revocationOutpoint | Transaction ID, full stop, and zero-based output index, such as txid.1 |
fields | Map from case-sensitive field names to Base64-encoded encrypted values |
signature | DER-encoded ECDSA signature represented as hexadecimal |
A type is not an issuer key. Multiple issuers may issue the same type with the same field meanings, and the verifier still decides which issuers to rely on. A serial alone is not a global identity or globally unique lookup key: retain at least the issuer, type, and serial when selecting a particular certificate. Preserve the subject and signed bytes as well when checking the actual assertion. Reusing the same issuer/type/serial for incompatible certificates is an issuer error and MUST NOT become a last-response-wins update mechanism.
Field names are 1–50 UTF-8 bytes under BRC-52. Producers SHOULD use simple printable ASCII names with documented ordering and exact case. userName and username are different fields. Field values are strings at the plaintext layer; a date, number, boolean, or structured assertion requires a schema defining its string representation. The core has no universal issuance time, expiry, assurance level, jurisdiction, or legal-person status. If a type needs those facts it MUST define and certify them, or clearly state the external policy on which they depend.
3.2 Canonical binary and signature
The signature preimage is the BRC-52 binary core without its signature. JSON serialization is not the certificate preimage.
| Order | Bytes |
|---|---|
| 1 | Base64-decoded type, 32 bytes |
| 2 | Base64-decoded serialNumber, 32 bytes |
| 3 | Hex-decoded subject, 33 bytes |
| 4 | Hex-decoded certifier, 33 bytes |
| 5 | Hex-decoded revocation transaction ID, 32 bytes in its displayed hexadecimal order |
| 6 | Revocation output index as a Bitcoin VarInt |
| 7 | Field count as a Bitcoin VarInt |
| 8 | Each field in BRC-52 name order: VarInt UTF-8 name length, name bytes, VarInt UTF-8 value length, value bytes |
| 9 | DER signature bytes only when serializing the signed certificate |
The field value bytes in this preimage are the UTF-8 bytes of the Base64 string, not the decoded encryption envelope. The transaction-ID bytes here are not reversed as they would be in a Bitcoin transaction input. VarInt means Bitcoin's compact-size encoding: one byte below 253, otherwise fd plus a two-byte little-endian value, fe plus four bytes, or ff plus eight bytes. Lengths count bytes, not Unicode characters.
BRC-52 specifies lexicographic ordering. The current SDK uses the host's localeCompare ordering; mixed-case, punctuation-rich, or non-ASCII field sets can therefore expose an ordering difference. A schema MUST make ordering unambiguous for its implementations, and implementations MUST preserve and verify the signed interpretation. They MUST NOT normalize field spelling or silently try a different certificate meaning after verification fails. The vectors use email followed by name, for which the relevant orderings agree. Section 17 records this compatibility boundary rather than defining a new signature format.
The certifier signs the preimage through BRC-100 with protocol [2, "certificate signature"], key ID type + " " + serialNumber, and publicly verifiable counterparty semantics ("anyone"). Both identifiers use their original canonical Base64 strings. BRC-100 hashes data with SHA-256 before ECDSA signing; do not separately hash and then accidentally ask it to hash the digest again. Verification uses the same protocol and key ID, the issuer as counterparty, and the publicly known anyone root. Equivalently, derive the issuer's BRC-42 public child with private scalar 1 as the other party and invoice 2-certificate signature-<type> <serialNumber>.
The final DER signature has no length prefix inside CertificateBinary. An enclosing format that appends a keyring MUST first length-prefix the complete signed certificate. Keyrings, decrypted caches, registry metadata, and trust scores MUST NOT be added to the core signature preimage. There is no current validationKey member.
3.3 Field encryption and keyrings
For each field independently, generate a random 32-byte revelation key K_f. Encode the plaintext string as UTF-8 and encrypt it with AES-256-GCM, a fresh random 32-byte IV, a 16-byte authentication tag, and no additional authenticated data. The encoded field is:
Base64(IV[32] || ciphertext || authenticationTag[16])
This is the SDK/BRC-2 envelope. There is no padding or extra header. Replacing the IV with a commonly used 12-byte GCM IV is a format change. Authentication failure MUST reject that field; it MUST NOT yield partial plaintext. Fresh IVs are required for every encryption, including keyring re-encryption. Fixed IVs in Section 16 are test inputs only.
A master keyring holds an encrypted K_f for every field. A verifier keyring holds encrypted revelation keys only for the selected fields. Their BRC-100 derivation parameters are:
| Operation | Protocol | Key ID | Encrypting and decrypting parties |
|---|---|---|---|
| Master keyring | [2, "certificate field encryption"] | Exact field name | Subject and issuer, or an explicitly supported keyring revealer |
| Verifier keyring | [2, "certificate field encryption"] | serialNumber + " " + fieldName | Subject and selected verifier |
The plaintext of each keyring encryption is the raw 32-byte K_f; the keyring value is the Base64-encoded BRC-2 envelope. The encrypting party supplies the other party as counterparty; the receiving party uses the sender as counterparty. BRC-42 derives matching symmetric keys through child-key ECDH, as used by BRC-100 encryption. These keys are neither a hash of the field name nor the subject's root private key.
A master certificate carries masterKeyring, also named keyringForSubject or keyring in particular storage/API contexts. A transmitted verifiable certificate carries keyring. A proveCertificate response calls the same verifier-specific map keyringForVerifier. An adapter MUST translate these names according to context without changing their cryptographic meaning. A master keyring MUST contain exactly the necessary nonempty entries for all signed fields; a verifier keyring MUST be a subset of those fields.
For binary extensions, prefix the complete signed CertificateBinary with its VarInt length, then append a keyring map: VarInt entry count, followed by each entry's VarInt name length, UTF-8 name, VarInt value length, and Base64-decoded keyring ciphertext. This distinction from the signed fields' Base64 text encoding is intentional. The enclosing protocol identifies whether the map is a master or verifier keyring.
3.4 What selective disclosure does and does not hide
The verifier receives the entire signed encrypted field map so it can verify the unchanged issuer signature. It receives revelation keys for only the authorized subset. Other field values remain encrypted, but their names, ciphertext lengths, certificate type, issuer, subject, serial, and revocation reference are visible. Reusing a certificate or identity key across interactions can link them.
Selective disclosure reveals selected certified values; it is not automatically a zero-knowledge predicate proof. To reveal “over 18” without a birth date using this mechanism, a certifier can issue an appropriately scoped and time-qualified over18 field and the subject reveals that field. Decrypting a birth-date field and hiding it in the UI does not conceal it from the application that received it.
Once a verifier has plaintext or a revelation key, it can retain or disclose that information. Removing a wallet permission, withdrawing a public token, or revoking a certificate cannot make the recipient forget previously learned bytes. These operations change future authorization or reliance, not historical knowledge.
4. Certificate types, certifiers, and issuance
4.1 Define the assertion before implementing its form
A certificate type definition MUST specify its exact 32-byte identifier, case-sensitive fields, plaintext encodings, what each field asserts, who can issue it, and any validity or revocation policy required for relying on it. “Who can issue” describes acceptable evidence and issuer policy, not an exclusive cryptographic namespace allocation. A type SHOULD explain normalization, renewal, reassignment, and how a verifier can distinguish stronger and weaker evidence.
For an email-control certificate, the claim may be that the issuer verified access to a mailbox at issuance. It is not automatically a claim about legal identity, continued exclusive control, or ability to receive a blockchain payment. For an employment certificate, an employer should define the role, scope, and period. For a qualification, a professional body should define what the qualification permits and how it changes. An image field attests only the meaning the issuer actually checked; a supplied profile image is not inherently proof that a photograph depicts the key holder.
Type definitions SHOULD be documented through the BRC process and submitted to CertMap under BRC-184. CertMap descriptors supply friendly names, descriptions, image references, and field presentation hints; they do not change the signed schema or appoint trusted issuers. Section 15 contains the registrations accompanying this proposal.
4.2 Certifier responsibilities
A certifier MUST authenticate the subject or otherwise establish the binding required by its issuance policy, validate every assertion it will sign, and bind the certificate to the intended subject key. Signing arbitrary encrypted values without validating the corresponding claim is not attribute verification. In an encrypted issuance flow, the issuer needs revelation keys for the fields it must check.
The issuer MUST protect its signing and revocation authority, keep sufficient issuance and revocation records for its policy, and distinguish issuance success from a pending request or failed transaction. It SHOULD publish its schema, verification methods, contact route, renewal and correction procedures, and revocation limitations. It SHOULD minimize retained verification evidence and avoid placing private evidence on-chain merely to issue a certificate. A certifier may charge for its work, but its business relationship need not remain in the path of every subsequent verification.
Issuer key rotation is a trust change. A new key MUST NOT silently inherit a user's trust because it serves the same domain or displays the same logo. An authenticated transition can help the user decide; it does not erase the need to assess compromised old keys, old certificates, and the new issuer's authority.
4.3 Direct acquisition
With acquireCertificate({ acquisitionProtocol: "direct", ... }), the subject's wallet receives type, certifier, serialNumber, revocationOutpoint, signature, encrypted fields, keyringForSubject, and keyringRevealer. The latter is "certifier" or the explicit revealer key supported by the implementation. The wallet determines its own subject key; the caller cannot acquire a certificate for an unrelated subject by substituting that field.
Before storage, the wallet MUST verify the core signature and subject binding, require a complete master keyring, and authenticate/decrypt every supplied field through the correct revealer relationship. Storage MUST be associated with the correct wallet identity/profile and keep encrypted values and keyring roles intact. A failed acquisition MUST NOT be reported as a stored certificate. Acquisition does not publish attributes or grant applications future disclosure permission.
The successful API response is the core certificate. The stored master keyring is not automatically returned to ordinary callers. Some current direct-acquisition and proof implementations assume the issuer is the revealer even where the interface permits another key; implementers MUST check that distinction rather than claim universal support for arbitrary revealers.
4.4 Interactive issuance acquisition
The deployed acquisitionProtocol: "issuance" flow performs an authenticated POST to signCertificate relative to the requested certifier base URL. The subject passes plaintext fields, type, certifier, and certifierUrl to its own wallet; the wallet encrypts those fields before sending the issuance request. Over the authenticated connection the request body is:
{ clientNonce, type, fields: encryptedFields, masterKeyring }
The wallet creates independent field revelation keys and a complete master keyring for the issuer. The issuer authenticates the requesting subject, checks the challenge, decrypts and verifies the claims, creates its server challenge and serial, selects the revocation reference, and signs a core certificate. Its successful response is:
{ certificate: signedCoreCertificate, serverNonce }
The client MUST authenticate the server as the requested certifier, including checking the authenticated response identity, not merely trust the URL. It MUST check the server challenge, serial derivation, exact returned type, subject, issuer, encrypted field names and bytes, acceptable revocation reference, signature, and master-keyring decryptability before storage. The returned encrypted fields MUST be exactly those submitted; unrequested additions or changes require a new, explicitly understood issuance operation. An HTTP success code alone is not an acquired certificate.
The wallet's permission to acquire, the issuer's decision to certify, and the user's permission to reveal are three separate decisions. The issuer's verification ceremony—an email challenge, an in-person check, or an external account authorization—can occur before this exchange. BRC-100 does not require one universal ceremony or a specific SocialCert endpoint for that work.
4.5 Challenge and serial derivation used by issuance
The SDK challenge used here is a canonical Base64 encoding of 48 bytes:
random[16] || HMAC-SHA256(derivedKey, random[16])
Derive the HMAC key using [2, "server hmac"], key ID equal to the SDK's UTF-8 decoding of the 16 random bytes, and the other issuance party as counterparty. The deployed decoder uses the WHATWG UTF-8 decoding behavior of TextDecoder: malformed sequences become U+FFFD and an initial UTF-8 BOM is removed. It is not hexadecimal or Base64 encoding of those bytes. The resulting string is encoded as UTF-8 in the derivation invoice. Verification uses the same raw 16 bytes and decoding rule. A verifier MUST require canonical Base64, the exact 48-byte length, and a successful HMAC verification result. These challenges are authenticated values, not inherently single-use or expiring credentials. The surrounding authenticated protocol and issuer transaction policy provide freshness, request binding, and retry handling.
Let C and S be the client and server challenge Base64 strings, respectively. The issuer computes:
| Serial derivation parameter | Value |
|---|---|
| Protocol | [2, "certificate issuance"] |
| Key ID | S + C, string concatenation with no separator |
| Counterparty | Subject for the issuer; issuer for the subject |
| HMAC data | Base64-decode C + S |
| Serial | Base64 of the resulting 32-byte HMAC-SHA256 |
Each challenge encodes 48 bytes without Base64 padding, so decoding C + S produces the two 48-byte challenge bodies in client-then-server order. The key ID deliberately uses the opposite string order. Do not use the Base64 text itself as HMAC data or insert a space. Directly issued certificates may use an independently generated canonical 32-byte serial instead; the interactive serial rule is not a requirement for all BRC-52 certificates.
Retries MUST NOT fabricate success or issue a materially different assertion under an existing serial. A production issuer should associate the authenticated request with its issuance record and make an interrupted acquisition recoverable under its documented policy. No universal issuance idempotency API is introduced here.
5. Private disclosure and peer exchange
5.1 Selecting and proving a certificate
listCertificates lists certificates held by the calling user's wallet, filtered by issuer and type and subject to applicable permissions. It is not a search of public certificates belonging to other users. Its encrypted core fields are not a disclosure of their plaintext. proveCertificate locates a particular stored certificate and returns a verifier-specific keyring for fieldsToReveal and verifier.
A conforming wallet MUST find an unambiguous stored certificate matching the request, enforce the selected field subset, and bind the keyring to the requested verifier. It MUST NOT reveal additional fields, substitute a verifier, or disclose merely because the requester knows the serial. The user may authorize a continuing grant through the wallet's normal permission system; a new modal for every previously authorized use is not required.
The recipient reconstructs the BRC-52 verifiable certificate using the unchanged core and returned keyring. It MUST verify the signature before relying on decrypted values, decrypt through the subject/verifier relationship, and reject a field whose authentication fails. Only the authenticated decrypted fields are assertions available to that recipient. A supplied decryptedFields cache is not independent evidence.
5.2 BRC-103 in an application journey
BRC-103 authenticates peer keys and carries certificate requests and responses. A request names acceptable certifier keys and maps each requested certificate type to the fields required. A response contains the signed cores and selected verifier keyrings. The certificate subject MUST match the authenticated peer whose attributes are being relied upon, unless an explicit delegation protocol authorizes a different relationship. The verifier MUST check that returned certificates and fields satisfy the actual request and its acceptance policy.
Discovery does not replace this handshake. An overlay result can identify the key Bob intends to contact; the peer at a subsequently obtained endpoint must still authenticate as that key. Conversely, a valid handshake need not include a real name or any certificate: two parties can communicate pseudonymously when the application permits it. Authentication is proof of key control, and certificate exchange supplies additional meaning where needed.
BRC-103 is transport-independent; BRC-104 binds it to HTTP. A known key does not itself create an IP route or a live connection. Peers can exchange endpoints directly, use independently authenticated service advertisements, or use a message relay such as a compatible messagebox. The chosen transport must actually deliver messages, and endpoint advertisements and server identities need their own validation. A relay transports messages; it need not become the authority that assigns the participants their identities.
The authentication protocol does not automatically encrypt arbitrary message payloads. Applications needing confidentiality MUST use the appropriate wallet encryption or encrypted messaging protocol in addition to authentication. They SHOULD request only the fields needed for the transaction and bind consequential requests, such as payment instructions or KYC disclosure, to the authenticated conversation.
6. Revocation, withdrawal, and current reliance
6.1 Certificate revocation
The certificate's signed revocationOutpoint identifies a UTXO governed by the issuer's revocation policy. Spending a non-sentinel revocation UTXO revokes the certificate under BRC-52. A conforming verifier MUST reject a certificate as current when it has authenticated evidence that this outpoint is spent. The all-zero transaction ID with index zero disables UTXO revocation; it does not mean that a revocation check succeeded.
The issuer MUST accurately describe who can spend this output and whether it is shared by multiple certificates. One shared outpoint permits group revocation. A reference to an arbitrary output, a missing transaction, or an output that was never validly created does not establish a usable revocation mechanism merely because its text is signed. The verifier may rely on the issuer for the correctness of that arrangement under its policy, or independently validate the referenced output; it MUST NOT describe an unperformed check as independent verification.
Transaction inclusion and script validation do not prove that an output remains unspent. Current revocation assessment requires a maintained spend index, an appropriate service, or the verifier's own tracking, with an explicit freshness and availability policy. The verifier MUST distinguish revoked, not observed revoked under the stated current check, revocation disabled, and status unavailable. Expiry and the continuing validity of external attributes remain separate even when the revocation output is unspent.
An application making a consequential decision MUST specify the status evidence and freshness it requires. If that evidence is unavailable, it MUST not turn the uncertainty into a claim of current certification. It may still permit an interaction on another basis, such as a personally verified contact or an explicitly accepted uncertified key. Historical messages need not disappear merely because a certificate later expires or is revoked.
6.2 Four different operations
| Operation | Controlled by | Effect | Does not do |
|---|---|---|---|
| Revoke a certificate | Whoever controls its revocation authority | Changes whether the issuer's assertion may be relied upon as current | Erase the certificate or previously disclosed plaintext |
| Withdraw a public revelation | Subject controlling the revelation output | Removes that revelation from participating current discovery indexes, with Section 8's withdrawal tracking | Revoke the underlying certificate or erase chain history |
relinquishCertificate | Subject's wallet under its permissions | Removes a locally held certificate from ordinary wallet use | Spend the issuer's revocation output or necessarily withdraw public copies |
| Remove a contact or trust anchor | The user controlling that local policy | Changes that user's future interpretation | Change another user's trust, revoke an issuer's certificate, or reassign the other party's key |
Applications and wallets MUST label these operations according to their actual effect. A UI may offer a combined workflow, but it must track each result separately. Losing a local certificate before preserving the ability to withdraw its public revelation can complicate cleanup. A transaction submission failure must remain distinguishable from successful withdrawal.
7. Public attribute revelation
7.1 Making selected fields public
Public discovery is an explicit publication choice. The subject takes a valid held certificate, selects at least one field, and obtains a verifier keyring for the public key of private scalar 1:
0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
This is the SDK's "anyone" participant. Anyone can construct its wallet and decrypt the selected revelation keys. Public keyring encryption is a conventional interoperable envelope, not confidentiality against the public. The subject MUST be told that publication makes those selected attributes publicly readable and linkable, rather than merely visible to the publishing application.
The published JSON contains exactly eight members: type, serialNumber, subject, certifier, revocationOutpoint, fields, signature, and keyring. fields remains the complete encrypted signed map; keyring is the nonempty publicly revealed subset. Do not include masterKeyring, local trust metadata, unselected field keys, private proof keyrings, or cached plaintext. No unsigned display label can replace a signed field.
The producer MUST verify the certificate, require the requested subset to exist, and check that the wallet returns exactly that subset before constructing the publication. The standard SDK publisher requests a one-satoshi output and disables output randomization so its new token is normally output zero. Readers and hosts MUST use the actual returned output index: zero is a producer convention, not a topic-wide requirement.
7.2 Subject-signed identity output
Let J be the exact UTF-8 bytes of the public JSON object. Derive the subject's locking/signing child using [1, "identity"], key ID "1", counterparty "anyone", and the subject's own child (forSelf: true). Sign J using that child, through the normal SHA-256/ECDSA data-signature operation. Construct the canonical signed PushDrop output:
PUSH33(subjectDerivedPublicKey) OP_CHECKSIG
PUSH(J) PUSH(DER_subjectFieldSignature) OP_2DROP
There are exactly two pushed data fields after OP_CHECKSIG. Push lengths use the direct length opcode through 75 bytes, OP_PUSHDATA1 for 76–255, OP_PUSHDATA2 for 256–65535, and OP_PUSHDATA4 above that, with the Bitcoin little-endian length operands. No extra prefix, trailing field, alternate drop sequence, or appended signature field is part of this envelope.
The subject signature authenticates the exact JSON bytes, including the keyring. It is distinct from the issuer's signature, which authenticates the canonical encrypted certificate core. JSON property ordering and insignificant whitespace can vary between publications, but changing them requires a new subject field signature. Readers MUST verify the original bytes rather than reserialize before checking that signature.
An anyone-root verifier derives the expected subject public child with protocol [1, "identity"], key ID "1", and counterparty equal to the certificate subject. It MUST check both equality to the script's locking key and the subject field signature, then independently verify the issuer signature and decrypt the public keyring. Possession of a signed certificate alone does not authorize publication as its subject.
7.3 Publication and spend lifecycle
The subject creates and signs the transaction through BRC-100 and submits its transaction evidence to tm_identity through the BRC-22/[object Object] publication mechanisms. Blockchain transaction validity, overlay acceptance, and successful lookup are separate observations. The publisher SHOULD preserve the transaction, outpoint, selected fields, and publication outcome so interrupted operations can be reconciled without accidentally creating unnecessary duplicate revelations.
The locking key remains under the subject's control even though its public derivation uses "anyone". To withdraw, authenticate the source output, construct a transaction spending that exact outpoint, sign its actual input position with the identity derivation, and submit the spend to the relevant overlay hosts. Standard PushDrop spending uses a transaction signature, distinct from the stored JSON field signature. Additional funding inputs and change outputs are permitted. A client MUST verify the intended source, destination outputs, and returned transaction before treating a wallet-created action as its authorized withdrawal.
The SDK withdrawal helper searches by certificate serial, then checks the subject, expected locking key, certificate signature, and field signature before selecting outputs to spend. Because serial queries can return other issuers' or subjects' records, matching a serial alone MUST NOT authorize a spend. Multiple independently published subsets may need separate withdrawal. A later new revelation can disclose a different subset or use fresh keyring envelopes; it does not retroactively erase an earlier disclosure.
8. The tm_identity topic
8.1 Admission
An overlay engine first applies its normal transaction-evidence, consensus, and spend-validation requirements. The identity Topic Manager then examines each output independently. One malformed output MUST NOT prevent acceptance of other valid identity outputs in the same transaction.
A conforming current-format validator MUST:
- Parse the exact canonical script in Section 7.2, with exactly two data fields and a valid compressed locking public key.
- Bound the JSON field to 1–262144 bytes and the field-signature encoding to 8–80 bytes, then require a valid DER signature. The size bound alone does not establish signature validity.
- Decode strict UTF-8 and a JSON object with exactly the eight specified top-level members. Require
fieldsandkeyringto be data maps, each with 1–100 entries, and require every keyring name to exist infields. Validate BRC-52 types, encodings, field names, keys, and signature structure. Producers MUST NOT emit duplicate JSON member names; readers SHOULD reject duplicate members rather than depend on parser overwrite behavior. - Derive the expected subject locking key and verify the subject signature over the original JSON bytes.
- Verify the complete certificate signature under the claimed issuer.
- Decrypt every public keyring entry through the anyone wallet and authenticate its corresponding field ciphertext. Require at least one successfully disclosed attribute, and reject the candidate if a supplied revelation fails authentication.
The standard producer uses one satoshi. The pinned topic predicate does not impose a separate satoshi amount or output-index restriction. Ordinary transaction rules still apply. Hosts MUST NOT treat an arbitrary client-selected protocol/key ID as the tm_identity format merely because it also produces a valid PushDrop script.
Admission does not consult a universal trusted-issuer list, reserve human-readable attributes, or require CertMap inclusion. Different certificates may disclose the same name, handle, or email value. The same subject may have several issuers, types, and public revelations. The topic validates attributable statements; it does not assign exclusive ownership of an attribute to the first claimant. A verifier's trust choices and application context resolve meaning later.
The pinned admission validator checks signatures and public decryptability. It does not establish current certificate revocation status, issuer truthfulness, or that an application should accept the assertion. An implementation claiming current-reliance validation must add Section 6's status checks. Merely constructing a Certificate and calling verify() is a signature check, not that complete decision.
8.2 Spends, retained history, and withdrawal identity
The Topic Manager returns the admissible output indexes and an empty coinsToRetain list. Thus a spent identity output is not retained as a current topic coin simply because a successor exists. A transaction that spends an identity token and creates no new admissible identity output is still a meaningful spend notification; zero new admissions does not cancel withdrawal.
Current lookup storage also remembers withdrawn revelations, separately from output indexing. A revelation is identified by this tuple:
(type, serialNumber, subject, certifier, revocationOutpoint,
certificate signature, public keyring entries)
Keyring equality means the same field names and exact ciphertext strings, independently of object insertion order. These values, rather than a friendly name or serial alone, identify the same signed disclosure. A different field subset or freshly encrypted keyring is a different revelation. The issuer signature commits the encrypted fields; storage MUST derive the tuple from the authenticated certificate, not accept an unauthenticated caller's withdrawal claim.
In the pinned store, the local revelationId is lowercase hex SHA-256 of UTF-8 compact JSON containing the seven tuple elements in the displayed order, with the last element represented as sorted [fieldName, keyringValue] pairs. The implementation sorts names with localeCompare. This hash is an internal index key, not a new on-chain field or cross-host consensus identifier. Implementations with different internal encodings MUST preserve the tuple's equality semantics. When reproducing the pinned hash, preserve its ordering and JSON rules; Section 16 uses a single keyring field, avoiding locale-dependent ordering.
When an authenticated spend of a revelation output is observed, the lookup service MUST record the withdrawal and suppress current discovery of that same revelation, including equivalent stored copies. The service validates that the spend notification contains exactly one input spending the indicated outpoint, has the authenticated source output available, and that the source is a valid identity revelation. The overlay engine remains responsible for proving the transaction and spend are valid; matching an input's textual outpoint alone is not proof of a valid spend.
The index lifecycle is:
| Event | Required effect in the current withdrawal profile |
|---|---|
| Admit an output with no matching withdrawal | Upsert by transaction ID and output index; index only authenticated public attributes |
| Re-admit the same output | Idempotent update, not another counted record |
| Admit an already withdrawn revelation | Do not restore it to current lookup |
| Observe an authenticated spend | Persist the revelation withdrawal and remove/hide matching indexed revelations |
| Spend races with admission | The resulting index must suppress the withdrawn revelation |
| Process stops between recording withdrawal and deleting rows | Lookup must still exclude rows joined to the withdrawal record |
| Evict an output for a non-spend reason | Remove that outpoint's row; eviction alone is not a certificate revocation or an authenticated revelation withdrawal |
The reference store checks for withdrawal before and after its admission upsert. It uses a persistent withdrawal collection, backfills older matching rows with the revelation identifier, and excludes withdrawn identifiers in lookup before pagination. Equivalent implementations need not use MongoDB but MUST preserve these effects, including across restarts. Legacy services that only delete the spent outpoint do not provide this withdrawal profile.
Withdrawal tracking prevents a participating current index from treating the same previously withdrawn disclosure as newly current. It is not data erasure, cannot force unrelated hosts to retain withdrawal evidence, and does not prevent the subject from deliberately publishing a new revelation. Chain reorganizations and rejected/unconfirmed spends require the host's documented transaction-state reconciliation. The pinned withdrawal store has no independent reorganization rollback API; a host MUST NOT claim automatic reversal of an incorrectly finalized withdrawal merely because it reprocesses an admission.
8.3 Replication and availability
The topic identifies a common public format, not one required server. Hosts can exchange available transactions through the overlay synchronization mechanisms, including BRC-76 GASP where supported. The format does not introduce a global ordering authority or require all hosts to have observed every publication and spend simultaneously.
Under BRC-183, hosts seeking broadly shared public coverage may operate a fairly strict deployment: most nodes should have most records most of the time. A host intentionally serving a selected collection must disclose that federated collection policy. In either case it MUST apply the advertised validation and withdrawal profile to the records it claims to serve. A result's absence from one host is not proof that the subject has no identity, no certificate, or no public revelation elsewhere.
Replicating admission data alone does not establish complete withdrawal knowledge. Hosts implementing the persistent withdrawal profile MUST preserve authenticated spend/source evidence and arrange its propagation or reconstruction; this proposal does not invent a separate tombstone wire message. Clients SHOULD have configurable provider discovery and avoid requiring a single certifier-owned host as the only source of that certifier's public assertions.
9. The ls_identity lookup service
9.1 Question and response
Use a BRC-24 question with service: "ls_identity" and an object-valued query. The current bounded query schema is:
| Query member | Form and bounds |
|---|---|
identityKey | A valid 33-byte compressed public key expressed as 66 hex characters |
attributes | An object with 1–32 named string values; names 1–50 UTF-8 bytes, values at most 500 UTF-8 bytes |
certifiers | 1–32 distinct valid compressed public-key strings |
certificateTypes | 1–32 distinct canonical Base64 strings, each decoding to 32 bytes |
serialNumber | Canonical Base64 encoding of 32 bytes |
limit | Integer 1–100; default 10 |
offset | Integer 0–100000; default 0 |
Unknown top-level members, malformed supplied members, invalid arrays, and unsafe field selectors MUST be rejected. Attribute field selectors MUST be ordinary field names, not database operators or paths: reject dots, dollar-sign syntax, NUL, and unsafe object-property names. Producers should use the certificate schema's exact field spelling. The special query key any is reserved for the search described below; it is not a demand that a certificate contain a signed field called any.
The pinned validator accepts either case in public-key hex, while several storage comparisons are textual. Clients SHOULD send canonical lowercase keys and MUST NOT infer that an uppercase query is guaranteed identical behavior on every legacy host. An omitted optional filter is distinct from an empty array: the current schema rejects empty certifiers and certificateTypes arrays. A wallet with no selected certifiers should complete its empty-trust decision locally rather than send a malformed or unintentionally unfiltered query.
The lookup service returns an overlay lookup formula selecting transaction/output references. The overlay engine resolves this to the ordinary BRC-24 output-list answer containing each output's transaction evidence (beef) and outputIndex. The public contract is not a MongoDB record, pre-decrypted identity, or a host's trust score. An application using raw lookup MUST validate the returned evidence and certificate before relying on it.
For example, the following selects public certificates for the synthetic subject used in Section 16:
{
"service": "ls_identity",
"query": {
"identityKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"limit": 10,
"offset": 0
}
}
9.2 Selector precedence
After validating all supplied members, the current lookup dispatcher applies the first applicable row:
| Priority | Condition | Effective selection |
|---|---|---|
| 1 | serialNumber supplied | Certificates with that serial; other selection filters are not applied |
| 2 | attributes supplied | Attribute search, optionally restricted to certifiers |
| 3 | identityKey and certificateTypes supplied | That subject and one of those types, optionally restricted to certifiers |
| 4 | identityKey supplied | That subject, optionally restricted to certifiers |
| 5 | certifiers supplied | Certificates from one of those issuers |
| Otherwise | No supported selector | Error |
certificateTypes alone is not a supported query. Combining selectors does not imply an intersection of all of them. In particular, callers MUST NOT rely on a certifier filter accompanying a serial query being applied. Validate the returned subject, issuer, type, and intended serial at the client boundary. Clients SHOULD send only the members belonging to the intended branch.
Stored public attributes are decrypted, authenticated values from the supplied keyring, never all encrypted fields decoded as if they were plaintext. The index's internal substitution of decrypted values for its local certificate.fields is a database representation only; returning the source transaction restores the original signed certificate with encrypted fields.
9.3 Attribute matching and deployed compatibility profiles
Named attribute searches normalize query whitespace by trimming and collapsing runs of whitespace to one space. Empty normalized named values are ignored; if none remain, no records match. Multiple effective named attributes are ANDed within the same certificate. They are not a join of an email in one certificate and an employer name in another certificate for the same subject.
For ordinary named fields, the deployed fuzzy matcher escapes regular-expression metacharacters, splits the normalized query into space-separated tokens, and looks for those literal tokens in order, case-insensitively, with arbitrary intervening characters on the same line. This is ordered substring matching, not edit distance or a guarantee of exact equality. A query for alice may therefore match a longer value containing that string.
The any search operates over the publicly decrypted field values joined with spaces in their stored enumeration order, excluding the exact names profilePhoto and icon. It takes precedence over other members inside attributes. After query whitespace normalization, fewer than two UTF-16 code units returns no matches. Excluding those two conventional image fields does not make all other values safe to display or automatically exclude every possible URL field.
Two deployed profiles require explicit distinction:
| Behavior | Current TS Stack storage profile | Corrected standalone identity-services profile |
|---|---|---|
Named userName | Exact, case-sensitive equality to the whitespace-normalized query | Anchored, escaped, case-insensitive equality to the normalized query |
| Other named fields | Ordered literal substring matching | Same |
any, normalized length 2 | Ordered literal substring matching | Same |
any, normalized length greater than 2 | MongoDB default English full-text search | Ordered literal substring matching |
The full-text branch uses tokenization and stemming, with default case/diacritic-insensitive text matching, ignored stopwords, quoted phrases, and negation. It is not an email-address equality test. The exact MongoDB behavior is part of this implementation profile, not an alternative certificate interpretation. See the MongoDB $text definition and the pinned sources in Section 17.
The pinned wallet's result binding conservatively implements complete English tokens, phrases, stopwords, and exclusions for the full-text branch, but not all server-side stemming or custom index languages. A stem-only result can be discarded. That wallet does not automatically adopt a standalone host's substring profile. A producer or consumer MUST declare which profile it implements and MUST NOT present fuzzy or full-text search as an exact identity binding. No query-field negotiation between these profiles currently exists. A future standardized search-mode extension requires explicit coordination rather than adding undocumented members to ls_identity.
For a payment destination or other exact-attribute decision, use search to discover candidates, then compare the authenticated value under the certificate type's explicit normalization rules and let the user select the intended subject. Email domains and mailbox local parts, international telephone numbers, and platform handles have different normalization policies; a universal lowercase-and-strip-punctuation rule MUST NOT be invented by a resolver.
9.4 Pagination, duplicates, and freshness
The pinned service excludes withdrawn revelations before applying offset and limit. It does not specify a stable sort, a relevance order, a first-claim order, or a snapshot cursor. Therefore, the first row has no special identity authority, and offset pages can shift as data or query plans change. limit bounds returned outputs, not the number of unique people.
Multiple outputs may carry the same certificate or different public subsets of it. Clients SHOULD deduplicate authenticated outpoints and retain enough certificate/revelation provenance to interpret repeated records. A host may be missing newer publications or withdrawals. An output-list is evidence to validate, not a proof of global completeness or current unspentness. Timeouts, invalid responses, resource-limit failures, and an empty successful answer MUST remain distinguishable in the caller's operational state, even where a legacy UI ultimately displays no matches.
10. BRC-100 discovery as an application capability
10.1 The two directions
discoverByIdentityKey answers: What publicly revealed, locally accepted attributes are associated with this key? An application already has a key from a payment, authenticated message, document author, or saved relationship and wants intelligible identity information.
discoverByAttributes answers: Which subjects have publicly revealed certificates matching these attributes under my trust choices? An application starts with a familiar attribute and needs candidate identity keys. This is what enables a recipient picker based on an existing email, phone number, or social handle without creating another application username.
Both calls concern discovery of public assertions about others, rather than disclosing the caller's private certificates. Public queries can still reveal the caller's interests to providers and can disclose a user's locally saved contacts if contacts participate. The wallet's normal permission model therefore remains relevant.
const candidates = await wallet.discoverByAttributes({
attributes: { email: 'alice@example.invalid' },
limit: 10,
offset: 0,
seekPermission: true
})
const identity = await wallet.discoverByIdentityKey({
identityKey: selectedSubjectKey,
seekPermission: true
})
The first call is candidate discovery, not automatic selection of candidates.certificates[0]. The second can enrich an already selected key with other public assertions. Those assertions remain individually attributed to their issuers and subject to application relevance checks.
10.2 Arguments, results, and wire identity
The public BRC-100 argument shapes are:
| Call | Required argument | Optional arguments |
|---|---|---|
discoverByIdentityKey | identityKey | limit, offset, seekPermission |
discoverByAttributes | attributes: Record<fieldName, string> | limit, offset, seekPermission |
The wallet-level default page size is 10, with a maximum requested limit of 10000 and nonnegative offset. This is not the same bound as one overlay host's 100-output maximum. The wallet must coordinate its own acquisition, validation, deduplication, trust calculation, and pagination. If it queries more than 32 selected issuers, it must partition the issuer filter into valid host-sized requests and combine authenticated evidence before applying the intended trust policy; it must not silently discard selected anchors. A conforming implementation MUST honor the caller's limit and offset for its declared result collection, rather than merely insert them in a cache key.
Each normal certificate result contains the BRC-52 core and:
| Additional member | Meaning |
|---|---|
publiclyRevealedKeyring | The subject's authenticated public-verifier keyring |
decryptedFields | Authenticated plaintext corresponding to that keyring |
certifierInfo.name, iconUrl, description | Locally selected descriptive issuer information |
certifierInfo.trust | That user's assigned issuer weight, normally an integer 1–10 |
The outer response contains certificates and totalCertificates. The count MUST be interpreted within the implementation's stated collection and pagination semantics; it is not a count of globally existing identities or a completeness proof. The pinned trust transformer returns the length of its accepted result array. Several certificates may name one subject.
The BRC-100 binary call codes remain 21 and 22. Code 21 carries the 33-byte identity key; code 22 carries the length-prefixed attribute string map. Both carry limit, offset, and the optional permission flag using BRC-100 encodings. The response carries signed certificate data, issuer display information and trust, the public keyring, and plaintext fields. Implementers MUST use those defined encodings rather than invent a new discovery response because a UI wants a name and image.
forceRefresh is an in-process Wallet Toolbox extension, not a field added to BRC-100 binary methods by this proposal. Likewise, SDK useContacts, overrideWithContacts, and parallel options belong to the higher-level resolution helper, not the two standard wallet argument objects. They require explicit adapter support when crossing a wallet transport.
10.3 Validation pipeline
Before returning an overlay-derived identity as accepted, a conforming wallet MUST:
- Apply the user's current selected issuer policy and appropriate request permission.
- Acquire bounded transaction/output evidence from the configured providers, preserving the distinction between received data and verified data.
- Validate transaction evidence in the wallet's network and chain context, and authenticate the exact output, subject-bound script, publication signature, issuer signature, and public field decryptions.
- Rebind the verified result to the query: the requested subject for a key query, or the declared attribute matching profile for an attribute query. A valid unrelated certificate is not a valid answer.
- Remove duplicate contributions before calculating trust, apply Section 11's selected policy, and preserve source attribution.
- Apply the promised pagination and return the actual checked values. Perform the current-reliance/status checks required for any claim of current certification.
The current wallet verifies transaction evidence with an independently supplied chain tracker and treats its overlay-response cache as untrusted evidence requiring revalidation. Signature validity and chain inclusion still do not establish current revelation unspentness or certificate non-revocation. A wallet MUST NOT label those additional checks as completed unless it actually performed them under a stated policy.
Cache keys and invalidation MUST respect network, wallet/profile, query, selected trust policy, and relevant source context. Changing the user's issuers or threshold MUST affect subsequent decisions, including cached results. Rendering caches in an application are not perpetual trust grants. Late responses for an old query, profile, or trust configuration MUST NOT overwrite a more recent selection.
10.4 The wallet serves the user's trust choices
A wallet implementing this profile MUST provide a practical way for its user to add, remove, and change valid trust anchors and local identity associations. It MUST NOT require a vendor partnership, issuer registration with the wallet company, a particular certifier's certificate, or inclusion in a descriptive registry before honoring an otherwise supported user-selected anchor. Importing an anchor from a known HTTPS domain is a convenience, not a prerequisite to entering or independently authenticating its key.
The wallet MUST carry out an authorized supported discovery or disclosure operation according to those choices. It MUST NOT replace a user's selected issuer with the wallet vendor's preferred issuer, suppress a personally accepted contact merely because an overlay has no certificate for it, or make an unavailable metadata service a prerequisite to identity use. Honest errors for invalid data, unavailable evidence, unsupported formats, or actual user denial remain necessary; silently overriding the user's trust policy is not an error-handling strategy.
Applications may have their own disclosed requirements for a specific operation—for example an employer may require its own employment credential, and a verifier may require a particular qualification. These are claims about the application's transaction policy, not authority for a wallet to prohibit the user's general identity relationships. An application SHOULD state the missing assertion and acceptable evidence rather than label the entire person invalid.
seekPermission controls whether the wallet may seek a required grant; it does not create one. Callers SHOULD set it explicitly because published documentation and current SDK defaults differ. A conforming adapter MUST honor explicit false by returning the appropriate permission error if a grant is required, and explicit true by using the normal user-choice path. The pinned permission wrapper's handling is characterized in Section 17. A wallet may reuse valid prior grants; repeated prompts must not become an artificial barrier to a user-authorized capability.
11. User-selected trust and identity interpretation
11.1 Appointing a trust anchor
A trust anchor here is a certifier public key deliberately selected by the relying user, with its local description and policy. Trust is not established by a high search position, a public key's age, a registry listing, or an issuer naming itself trustworthy. The user can recognize an organization, inspect its verification policy, obtain its key through an independent channel, or import its proposed details using BRC-68.
BRC-68 publishes metanet.trust in an HTTPS /manifest.json, with name, note, icon, and publicKey. Legacy babbage.trust may be accepted for migration. Fetching that file obtains a domain-attributed proposal for an anchor; selecting it is the user's decision. It MUST NOT silently install future replacement keys. Direct key entry and personal contacts keep a domain or manifest from becoming a mandatory identity authority.
Certifier trust, registry-publisher preference, overlay-provider selection, and permission to a particular application are different relationships. Some wallet settings currently share an entity list across several of them. Implementations MUST disclose that coupling and MUST NOT infer one kind of authority solely from another. The user should be able to understand why an assertion was accepted and change the relevant relationship.
11.2 Deployed weighted policy
The Wallet Toolbox trust profile has trustLevel, a positive integer threshold, and trustedCertifiers, each with a distinct identityKey, descriptive metadata, and integer trust from 1 through 10. Current settings validation permits at most 256 issuers and thresholds from 1 through 2560. The numbers express the user's policy, not probabilities, global reputations, or universally comparable assurance levels.
For the verified, query-matching certificate set available to that lookup:
- Ignore certificates whose issuer is absent from the selected list.
- Group by subject identity key.
- Within each subject, deduplicate certificates by
(type, serialNumber, certifier). - Sum the selected weights of distinct contributing issuer keys, once per issuer for that subject.
- Keep the subject's eligible certificates if that sum is at least
trustLevel. - Attach issuer metadata from the user's settings and order the retained certificates by issuer weight descending. Equal-weight ordering is not an identity-authority rule.
Two certificates or ten copied outputs from one issuer do not supply two independent trust contributions. Separate keys operated by the same organization are not necessarily independent authorities either; selecting and weighting them is the user's responsibility. The calculation uses the evidence actually available for the query, so a limited or incomplete result can fail to accumulate sufficient weight even when further certificates exist elsewhere.
For example, Bob gives a professional association weight 4, an employer weight 3, and a social-account verifier weight 2, with threshold 5. An available association certificate plus an employer certificate for Alice contributes 7; ten association certificates alone still contribute 4. Removing the employer from Bob's selected list immediately changes that result. Carol may choose a different policy and receive a different accepted result for the same public evidence.
This threshold qualifies a subject's discovery result under that policy. It does not mean that every issuer jointly attested every field, or that their certificates agree. If one issuer says an email is Alice's and another certifies a professional qualification, the second issuer did not thereby verify the email. An application MUST retain per-certificate attribution and evaluate the particular claim needed for its task. It must not flatten a collection into an unattributed “verified person” object.
The pinned transformer processes at most 256 supplied certificate entries and retains the first encountered certificate for a repeated issuer/type/serial. Separate revelations of the same core can expose different subsets, so that behavior does not promise the union of all public fields. A client combining compatible revelations MUST authenticate each contributing publication and preserve the unchanged certificate core and the provenance of each revealed field. Conflicting signed cores under one logical certificate identifier require explicit handling, not silent merging.
11.3 Choice, uncertainty, and personal authority
An unknown identity is a key for which the current lookup and policy did not supply an accepted public description. It is not proof that the key has no legitimate holder. Users can still authenticate a known key, obtain a certificate privately, or make their own contact assertion.
A user may directly decide, “This is Alice's key; I know her as Alice from the workshop, and this is the photo I use.” That decision needs no third-party issuer's permission. In that user's context, the saved association can take precedence over external descriptions. Its local authority is positive and intentional; it is not a defective certificate awaiting vendor approval. Section 12 specifies its persistence and presentation boundaries.
When two accepted subjects share an attribute, the wallet/application MUST preserve the ambiguity rather than choose the first or highest-ranked record as the unique owner. Helpful resolution includes other certified attributes, an existing contact, a directly checked key, and a fresh authenticated conversation. The relevant question is which key the user intends to interact with, not which vendor owns a global spelling.
12. Contacts and direct personal assertions
12.1 Meaning and consent
A contact associates an identity key with a user's own name, image, and optional contextual notes. Saving it is a personal trust action, analogous to installing a local trust anchor. The user can make the association after meeting someone, checking a key over an independent channel, inspecting an authenticated exchange, or knowingly accepting information supplied by the person. A wallet MUST allow that personal decision without demanding a third-party certificate first.
The contact author can describe their own key or another party's key. A record saved by Bob saying “this key is Alice” is Bob's local assertion, not an assertion signed by Alice merely because she is the contact's subject. Alice can separately issue a self-signed BRC-52 certificate or send a signed introduction; those are distinct objects with their own signatures and reliance rules. An automatic import of a network result MUST NOT become an authoritative contact without the user's or an appropriately authorized application's deliberate acceptance.
The contact's storage authentication proves that the wallet stored those bytes. Its identity authority comes from the saving user's decision. A photo, name, or badge can be personally selected and can override an overlay's display for that user. Applications MUST preserve this local attribution when exporting or showing the result to another user, rather than inventing a third-party certification claim.
12.2 Encrypted contact record
The SDK ContactsManager stores a one-satoshi signed PushDrop output in the BRC-46 basket contacts. Its plaintext is UTF-8 JSON with these required string members and optional JSON metadata:
| Member | Meaning and current writer bounds |
|---|---|
name | User's display name for this key; nonempty, at most 500 UTF-8 bytes |
avatarURL | Image reference; may be empty, at most 2048 bytes |
abbreviatedKey | Display abbreviation; may be empty, at most 256 bytes; never used instead of the full key for cryptography |
identityKey | Canonical lowercase compressed secp256k1 public key |
badgeIconURL | Optional display image reference represented as a string, at most 2048 bytes |
badgeLabel | Local descriptive label, at most 1000 bytes |
badgeClickURL | Empty or credential-free HTTPS navigation URL, at most 2048 bytes; local-development HTTP is a compatibility exception |
metadata | Optional bounded JSON object, such as personal notes or an independently obtained provenance description |
Unknown top-level contact members are rejected by the current writer. Metadata must be JSON data, with finite numbers and no accessors or unsafe object keys; the current limits are depth 10, 2000 nodes, 200 keys per object, 1000 entries per array, and 32 KiB of encoded metadata. The complete plaintext is at most 64 KiB. These are current storage-client bounds, not a requirement to reveal personal notes to applications or put them in certificate metadata. Resource references MUST be treated as untrusted content even after contact decryption.
On creation, generate 32 random bytes and use their canonical Base64 string as the contact record's keyID. Encrypt the complete plaintext through BRC-100 using [2, "contact"], that key ID, and counterparty "self". The same tuple, key ID, and self counterparty derive the signing and locking child for:
PUSH33(ownerDerivedPublicKey) OP_CHECKSIG
PUSH(encryptedContactBytes) PUSH(DER_ciphertextSignature) OP_2DROP
The encrypted bytes use the BRC-2 AES-GCM envelope; the data signature covers the exact ciphertext envelope. Both derivations use the saving wallet's root/profile, not the contact's identity private key. A reader MUST check the expected locking key and data signature before decrypting and accepting the local record. A different layout or unauthenticated JSON in custom instructions is not a valid contact body.
The wallet output carries customInstructions containing exactly the JSON object { "keyID": "<32-byte Base64 value>" }. This key ID is wallet tracking metadata, not another field in the on-chain PushDrop payload. Backup and migration MUST preserve it, the basket association, and the owner's appropriate key context; the public chain by itself does not reveal a missing random derivation key ID.
For private lookup indexing, compute a BRC-100 HMAC-SHA256 using [2, "contact"], key ID equal to the contact's canonical identity-key hex string, counterparty "self", and data equal to the UTF-8 bytes of that same hex string. Store the tag:
identityKey <lowercase hex of the 32-byte HMAC>
The tag is not a public SHA-256 of the key and is not the record's random encryption key ID. It helps locate a candidate output; a reader MUST still decrypt/authenticate that output and check the full stored identityKey. Tags, basket names, and custom instructions are wallet metadata rather than a public identity overlay index.
12.3 Create, read, update, remove
Creation stores the encrypted output, tag, basket, and custom instructions together. Reads request locking scripts and custom instructions from contacts, verify the canonical signed envelope and expected key, authenticate the encryption, parse bounded UTF-8 JSON, and validate the contact object. Malformed records must not acquire authority merely because they are in the named basket.
An update finds the authenticated output for the key, spends it, and creates a replacement contact output with updated encrypted data. The pinned implementation reuses that record's random key ID while generating a fresh encryption IV. It refuses an ambiguous multi-output update rather than choose arbitrarily. A conforming writer MUST bind the actual input to the intended old outpoint and check that the signed transaction preserves the authorized outputs. The full identity key, not its display abbreviation or label, selects the association.
Removal spends the authenticated contact output without creating its replacement. It changes local trust/presentation, not the subject's identity, certificates, or public revelations. The current removal helper stops after one matching output; callers reconciling duplicates must not assume that this proves all historical or concurrently created records are gone. Failed spends MUST NOT be reported as successful persisted removal.
The current reader loads at most 1000 contact outputs and caches a decrypted snapshot. An empty-basket cache and concurrent-load coalescing improve ordinary application responsiveness. Save/remove operations invalidate or update that cache; an explicit force refresh reloads it. A cached result is not a promise of completeness for a larger basket or of instantaneous cross-device synchronization. Implementers supporting larger address books must paginate and reconcile deliberately.
Encrypted contact persistence can reveal that outputs were created, updated, and spent. Wallet output descriptions and other storage metadata may also contain labels. Implementers SHOULD protect that metadata and avoid treating encryption of the contact body as privacy for every associated record or access pattern.
12.4 Resolution precedence and transport boundaries
The current SDK IdentityClient has contacts disabled by default. Passing { useContacts: true }, the legacy boolean true, or overrideWithContacts: true opts into the user's personal associations. The legacy overrideWithContacts option takes precedence if both flags are supplied.
For identity-key resolution with contacts enabled, a local hit can return immediately and avoid the overlay query. With parallel: true, both sources are queried and a contact wins on a matching key. For attribute resolution, the sequential helper first matches the saved contact's name and identityKey, case-insensitively with equality; it does not treat arbitrary metadata or an any query as a contact search index. A local match can short-circuit. Otherwise it obtains overlay results and substitutes saved contact display data for matching subject keys. The parallel attribute path performs that substitution over the overlay result set rather than unioning all local contacts into the search results. These are helper behaviors, not general promises that every contact field is searchable.
Wallet Toolbox can separately accept an explicitly installed ContactSource before overlay discovery. Its in-process adapter synthesizes a result with a default contact type, empty certificate-proof fields, and a local priority that may be represented as Infinity. This expresses a local policy decision; it is not a valid BRC-52 certificate or BRC-100 binary certificate result. The result cannot be made portable by casting it to the certificate interface or serializing infinity into an unsigned byte.
A portable implementation MUST preserve the distinction. It can use ContactsManager's existing basket/encryption operations and merge local contact display records at the application/helper layer. A wallet transport wishing to carry a new explicit local-assertion result needs a separately specified extension; this proposal does not silently add one to call codes 21 and 22. Until then it MUST NOT invent issuer signatures, type IDs, or serials merely to squeeze a contact into the certificate wire format. This boundary limits one representation, not the user's ability to appoint personal trust or an application's ability to honor it.
13. Application journeys
13.1 From a familiar attribute to payment and a continuing relationship
Alice wants people who already know her email address to find her wallet identity. A SocialCert-style issuer authenticates Alice's subject key, verifies access to the mailbox under its published policy, and issues an email-control certificate. Alice acquires and retains the certificate and master keyring in her wallet. Acquisition alone does not publish her address.
Alice chooses to make the email field public. Her wallet produces an anyone-verifier keyring for that field and creates the subject-signed identity output. The overlay validates the output and indexes the decrypted email with the authenticated certificate. The issuer need not operate the only overlay, and Alice need not create a separate username at Bob's payment application.
Bob recognizes and selects that issuer's key in his wallet's trust settings. His payment application can now request:
const result = await wallet.discoverByAttributes({
attributes: { email: 'alice@example.invalid' },
limit: 10,
offset: 0,
seekPermission: true
})
This call is an illustration, not an assertion that the synthetic address exists. seekPermission is explicit because of the compatibility difference in Section 10. An application can make the corresponding call through the BRC-100 transport; it need not know which overlay host the wallet uses or build its own certifier allowlist. The result carries the subject key, signed encrypted certificate, public keyring, decrypted fields, and the wallet's attributed certifier information.
The application checks the returned field and its meaning, shows the full intended association and issuer attribution, and lets Bob resolve ambiguity. Search matching can be fuzzy; a search hit is not proof of exact mailbox equality. The application MUST compare the desired attribute using its type's documented comparison rules before presenting a result as an exact match. If several subjects qualify, it MUST NOT select a payment recipient solely because it is the first lookup result. It can ask Bob to distinguish them, use a saved contact, or obtain an independent confirmation.
Once Bob has selected Alice's identity key, the parties can authenticate directly through BRC-103 and use BRC-100 encryption or signing operations with each other as counterparties. An identity key is a cryptographic destination, not a routable socket address. Their application must obtain a usable endpoint or message-delivery route separately, such as an independently exchanged endpoint or a message-box service. Any relay or endpoint MUST be bound to the intended peer through authentication; control of a convenient server name must not silently replace Alice's key.
Suppose the payment requires additional customer information. Bob's application can request the relevant certificate type and selected fields over the authenticated session. Alice's wallet presents the requested disclosure and verifier identity to Alice and produces the verifier-specific keyring after authorization. Bob verifies the certificate, session binding, issuer policy, relevant fields, and current revocation status. Alice's public email listing has not authorized the disclosure of her address, date of birth, or other private information. A jurisdiction's requirements for accepting customer information are outside this protocol; the mechanism makes appropriately certified information exchange possible.
For payment, the parties use the appropriate payment protocol, for example BRC-29. They agree the amount and the derivation information needed by the recipient, derive the destination using the selected identity keys and BRC-29 parameters, create the transaction, and deliver its BEEF and payment metadata so the recipient can internalizeAction. Discovery is not a complete payment-delivery protocol. The application MUST bind the displayed recipient, selected identity key, payment derivation, and transaction approval to the same intended party.
Finally, Bob saves Alice as a contact after confirming the association. He may use a personal name and photograph meaningful to him. Later applications can resolve the same key through that saved association without asking SocialCert or its overlay for permission. Removing the certifier from Bob's trust settings need not erase his independently established contact. Conversely, saving a contact does not make every past or future claim from that key true.
13.2 Reverse resolution in transaction history and messaging
A wallet or application already holding Alice's identity key can call:
const result = await wallet.discoverByIdentityKey({
identityKey: aliceIdentityKey,
limit: 10,
offset: 0,
seekPermission: true
})
It can show the returned certified name or profile information beside a payment or message. A contacts-aware helper can substitute Bob's own saved label and photograph. The application SHOULD make it possible to inspect the underlying key and whether the display came from a contact or a particular certificate. A pleasant display name must not obscure that two similarly named counterparties have different keys.
This allows a new application to inherit useful identity context from the user's wallet without importing the user's entire address book into the application's server. Discovery permissions and contact-basket permissions still govern what that application can request. Applications SHOULD avoid public lookups when an adequate local association is available, especially where a lookup would reveal an otherwise private relationship.
13.3 Personal recognition without a certifier
Bob meets Alice in person. They exchange identity keys through their chosen authenticated or independently checked channel. Bob saves Alice's key, his own label, and a photograph in contacts. His wallet authenticates and encrypts that association under Bob's own keys. No external certifier, registry record, public revelation, or common naming platform is needed.
When Alice subsequently messages Bob, proof that the peer controls the saved key lets Bob apply his own association. The wallet MUST permit this use of Bob's personal authority. It must not require a vendor-selected issuer to validate his choice. An application that needs a separately certified qualification may still ask for that qualification, while preserving Bob's contact as his personal identification of the counterparty.
13.4 Qualifications, age assertions, and referrals
A professional directory can discover people by a publicly certified qualification, then request a more detailed private certificate from the selected peer. An employer can certify a role or organization membership, with a defined validity period and revocation policy. A service can ask for a certified age predicate without requesting a name or birth date. These types need explicit schemas; neither a generic trust score nor an email certificate supplies the missing qualification.
A referral application can address and authenticate a referred party by key, display public or locally recognized identity information, and negotiate the service directly. A document-sharing application can encrypt for a selected counterpart using the relevant BRC-100 protocol and key ID. Identity resolution supplies the counterparty; the service's own transaction, authorization, and encryption protocols determine what happens next. These applications reuse the identity machinery instead of each inventing an issuer directory, profile database, or key-to-name authority.
13.5 Social attributes and continuity
Email, telephone, X, and Discord examples illustrate different ways an issuer can verify an existing relationship. The pinned SocialCert backend actively configures email, X, and Discord types. A telephone type remains defined in its source and client conventions but is disabled in that backend configuration. This proposal describes the telephone schema for compatibility; it does not assert that the cited deployment currently offers telephone issuance.
The platform or carrier still controls its underlying account, handle, mailbox, or number. An issuer's evidence may become stale after reassignment, account loss, or policy changes. A durable application MUST distinguish a claim about verification at issuance from continuing control. Renewal, expiry fields, revocation, and fresh interaction can address different parts of that problem; none can be inferred from an attractive badge.
Already obtained certificates and subject-controlled public revelations can remain independently verifiable and retrievable when an issuer website disappears, subject to data availability and the chosen validity policy. A saved personal contact can continue to identify a known key even after a social handle changes. This preserves relationships without claiming to preserve control of a defunct platform account. If the identity private key changes, use an explicit continuity procedure rather than automatically transferring trust to whoever next obtains the same handle.
14. Relationship to Paymail and BRC-169
Paymail makes human-readable addresses useful for discovering capabilities, obtaining payment destinations, and delivering transactions. Its address namespace and capability discovery depend on the address's domain and the services that domain advertises. Self-hosting and multiple providers are possible; it is not a single global operator. Nevertheless, a user of a provider-controlled domain relies on that provider for that name's resolution and continuity. BRC-28 describes Paymail's payment role.
BRC-169 defines human-readable ecosystem handles and certified resolution. It already uses existing certificate and trust mechanisms in parts of its design. Its ecosystem domain remains the authority for allocation and resolution within that handle namespace, with associated directory and delivery information. That is a meaningful choice when an application specifically needs an authoritative domain namespace. It should not be confused with a universal prerequisite for finding people, learning their keys, or paying them.
This proposal permits an alternative application architecture: discover a subject-controlled public assertion under a user's selected issuer trust, authenticate the selected key, and interact using that key. There is no mandatory new ecosystem handle, global directory, wallet-provider account, or single overlay host. Multiple issuers can attest existing attributes, multiple hosts can serve authentic public records, and users can preserve direct associations in contacts. Applications that only need counterparty identification and subsequent interaction SHOULD first use these existing capabilities rather than require another naming system.
The distinction is where authority lies. A domain resolves its own names. A certifier signs an attributable claim. The subject chooses publication. The relying user chooses issuer trust and personal associations. An overlay supplies available evidence. Neither design abolishes dependencies: public records still need hosting and synchronization, certified claims need suitable issuers, and network interaction needs a delivery route. The distributed approach makes these roles independently replaceable and keeps prior cryptographic relationships portable.
An application MAY retain Paymail or an ecosystem handle as an input or compatibility feature. It MUST disclose the additional namespace authority and MUST NOT treat success in one namespace as blanket acceptance of unrelated claims. If a discovered certificate names a familiar email or social handle, its assurance comes from the chosen issuer's claim and policy, not from resemblance to an address accepted by a different payment system.
15. BRC-184 registration requests
15.1 Scope and submission
This section is a protocol, basket, and certificate-type registration request under BRC-184. The accompanying BRC pull request is the public review thread. The initial requested publisher is Metanet Trust Services, separately on mainnet and testnet, through the registry submission process, with @ty-everett tagged in the request. The maintainer is Ty Everett, ty@projectbabbage.com; ordinary discussion belongs in the public thread, not urgent email.
Publication remains a separate publisher action. Until an operator records its publisher public key, network, actual current record outpoints, and outcome in the review thread, these are proposed descriptions, not claims of on-chain registration. Before publishing, the operator MUST inspect existing records for the exact identifiers and correct or update its existing descriptions where appropriate rather than imply the established identifiers are newly allocated. A record is scoped by network, publisher, registry, and exact identifier. Other publishers may independently describe the same identifiers.
For all requested records, documentationURL is the public URL of this complete specification at the reviewed Git commit, without a URL fragment. iconURL is the corresponding raw-file URL for the accompanying identity icon, an original SVG dedicated to the public domain under CC0-1.0. The submission thread supplies the resolved immutable URLs. The icon carries no issuer badge or endorsement. For CertMap field descriptors below, fieldIcon uses that same icon URL. The publisher should preserve a usable licensed copy if hosting changes.
The author and initial requested operator contact overlap. That relationship MUST be disclosed in the review; an uninvolved reviewer should be sought where practicable, without pretending one has approved the request. Corrections and disputes follow BRC-184 and retain the exact identifier, source evidence, reason, and affected record history. Metadata remains optional presentation, not wallet permission, issuer trust, or identifier exclusivity.
15.2 ProtoMap
Each row supplies an exact [securityLevel, protocol], proposed name, and proposed description. Key IDs and counterparties are part of the protocol definition, not fields to concatenate into the registry's protocol string.
| Exact protocol tuple | Name | Description | Key IDs and counterparties |
|---|---|---|---|
[2, "certificate signature"] | Certificate signatures | Signs or verifies the encrypted BRC-52 certificate core under its certifier's derived key. | type + " " + serialNumber; publicly verifiable issuer/anyone derivation |
[2, "certificate field encryption"] | Certificate field revelation keys | Protects per-field revelation keys for certificate acquisition and selective disclosure. | Field name for master keys; serialNumber + " " + fieldName for verifier keys; subject and issuer/revealer or verifier |
[2, "certificate issuance"] | Certificate issuance serials | Authenticates the serial binding for the interactive certificate issuance exchange. | serverNonce + clientNonce; issuer and subject; HMAC over decoded clientNonce + serverNonce |
[2, "auth message signature"] | Authenticated peer messages | Authenticates BRC-103 handshake, certificate-exchange, and application messages under the communicating peers' derived keys. | BRC-103 message/session nonce pairs, joined by one space in the order specified for the message; peer counterparty |
[2, "server hmac"] | Peer challenge authentication | Authenticates nonce bytes used in peer challenge and certificate issuance exchanges. | UTF-8 decoding of the 16 nonce bytes; the particular peer, or self where the calling protocol specifies it |
[1, "identity"] | Public identity revelation | Signs and controls a public output revealing selected certified identity fields. | "1"; subject with "anyone"; public-verification semantics |
[2, "contact"] | Personal contacts | Encrypts and authenticates personal key-to-identity associations and derives private contact lookup tags. | Random 32-byte Base64 record key ID; or canonical subject hex for tag HMAC; "self" |
[1, "identity key retrieval"] | Identity key access permission | Names the wallet permission scope for returning the user's identity public key to an application. | Permission-scoped identity with self; returns the identity key rather than a child of this descriptive permission tuple |
[1, "identity resolution"] | Identity discovery permission | Names the wallet permission scope for discovering public certified identities under the user's trust choices. | Permission-scoped identity with self; no additional public payload or identity certificate format |
[1, "certificate list"] | Certificate listing permission | Names the wallet permission scope for listing stored certificates for an application. | Permission-scoped identity with self; not a certificate-signature or field-encryption key |
These registrations distinguish level 1 from level 2. In particular, public identity is [1, "identity"], while contact persistence is [2, "contact"]. The permission tuples describe existing wallet authorization namespaces, not a grant to applications and not a new cryptographic use of an unspecified key ID. Requesting their metadata does not require an application to invoke a dummy signing or encryption operation.
The pinned permission manager also constructs certificate acquisition and relinquishment scope labels by appending a certificate type to certificate acquisition and certificate relinquishment . These are parameterized permission labels. A Base64 type can contain characters outside BRC-43's protocol-name grammar, so the literal construction cannot be assumed to be a portable cryptographic protocol identifier. This document does not invent a normalization or request a misleading wildcard ProtoMap record for either family. A future canonical mapping needs its own precise specification and migration. Per-verifier certificate disclosure permissions are likewise not a single new literal tuple to fabricate for registration.
tm_identity and ls_identity are overlay topic and service names, not BRC-43 wallet protocol tuples. They are specified here but MUST NOT be published as invented ProtoMap tuples merely to obtain descriptions. The registered authentication signature tuple retains BRC-103's message-specific nonce and payload rules. It is not a blanket encryption protocol, and this request does not allocate a new authentication format.
15.3 BasketMap
| Exact basket | Name | Description |
|---|---|---|
contacts | Personal contacts | Encrypted, owner-authenticated personal associations between identity keys and display attributes, including the derivation metadata required to read and update them. |
The basket description grants neither read access nor permission to spend a contact output. Contact backup must preserve custom instructions as well as transaction data. The public identity helper does not establish an additional mandatory wallet basket; this request does not invent one.
15.4 CertMap and concrete type semantics
The following existing SocialCert-related types are requested with the exact identifiers and field spellings shown. These are type descriptions, not issuer appointments. An implementation MUST still select and verify a particular issuer and its evidence policy. The type identifier alone does not prove issuance by SocialCert. The friendly names and descriptions below are the proposed metadata values.
| Type, canonical Base64 | Name | Description |
|---|---|---|
exOl3KM0dIJ04EW5pZgbZmPag6MdJXd3/a1enmUU/BA= | Email control | A certifier's assertion that a subject demonstrated access to the specified email account under the issuer's verification policy. |
vdDWvftf1H+5+ZprUw123kjHlywH+v20aPQTuXgMpNc= | X account | A certifier's assertion binding an X account user name and associated profile-photo reference to a subject key under the issuer's verification policy. |
2TgqRC35B1zehGmB21xveZNc7i5iqHc0uxMb+1NMPW4= | Discord account | A certifier's assertion binding a Discord user name and associated profile-photo reference to a subject key under the issuer's verification policy. |
mffUklUzxbHr65xLohn0hRL0Tq2GjW1GYF/OPfzqJ6A= | Telephone control | A certifier's assertion that a subject demonstrated access to the specified telephone number under the issuer's verification policy; retained for existing schema compatibility. |
fields in each CertMap record is an object keyed by exact field name. Each descriptor contains friendlyName, description, type, and fieldIcon; this table supplies the first three and Section 15.1 supplies fieldIcon.
| Applicable type | Exact field | friendlyName | description | type |
|---|---|---|---|---|
| Email control | email | Email address | The mailbox address whose access the issuer checked; this field alone does not assert a legal name or continuing exclusive control. | text |
| X account | userName | X user name | The platform user-name string bound by the issuer; exact signed case and spelling must be preserved. | text |
| X account | profilePhoto | X profile photo | The profile-photo reference associated with the verified account; interpret its encoding under the issuer's documented schema. | other |
| Discord account | userName | Discord user name | The platform user-name string bound by the issuer; exact signed case and spelling must be preserved. | text |
| Discord account | profilePhoto | Discord profile photo | The profile-photo reference associated with the verified account; interpret its encoding under the issuer's documented schema. | other |
| Telephone control | phoneNumber | Telephone number | The telephone-number string whose access the issuer checked; it does not imply permanent ownership or a particular legal person. | text |
profilePhoto uses the conservative descriptor other because the signed representation must be interpreted before deciding it is a fetchable image URL. A publisher may use imageURL only after documenting and verifying that constraint for the applicable schema; it must not induce applications to fetch arbitrary signed strings. Images and links remain untrusted external resources.
Historical X registry examples also use username with a lowercase n. A retained description for that historical field, where needed, is { "friendlyName": "Legacy X user name", "description": "Historical spelling; distinct from userName and interpreted only when present in the signed certificate.", "type": "text", "fieldIcon": "<the Section 15.1 icon URL>" }. It is not a replacement name or a rule for modifying existing certificates. Operators MUST inspect existing records and preserve necessary historical descriptions rather than silently rename a signed field.
These deployed types do not supply a universal normalization or expiry rule. The issuer's evidence and application purpose determine exact-match handling; an application must not invent, for example, lowercasing the local part of every email address or stripping telephone prefixes as a cryptographic equivalence rule. For new issuance, issuers SHOULD document canonical representations and include appropriate time/scope information through a compatible type definition. An incompatible new signed schema must not silently repurpose an established type. The synthetic test type in Section 16 is test data and is not another CertMap registration request.
16. Test vectors and acceptance cases
16.1 Cryptographic fixture
The following is entirely synthetic test material. The private scalars, fixed revelation keys, and fixed IVs MUST NOT be used for real accounts. The revocation outpoint is a serialization fixture, not an assertion that the output exists, is unspent, or provides a usable revocation service. These vectors test cryptographic content and formats; they do not establish blockchain acceptance or live overlay completeness.
Interpret hex as bytes and Base64 canonically. publicRevelation.payload and contact.plaintext are serialized as compact UTF-8 JSON in the property order shown, without extra spaces or a trailing newline. SHA-256 values are single hashes. Reconstruct the two scripts from their locking public key, payload or ciphertext, and provided DER field signature using Section 7.2. The complete certificate signature is included, so lengths and hashes suffice to check the reconstructed binary without repeating it as another long hex string.
The master wrappers use the subject/issuer relationship and bare field names; privateName discloses only name to scalar 4; publicEmail discloses only email to anyone. The contact belongs to scalar 5 and names scalar 2. HMAC key derivation uses BRC-100's BRC-42 symmetric-key operation, not the child private scalar or a direct HMAC with the root private key. The issuance fixture uses fixed readable 16-byte challenges to make the unusual string/data ordering inspectable. Its generated serial is a separate fixture and does not replace the certificate's fixed serial of 32 22 bytes.
{
"keys": {
"subject": {
"privateScalarHex": "0000000000000000000000000000000000000000000000000000000000000002",
"publicKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5"
},
"certifier": {
"privateScalarHex": "0000000000000000000000000000000000000000000000000000000000000003",
"publicKey": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9"
},
"verifier": {
"privateScalarHex": "0000000000000000000000000000000000000000000000000000000000000004",
"publicKey": "02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13"
},
"contactOwner": {
"privateScalarHex": "0000000000000000000000000000000000000000000000000000000000000005",
"publicKey": "022f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4"
}
},
"fieldInputs": {
"email": {
"plaintext": "alice@example.invalid",
"keyHex": "4141414141414141414141414141414141414141414141414141414141414141",
"ivHex": "5151515151515151515151515151515151515151515151515151515151515151"
},
"name": {
"plaintext": "Alice Example",
"keyHex": "4242424242424242424242424242424242424242424242424242424242424242",
"ivHex": "5252525252525252525252525252525252525252525252525252525252525252"
}
},
"certificate": {
"type": "ERERERERERERERERERERERERERERERERERERERERERE=",
"serialNumber": "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI=",
"subject": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"certifier": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
"revocationOutpoint": "3333333333333333333333333333333333333333333333333333333333333333.1",
"fields": {
"email": "UVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEfKogOtq1r5zAJRnUSz103d7+0sYMV6N2Gb8xP5gaVEKUhAt8q",
"name": "UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlIBbYFny64VpL4UOEru9WtI0rwQGOFUBN6oRx+yLA=="
},
"signature": "3045022100d31674450017aa3eb449ea890a97694f2141ba34aa037c8d77c4d3e1ff9a348b02201633ad9389b69856b6c46d5d704a7471a7c91286d11db9a094766aee74edbcbf"
},
"certificateBinary": {
"withoutSignatureLength": 353,
"withoutSignatureSHA256": "296e5e07d39301a5530b9ae2b0b14624ea4089ab20eaa860fe4a81fb22e5a624",
"withSignatureLength": 424,
"withSignatureSHA256": "2ba78e3bc714a0940bccfc493957d8dfa0487273a0b1bacc793adb1929917550",
"derivedSigningPublicKey": "02818a006c82d870268dcd8539ff05323a20dcc164762b120e265d52882b616234"
},
"wrappers": {
"masterEmail": {
"field": "email",
"keyID": "email",
"counterparty": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
"derivedKeyHex": "a7b7919cf3290082a206d9e53477e0fc7875eeea32724f93938eabf11876b6dc",
"ivHex": "6161616161616161616161616161616161616161616161616161616161616161",
"ciphertextBase64": "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFsI2cn7ANzJATt2oH2Yj1towY5QgBAgiTfdha4RsvWCremov+Aa8KoX/1Pr8Un7U4="
},
"masterName": {
"field": "name",
"keyID": "name",
"counterparty": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
"derivedKeyHex": "4446a008b8c96887c4473f8b2ea9a40f1361bac2698d80594c639cf1bc3fe44a",
"ivHex": "6262626262626262626262626262626262626262626262626262626262626262",
"ciphertextBase64": "YmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJpJbPrzDkz37u3azKcN6LA265ahzhp77FStWw8eDOrastX7KeFjA40g1/iC1v64FE="
},
"privateName": {
"field": "name",
"keyID": "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI= name",
"counterparty": "02e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13",
"derivedKeyHex": "944165fe7b72c776f29c5508dddcbe9c61b5e5fd2a10c36671d091f7aaa87755",
"ivHex": "7171717171717171717171717171717171717171717171717171717171717171",
"ciphertextBase64": "cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXGMm+yffJMsUvp6/+TM6ou3MI05v+fhM3j3Lj2ODJrpVNEtawBoIT+ZrArRr1xQjwE="
},
"publicEmail": {
"field": "email",
"keyID": "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI= email",
"counterparty": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"derivedKeyHex": "4c3d6500dac678b99372437a07303a3d2019ef71eab2067ed36926f2f55a5f8d",
"ivHex": "7272727272727272727272727272727272727272727272727272727272727272",
"ciphertextBase64": "cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJHQ8mwg3g7Elcs/YVEe8/ybZCR/bHCIA4RUaNZwiQ3nFbQEeWiMLhc8UpKm/ytSS8="
}
},
"publicRevelation": {
"payload": {
"type": "ERERERERERERERERERERERERERERERERERERERERERE=",
"serialNumber": "IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI=",
"subject": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"certifier": "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
"revocationOutpoint": "3333333333333333333333333333333333333333333333333333333333333333.1",
"fields": {
"email": "UVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVEfKogOtq1r5zAJRnUSz103d7+0sYMV6N2Gb8xP5gaVEKUhAt8q",
"name": "UlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlIBbYFny64VpL4UOEru9WtI0rwQGOFUBN6oRx+yLA=="
},
"signature": "3045022100d31674450017aa3eb449ea890a97694f2141ba34aa037c8d77c4d3e1ff9a348b02201633ad9389b69856b6c46d5d704a7471a7c91286d11db9a094766aee74edbcbf",
"keyring": {
"email": "cnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJHQ8mwg3g7Elcs/YVEe8/ybZCR/bHCIA4RUaNZwiQ3nFbQEeWiMLhc8UpKm/ytSS8="
}
},
"payloadUTF8Length": 863,
"payloadSHA256": "adf73cef20e6a9f2827b49c00703e2a34cc32faef7ac7d25439c1b1641a4826d",
"lockingPublicKey": "03ea9865ff14e36433501a70bd172ab83958fc63c7cd6bf6e273f014f4c0960371",
"fieldSignatureHex": "3045022100cd306376fadadaae9b44b12d4353a499bf6dc7f338a132c5d1cde9bb4eff259902206e7176197daa3184abae448a3c9fe189943a03e330cc547e91ef5d89b8946f60",
"scriptLength": 974,
"scriptSHA256": "a4dd9d3d5e0ccd11531894237ef20684689e69034924d26442d408e8c2a714a7",
"revelationID": "78bf82ae1936cce6f98dfbffc8d22ae3822eed6e7f00179603a24671dd150b50",
"decryptedFields": {
"email": "alice@example.invalid"
}
},
"contact": {
"plaintext": {
"name": "Alice at the workshop",
"avatarURL": "https://example.invalid/alice.png",
"abbreviatedKey": "02c6047f94...",
"identityKey": "02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5",
"badgeIconURL": "",
"badgeLabel": "Saved by me",
"badgeClickURL": "",
"metadata": {
"source": "met in person"
}
},
"keyID": "gYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYE=",
"derivedKeyHex": "7c2a3744a8ac624aa63f6f1e08e16a87bd86d52bcdf17cf93492a6461c358725",
"ivHex": "8282828282828282828282828282828282828282828282828282828282828282",
"ciphertextBase64": "goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoICjmzAOMfDajIeoFMXebz3/TZKmmhJg8MB63r01S6sF8sGoxIc/igmi1lXW2uXKmBOR2JhMgoHGTxHZcQI5364N8kqcir14T1aJqyJrZPiEFjGF22IY6lodLyp/ngSNvXE6uW8SHIxvoB3v+HeGx6/Rj3H6IzUTp1zT+Jau8pBEEubTDiETNrq7ebVNPhJeU9k12whqpgP7J3TOBgp+DKIXqPCybzKHPyiBsTrpuKpdEy1WfS758cMd8FlZR6LxB/Q73Db3Gnhq2OZOJgEkI19eJJpJup86EhGYh36iUvqrsw3TL7/1x9UT2QYcggkBl8aOgjYR95JKirjgyZDXZdWTNUT3kID9X5KMMM/CXyGAE/xCfypLRDzF0YtBvdft0OtierHwd+SfjlVD7F5v2MrhmAQTfZ0E3CvHQ==",
"lockingPublicKey": "0384ebefcb1e6421b01b0dbd27b925f3fee9cd86668c6fdc61c39b5e286c482555",
"fieldSignatureHex": "304402202162d792eac035c06b43a1cde8f0403214978c0d06ab9b4f87fdfa7e917706d5022045b8e2063b50462a4f5e4587f21a95d7eefaaad4c3379b349392e27844b308dd",
"scriptLength": 456,
"scriptSHA256": "b9ae0f0ae8d50fb92ccff9361c31f08c040680aea482d235a154e0396cd5f961",
"tagHmacKeyHex": "373db691dfd26a2a5aacf4fb95e5f47eb695f20b0295b48d2e01eae77528d6b3",
"tag": "identityKey 24bf289dd486a165f60c0aa96bc6dec0a5d8a4f9c6d0af95a6afc60b6eb2cfb5",
"customInstructions": "{\"keyID\":\"gYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYE=\"}"
},
"issuance": {
"clientChallenge": {
"randomHex": "30313233343536373839616263646566",
"keyID": "0123456789abcdef",
"derivedKeyHex": "893ee146ce0da0073c2866472b1e39d541e9af30c94608c98140a107afa9247f",
"hmacHex": "9542cc4c6773945c4fe7c8bc3e192a3edee4e13aacbe2df5a2b5be2f51f41cd9",
"nonce": "MDEyMzQ1Njc4OWFiY2RlZpVCzExnc5RcT+fIvD4ZKj7e5OE6rL4t9aK1vi9R9BzZ"
},
"serverChallenge": {
"randomHex": "66656463626139383736353433323130",
"keyID": "fedcba9876543210",
"derivedKeyHex": "c54420ba7f2daffb1424b6505fdfc38b05e37e7157dc5f4940545ef02d866ec9",
"hmacHex": "d06dddea230d8ea9372cc0e46ab27f6fa4c3ea310d8c42dbdeaf60fd5640d702",
"nonce": "ZmVkY2JhOTg3NjU0MzIxMNBt3eojDY6pNyzA5Gqyf2+kw+oxDYxC296vYP1WQNcC"
},
"keyID": "ZmVkY2JhOTg3NjU0MzIxMNBt3eojDY6pNyzA5Gqyf2+kw+oxDYxC296vYP1WQNcCMDEyMzQ1Njc4OWFiY2RlZpVCzExnc5RcT+fIvD4ZKj7e5OE6rL4t9aK1vi9R9BzZ",
"derivedKeyHex": "aedda56b11492efe61485f92f1ea419d8fc4b769ef19c0c99a9b88e92c572c1a",
"dataHex": "303132333435363738396162636465669542cc4c6773945c4fe7c8bc3e192a3edee4e13aacbe2df5a2b5be2f51f41cd966656463626139383736353433323130d06dddea230d8ea9372cc0e46ab27f6fa4c3ea310d8c42dbdeaf60fd5640d702",
"serialNumber": "RMoclwkdq9MSSTZyLj183KaFfbt1cIhFcQF7yAHudyo="
}
}
Expected results: the issuer signature verifies; both master field keys decrypt for their intended parties; scalar 4 reveals name: "Alice Example"; the anyone wallet reveals exactly email: "alice@example.invalid"; the public identity and contact field signatures verify; the contact owner recovers the exact JSON object; and the two parties derive the same issuance serial. The public revelation does not reveal name even though that encrypted field remains in the signed certificate.
The fixture was generated with @bsv/sdk 2.8.10. Its derivations, encodings, ECDSA signatures, AES-GCM envelopes, scripts, HMACs, and hashes were also checked independently with Python and cryptography 50.0.1. Another signer may produce a different valid ECDSA signature; it should verify these provided signatures and reproduce their associated byte/hash results when using the fixture's exact signatures.
16.2 Identity and lookup acceptance cases
These are deterministic conformance cases for the specified behavior, separate from a claim that a live service has passed a test suite. All records below are assumed to have valid authenticated transaction evidence unless the case says otherwise. No submission to a public service is necessary.
| Case | Expected interpretation |
|---|---|
| The Section 16.1 identity script, with its public email keyring | A valid current-format identity payload; its synthetic transaction/revocation evidence still needs separate handling |
| The same certificate held privately with only the master keyring | Usable for the holder's authorized disclosures; not automatically a public identity publication |
| A public result includes an unsigned plaintext cache | Recompute plaintext from authenticated keyring/fields before relying on it |
| Two valid revelations disclose the same email for different subject keys | Both may be admitted; no first-result or first-claim ownership rule |
| Two outputs carry the exact same revelation tuple and one authenticated spend is observed | Persist withdrawal and suppress that revelation's indexed copies |
| A previously withdrawn tuple is later re-admitted or an old cached row remains | Do not restore it to current lookup in the persistent withdrawal profile |
| A fresh keyring envelope reveals a different subset of the same valid certificate | A distinct revelation; inspect its own publication and withdrawal state |
| Query has serial plus a different issuer filter | Dispatch by serial; client must independently check the issuer it intended |
Query has only certificateTypes | Reject as no supported selector |
Query has an empty certifiers array | Reject the malformed supplied filter; no-trust wallets should decide locally |
| Certificate A reveals email; certificate B for the same subject reveals employer | A named email-and-employer attribute query does not join A and B |
Stored userName is Alice, query is alice | No match in TS Stack exact-case profile; match in corrected standalone profile |
Stored email is alice@example.invalid, named email query is alice | Candidate fuzzy match, not proof of exact email equality |
any is one UTF-16 code unit after normalization | No matches |
Public source includes a field whose name is profilePhoto | Exclude that value from any; do not automatically exclude it from its explicit named-field search |
| Host lacks a recent spend or publication | Its answer is incomplete/stale evidence, not a global identity verdict |
16.3 Trust calculation and personal resolution
Let Bob select issuer A with weight 3 and issuer B with weight 2, with threshold 5. Issuer C is unselected. Each record below is already cryptographically verified and appropriately bound to the query.
| Evidence for one subject | Distinct selected weight | Result |
|---|---|---|
| Three different certificates from A | 3 | No qualifying public discovery result |
| One certificate from A and one from B | 5 | Subject qualifies; return attributed accepted certificates |
| A certificate from A repeated in multiple outputs, plus B | 5 | Repetition adds no issuer weight |
| A and C | 3 | C does not contribute or become a selected issuer |
| A and B, then Bob removes B before interpreting cached evidence | 3 under the new policy | Recompute; cached evidence does not preserve the old trust decision |
| A signs email and B signs employer | 5 for the subject | Neither issuer is thereby represented as having signed the other's field |
With threshold 3, A alone can qualify; that is Bob's policy choice. Trust numbers are local weights, not probabilities or a network reputation consensus. A direct saved contact can independently identify the subject under Bob's personal authority. It is not an extra invented issuer certificate or a reason to fabricate a signature.
For contacts-aware sequential key resolution, an authenticated saved contact for the key wins without needing an overlay response. With contacts disabled, a contact is not consulted by that helper. For attribute resolution, a saved name equal to the query can short-circuit the sequential contact helper, while an arbitrary metadata email or any value does not become a supported local search key. In the parallel attribute helper, contacts override corresponding overlay subjects; they do not automatically add every local contact to the result set.
17. Implementation evidence and compatibility
17.1 Pinned sources
The reviewed implementation baseline is the following public source, rather than an unversioned promise about every deployment. The specification above is the protocol description; these links let readers examine how current implementations realize it.
| Source | Revision and relevant areas |
|---|---|
| TS Stack SDK and Wallet Toolbox | c9195d8417579b9c3c56c5c9f29022e1a0019806: SDK package 2.8.10 and Wallet Toolbox 2.14.3 |
| Certificate primitives and peer exchange | SDK auth: Certificate, MasterCertificate, VerifiableCertificate, Peer, and nonce utilities |
| Publication, withdrawal, display resolution, contacts | SDK identity: IdentityClient and ContactsManager |
| Wallet discovery, issuance, trust, permissions | Wallet Toolbox: Wallet.ts, WalletSettingsManager.ts, WalletPermissionsManager.ts, and utility/identityUtils.ts |
| Topic validation and indexed lookup | TS Stack identity overlay: topic, validator, lookup service, storage manager |
| Standalone search compatibility profile | identity-services at b5b20f2ad1e63658483969b30ff024159f9bbf7c: corrected literal/substring matching profile |
| Issuer and concrete social schemas | SocialCert backend at 79de17aa35797b34abcc7587d83cf137a895fa25: issuer configuration, certificate handlers, issuance routes |
| Issuance/publication application | SocialCert UI at b662c8a777c2db2915b32062b4532fbbfaf85255 |
| Application identity components | identity-react at c42f4a474330c3029c6671306b71828075a6c177 |
Metanet Client Desktop and Metanet Explorer provide wallet/application context for these flows. Their names are examples of clients using the underlying wallet ecosystem, not claims that every released UI exposes every operation or passes this proposal's conformance requirements. The normative mechanisms are traceable to the public SDK, wallet, and overlay sources above.
17.2 Compatibility boundaries that implementers must retain
The following observations are relevant to interoperation; they are not new encodings or claims of universal conformance:
- Certificate ordering: the current serializer's
localeComparecan differ from language-independent lexical ordering. Use documented schemas and preserve signed bytes/interpretations; do not silently normalize existing certificates. - Direct master-keyring revealer: interfaces can name a revealer distinct from the issuer, while pinned acquisition/proving paths assume the stored certifier relationship. A deployment must verify support before using a different revealer, rather than assume all interface-shaped values are implemented.
- Discovery permissions: BRC-100's documented optional default and SDK argument defaults differ, and the pinned permissions wrapper does not forward every discovery permission preference. Applications should specify intent explicitly; wallets adopting this profile must honor the documented permission behavior.
- Pagination: the pinned wallet discovery path includes caller pagination in cache identity but does not pass it to the overlay question or fully implement it after trust filtering. It also sends the selected issuer list as one filter, despite the host's 32-issuer bound and settings' larger capacity. A request for a larger page is not evidence that more than the host's default collection was examined. Section 10's conformance requirement calls for actual pagination semantics.
- Search: TS Stack and corrected standalone storage have the explicitly different
anyanduserNameprofiles in Section 9; the pinned wallet's conservative result binding does not erase that difference. - Current state: certificate signature verification, BEEF validity, public revelation withdrawal, and current revocation assessment are separate. The pinned public validator and discovery utilities do not establish every current-state fact merely by returning a certificate.
- Contacts: opt-in SDK contact resolution and an injected in-process
ContactSourcehave different representations. Synthetic local assertions must not be serialized as valid BRC-52 certificates through an unextended BRC-100 wire format. - Presentation: known-type helpers select fields such as
email,userName,name, orprofilePhotofor display. A heuristic display choice is not a new signed assertion or evidence that all CertMap metadata is automatically interpreted by every application. - SocialCert scope: the pinned configuration enables three social types, retains a disabled telephone example, and uses the disabled-revocation sentinel in its ordinary signing path. It must not be described as implementing a functioning per-certificate UTXO revocation service merely because a revoke route exists in source.
These observations give implementers concrete migration work without requiring a competing certificate system. Conformance claims should identify the release, supported profile, exercised role, and any remaining differences. Changes to normative wallet transport or certificate primitives belong with their authoritative BRCs; an integration document cannot resolve those differences by quietly inventing fields.
18. Security, privacy, and operational continuity
Wallets and applications MUST maintain the boundaries between cryptographic evidence, attributed claims, user trust, and permission to act. A valid issuer signature proves who signed, not that the claim is true. A valid subject field signature proves authorization by a key, not informed human consent. Trusted UI, scoped permissions, and understandable publication/disclosure decisions remain necessary.
Public publication makes attributes, issuer relationships, and subject linkage available to observers indefinitely. Withdrawal reduces current discovery, not historical disclosure. Search providers can observe queries; image and documentation servers can observe fetches. Applications SHOULD minimize searches, use local contacts where appropriate, cache with explicit freshness limits, and avoid sending private certificate fields or master keyrings to public services. Metadata, display strings, URLs, and images must be treated as untrusted input and rendered without code execution or unintended local-resource access.
Wallet backups need private-key continuity, held certificates and master keyrings, contact transaction evidence and derivation metadata, and sufficient publication history to manage withdrawals. A public index is not a backup of a private certificate collection or encrypted contacts. Issuers should preserve the evidence and revocation authority necessary for their stated policies; overlay operators should preserve authenticated spend knowledge and test index reconstruction, not just copy current attribute rows.
A failing issuer, registry publisher, wallet vendor, storage host, or overlay need not become a universal identity failure. Users can choose other trust anchors and providers and preserve independently established contacts. The replacement must retain attribution, validate available evidence, and state its limitations. No provider can legitimately transfer another issuer's signing authority merely by hosting its records. When continuity requires a different identity key, explicit re-establishment of trust is necessary.
References
- BRC-2: Data Encryption and Decryption, for the encryption envelope used by the wallet primitives.
- BRC-42 and BRC-43, for child-key derivation and protocol/key/counterparty naming.
- BRC-52: Identity Certificates, BRC-100: Wallet-to-Application Interface, BRC-103, and BRC-104.
- BRC-22, BRC-24, BRC-76, and BRC-183, for overlay submission, lookup, synchronization, and deployment models.
- BRC-184: Optional Metadata Registries and Their Stewardship, registry submissions, and BRC-116, for metadata and wallet permission/trust boundaries.
- BRC-28, BRC-29, and BRC-169, for related payment and naming systems.
- Computing with Integrity, Ty Everett (2020), conceptual background; BRC-51 and BRC-89, application and architecture context.
- RFC 2119 and RFC 8174, requirement terminology.