Abstract
We specify two Paymail capabilities that bind a human-readable handle@domain to an identity key, in both directions. The forward capability, public profile lookup (0ace65da5987), takes a full or partial handle and returns matching public profiles. The reverse capability, public profile reverse lookup (43dcf83ddc5f), takes an identity key and returns its profile. Every profile is a self-signed BRC-52 certificate in which subject and certifier are both the holder's identity key, so a client verifies what the host returns rather than trusting it. The identity key obtained is the recipient for BRC-29 payments; the reverse capability lets interfaces show alice@example.com where they would otherwise show 66 hex characters.
Discovery is unchanged from Paymail: DNS SRV _bsvalias._tcp for the host, then the /.well-known/bsvalias capability document. A host may publish these two capabilities and nothing else.
Motivation
Paymail (BRC-28) solved addressing with user@domain, resolved at the domain, and that deployment model is still the right one: operators already run DNS, SRV records and .well-known/bsvalias, and users already recognize the format. What has aged is what the address resolves to. Legacy capabilities hand out a public key for a script or a payment destination per request; identity-based wallets (BRC-100) want one thing instead: the recipient's identity key, from which BRC-42 derivation and BRC-29 payment take over without further help from the host.
Two problems follow from asking a host for an identity key:
- Trust. A host that answers "this handle is this key" in plain JSON can substitute its own key. Here the host returns a certificate the holder signed, naming the handle and domain, so the host cannot forge a profile or move one to another handle. It still decides which key holds a handle; that residue is inherent to any domain-scoped name and is stated under Security Considerations.
- Hex in interfaces. Wallets that receive a BRC-29 payment, or list contacts by key, have no name to show. A reverse lookup at the payer's domain recovers one.
These capabilities deliberately need none of the legacy ones. A modern wallet operator should be able to serve .well-known/bsvalias with exactly these two entries, and a client should be able to resolve against such a host.
Relation to BRC-169
BRC-169 specifies a broader addressing system, @handle@ecosystem, discovered through a BRC-68 manifest, with handles attested by the ecosystem's certifier key, on-chain revocation, messaging, reachability policy and delegation. This document is narrower and differs in two ways:
| BRC-169 | BRC-235 | |
|---|---|---|
| Discovery | BRC-68 manifest.json, metanet.handles |
Paymail SRV + .well-known/bsvalias capability (BRFC id) |
| Who signs the binding | Ecosystem host (certifier = host key) |
The holder (subject = certifier) |
| Revocation | Spend of a certifier outpoint | None on chain; replace or tombstone |
| Address syntax | @handle@ecosystem |
handle@domain |
A host MAY implement both. The certificate types differ, so a client never mistakes one for the other.
Specification
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119.
1. Terminology
- Handle: the local part of a paymail, unique within its domain.
- Paymail:
handle@domain, always lowercase in a profile. - Host: the HTTPS origin that serves a domain's capabilities, found by discovery (section 3).
- Profile: a profile certificate (section 5) that passed client verification (section 8).
- Tombstone: a profile carrying
released: "true"; it announces that the holder gave the handle up.
2. Capability identifiers
Both identifiers are BRFC ids: the first 12 hex characters of the byte-reversed double SHA-256 of title + author + version, each trimmed, as in the existing Paymail BRFC scheme.
brfcid: 0ace65da5987
title: public profile lookup
author: Deggen
version: v1.0.0
brfcid: 43dcf83ddc5f
title: public profile reverse lookup
author: Deggen
version: v1.0.0
The leading v in the version is part of the hashed input; without it the forward id would be b78c0cbacf47.
3. Discovery
A client resolving domain:
- MUST query the SRV record
_bsvalias._tcp.<domain>. If the answer names a target other thandomainitself, the client MUST require that the answer is DNSSEC-authenticated (for example, the AD bit from a validating resolver), and MUST otherwise treat discovery as failed rather than falling back. When there is no SRV record (NXDOMAIN or an empty NOERROR answer), the host ishttps://<domain>on port 443. A resolver failure such as SERVFAIL is a failure, not an absence: under DNSSEC it is what a bogus zone produces. - MUST fetch
https://<target>[:<port>]/.well-known/bsvaliasand readcapabilities. - MUST treat the capability as unavailable unless its value is an absolute
https://URL containing the placeholder this document names for it. - SHOULD refuse a template, or an SRV target, whose host is an IP literal,
localhost, or a private or link-local name. A domain's own document names where later requests go, and nothing else binds that destination to the domain. - MAY cache a successful discovery for a bounded period (ten minutes is typical) and a failed one for less.
A client configured with a fixed host for one domain (its own operator's, for instance) MAY skip discovery for that domain.
A host:
- MUST list each capability it offers in
capabilitiesunder its BRFC id. - MAY list only these two capabilities. The well-known document below is complete:
{
"bsvalias": "1.0",
"capabilities": {
"0ace65da5987": "https://paymail.example.com/api/handle/{query}",
"43dcf83ddc5f": "https://paymail.example.com/api/identityKey/{pubkey}"
}
}
Clients MUST NOT require any other capability, including pki or paymentDestination, before using these two. Paths are the host's choice; only the placeholders are fixed.
4. Handle syntax
A handle is 1 to 32 characters matching:
^[a-z0-9](https://raw.githubusercontent.com/bsv-blockchain/BRCs/fc24468f73b1357bc8d12c32b742a45d8168e81c/payments/%5Ba-z0-9._-%5D%7B0%2C30%7D%5Ba-z0-9%5D)?$
A host MAY impose a higher minimum length and MAY reserve names (admin, postmaster, bsvalias, …). A host SHOULD refuse to register a handle that is confusable with an existing one: for example by comparing a skeleton that removes ., _ and -, folds rn→m, vv→w, 0→o, 1→l, i→l, 5→s, 2→z, 8→b, and collapses repeated characters. The skeleton is a registration rule; clients need not compute it.
5. Profile certificate
A profile certificate is a BRC-52 certificate in its JSON form:
{
"type": "...",
"serialNumber": "...",
"subject": "...",
"certifier": "...",
"revocationOutpoint": "...",
"fields": { "...": "..." },
"signature": "..."
}
with these rules:
typeMUST beSbatVXXssDW3AO0J9bxIljkHGbPBGCVAXg94gXFf0cE=, the base64 of SHA-256 of the UTF-8 stringpublic profile lookup.subjectMUST equalcertifier, compared as public keys (hex case-insensitively). That key is the holder's identity key. A signature that verifies againstcertifiersays nothing aboutsubjectunless this equality is checked separately.signatureMUST verify per BRC-52 againstcertifier, counterpartyanyone.revocationOutpointMUST be the zero outpoint,0000000000000000000000000000000000000000000000000000000000000000.0. There is no on-chain revocation: a holder replaces a profile with a newer one or publishes a tombstone.serialNumberMUST be 32 bytes in canonical base64. A holder MUST use a fresh serial for every profile it issues.fieldsvalues are plaintext UTF-8 strings. BRC-52 field encryption and keyrings are not used; a profile is public by definition.paymail(required):handle@domain, all lowercase, withdomainthe domain the profile is published under.issuedAt(required): an RFC 3339 timestamp. A later profile for the same handle MUST carry a laterissuedAt; hosts use it to refuse replays of older profiles.released(optional):"true"marks a tombstone. Any other value, or absence, means not released.displayName(optional): a name to show alongside the paymail. It is not unique and MUST NOT be used to identify anyone.- Any other field name is free-form (avatar, bio, …) and MAY be ignored.
- Limits: at most 32 fields; each field name under 50 bytes; each value at most 1024 bytes; the serialized certificate at most 16384 bytes.
How a holder submits a profile to its host (registration, update, release, account recovery) is outside this specification. A host that accepts submissions SHOULD verify rules 1 to 7 on write, SHOULD bound issuedAt to a few minutes ahead of its own clock (a far-future value would win every later comparison and freeze the handle), and SHOULD serve tombstoned handles from neither capability.
6. Public profile lookup (0ace65da5987)
Request. The client replaces {query} in the template with the URL-encoded query and performs GET.
The query is what a user has typed: al, alice, or alice@example.com. The client SHOULD lowercase and trim it and SHOULD NOT send a query the host would not search: one shorter than 2 or longer than 32 characters after any @domain suffix is removed, or containing characters outside [a-z0-9._-]. A client MUST NOT send a query that is a path segment with special meaning to URL parsers (., ..).
Host behavior. The host:
- lowercases the query and strips an
@<domain>suffix. A suffix that is a prefix of the domain the host serves is a domain still being typed and is accepted; any other suffix matches nothing. - returns an empty result for a query outside the length and character limits above, rather than an error.
- matches on the handle only. It MUST NOT match on
displayNameor other free-form fields: those are not unique and searching them invites impersonation. - ranks results best first. RECOMMENDED order: the exact handle; handles with the query as prefix; handles whose confusable skeleton has the query's skeleton as prefix; handles containing the query (queries of 3 or more characters only).
- returns at most 10 results and no tombstones.
Response. 200 with a JSON array of profile certificates, possibly empty:
[ { "type": "SbatVXXssDW3AO0J9bxIljkHGbPBGCVAXg94gXFf0cE=", "...": "..." } ]
No match is [], never 404 and never null.
7. Public profile reverse lookup (43dcf83ddc5f)
Request. The client replaces {pubkey} with a 33-byte compressed public key as 66 lowercase hex characters and performs GET.
Response. 200 with the single current profile certificate (a JSON object, not an array) of that key at this host, or 404 when the key holds no handle here. A key that does not match ^0[23][0-9a-f]{64}$ is 400.
A host answers only for handles it hosts; there is no cross-domain index. A host holds at most one active handle per identity key.
8. Client verification
The host is a directory and a cache, not an authority on what a profile says. A client MUST apply every rule below to every certificate it receives, from either capability, before showing or using any field, and MUST discard a certificate that fails any rule, not the whole response.
- Rules 1 to 7 of section 5, except freshness of
issuedAt. fields.paymailends with@<domain>, wheredomainis the one the client resolved, compared case-sensitively against the lowercase form.fields.releasedis not"true".- A client SHOULD process at most 10 results from a lookup, since each one costs a signature verification and the response size is set by a host the client may not control. A client SHOULD bound response size and time.
For lookup:
- Results are suggestions. A client MUST show the full
fields.paymailof each and let the user choose, and MUST NOT select a result on the user's behalf by position. - When the user entered a complete
handle@domain, the client MUST accept only a certificate whosefields.paymailequals it exactly.
For reverse lookup:
subjectMUST equal the queried key (hex case-insensitively).- A client MAY forward-resolve
fields.paymailand check that it returns the same key, which detects a host serving a stale profile.
The verified subject is the identity key to pay. A client SHOULD remember the key it paid under a paymail and warn when a later lookup returns a different one.
9. Errors
Errors other than the empty lookup result use a non-2xx status: 404 for a reverse lookup of a key with no handle, 400 for a malformed key. Clients act on the status alone; the error body is the host's choice, and MAY be a JSON object with a machine-readable code. A host SHOULD rate-limit both capabilities per client. A client MUST NOT treat any error as a lookup result.
Security Considerations
What the host cannot do. Without the holder's private key, the host cannot alter a profile's fields, move a profile to another handle or domain, or forge a profile for a key it does not hold. Each of those breaks the signature or rule 2 of section 8.
What the host still decides. Which key holds a handle at its domain is the host's decision, as it is for every domain-scoped name: a host can register a handle to its own key first, or reassign a handle after a recovery process. It can also serve an older profile of the same key, or withhold one. Clients that pin keys per paymail (section 8) detect reassignment after first contact.
Lookalikes. A handle that resembles another (a1ice and alice) is a different handle with a different key and a valid certificate. Hosts SHOULD refuse confusable registrations (section 4); clients MUST show the full paymail and require exact equality where the user typed one.
Reverse lookup links keys to names. An identity key appears in BRC-29 remittances, in certificates, and wherever the holder has authenticated. Reverse lookup turns any such sighting into a name. Holders who want contexts kept apart SHOULD use separate identity keys, not separate handles, and payers who want neither direction SHOULD use BRC-228.
Discovery. An SRV answer that moves resolution to another host is trusted only under DNSSEC (section 3). The capability template is attacker-controlled for an attacker's own domain, so clients restrict its destination (section 3, client rule 4).
Resource bounds. Lookup results come from hosts the client does not control; the result cap and size bounds of section 8 keep one response from becoming an unbounded amount of signature verification.
Test Vectors
BRFC ids. BRFCID("public profile lookup", "Deggen", "v1.0.0") = 0ace65da5987; BRFCID("public profile reverse lookup", "Deggen", "v1.0.0") = 43dcf83ddc5f.
Certificate type. base64(SHA-256("public profile lookup")) = SbatVXXssDW3AO0J9bxIljkHGbPBGCVAXg94gXFf0cE=.
Profile certificate. Signed with the test-only private key 6a2991c9de20e38b31d7ea147bf55f5039e4bbc073160f5e0d541d1f17e321b8 and serial bytes 01 02 … 20. It passes every rule of section 8 for domain example.com and, for reverse lookup, queried key 025ad43a22ac38d0bc1f8bacaabb323b5d634703b7a774c4268f6a09e4ddf79097.
{
"type": "SbatVXXssDW3AO0J9bxIljkHGbPBGCVAXg94gXFf0cE=",
"serialNumber": "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
"subject": "025ad43a22ac38d0bc1f8bacaabb323b5d634703b7a774c4268f6a09e4ddf79097",
"certifier": "025ad43a22ac38d0bc1f8bacaabb323b5d634703b7a774c4268f6a09e4ddf79097",
"revocationOutpoint": "0000000000000000000000000000000000000000000000000000000000000000.0",
"fields": {
"displayName": "Alice",
"issuedAt": "2026-10-29T12:00:00.000Z",
"paymail": "alice@example.com"
},
"signature": "304402201433492b6713a2f210bbd75c5d57de1085b92193f868e1add7785d35e55fc602022032ee8493f6e7d2273164c22c9ae8d8e59419e56d7ba0445663a17a9513c84c19"
}
The same certificate fails verification for domain example.org (rule 2), and fails reverse lookup for any other queried key (rule 7). Changing any field value invalidates the signature.
Implementations
- go-message-box-server hosts both capabilities (
pkg/handlers/lookup.go) with registration, release and confusable-handle rules. - Client and host support is in progress for
@bsv/paymail(ProfileLookupRoute,PaymailClient.lookupProfiles) and go-paymail (WithProfileLookupCapabilities,Client.LookupProfiles). Both verify the test vector below.
References
- BRC-28: Paymail Payment Destinations
- BRC-29: Simple Authenticated BSV P2PKH Payment Protocol
- BRC-42: BSV Key Derivation Scheme (BKDS)
- BRC-52: Identity Certificates
- BRC-100: Unified, Vendor-Neutral, Unchanging, and Open BSV Blockchain Standard Wallet-to-Application Interface
- BRC-169: Universal Handle Addressing and Resolution for the Metanet
- BRC-228: Unlinkable Payments under the Identity Paradigm
- RFC 2782: A DNS RR for specifying the location of services (DNS SRV)
- RFC 3339: Date and Time on the Internet: Timestamps