Beersy
BRC-228

Unlinkable Payments under the Identity Paradigm

Sending someone a bit of digital cash normally means telling them who you are, because the payment format includes your long-term . That's fine for a friend or a business you trust, but it means every coffee or casual peer payment lets the recipient permanently tag it to your identity and link it to every other payment you've ever made them. There was no easy way to pay someone spendable coins for a one-off transaction while keeping your long-term identity out of the record.

Darren Kellenschwiler, Siggi Oskarsson17 min read

Reference for an AI

Everything an assistant needs to answer questions about BRC-228 accurately, including what it depends on.

Summary

Why
Casual, low-stakes payments should not force the sender's long-term identity into the remittance just so the recipient can unlock the coins.
What
BRC-228 is a sender-side variant of BRC-29 that swaps the sender's long-term identity key for a fresh one-time key in the payment remittance, producing standard payments any BRC-100 wallet can already receive.
How
The sender generates a new ephemeral key pair per payment, uses it in place of their identity key when deriving the beneficiary's output keys via BRC-42, and places that ephemeral public key in the remittance field the recipient normally reads as , while inputs and change still come from the…

What this lets you do

  • Send a P2PKH payment without exposing your long-term identity key
  • Let unmodified BRC-29/BRC-100 wallets receive and internalize the payment normally
  • Generate a fresh ephemeral key per payment to avoid linking separate payments together
  • Fall back to authenticated BRC-29 when the recipient needs to know who paid
  • Signal ephemeral vs identity mode in an optional higher-level field

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

senderbeneficiaryephemeral keyoutput key

The specification

Abstract

This BRC specifies a sender-side profile of BRC-29. It produces payments that a recipient can internalize with existing BRC-100 wallets, while keeping the sender's long-term out of the remittance.

The sender generates a fresh ephemeral key pair per payment, derives the beneficiary outputs with BRC-42 as if that ephemeral public key were the sender identity key, and places the ephemeral public key in the remittance field ordinarily occupied by senderIdentityKey. The recipient unlocks and accepts the payment exactly as in BRC-29. Inputs and change continue to be produced under the sender's real identity key.

The result is remittance-unlinkable, pseudonymous casual payment within the existing identity-key and invoice-number paradigm: the beneficiary sees a per-payment ephemeral key rather than the originator's long-term identity. That is not anonymity. Authenticated BRC-29 remains available when the beneficiary should be able to recognize the payer: the remitted identity key can be resolved through the Identity client and identity-overlay before accepting high-value payments.

Motivation

BRC-29 payments are authenticated in the everyday sense that the remittance names the sender's identity key. The beneficiary derives the unlocking key from an shared secret between that alleged sender identity key and their own identity key, then an over the built from the and suffix. That is the right design when the parties want a durable relationship. It is the wrong default for small, casual payments where the only requirement is that the beneficiary can unlock the coins — and where putting a stable sender identity key in remittance would let that beneficiary join every such payment to the same person.

This BRC keeps the identity paradigm (BRC-42 invoice numbers, BRC-29 remittance shape, BRC-100 createAction / internalizeAction) and changes only who the "sender" is when deriving beneficiary payment outputs: a one-time random key. The beneficiary's wallet still treats senderIdentityKey as the payer; that value is simply an ephemeral public key the real sender never reuses. The profile does not exchange identity attestations or KYC data. It does not substitute for issuer-traceable or compliance-attested schemes. It is the lightweight unlinkable mode for payments that do not need counterparty attribution.

Specification

Relationship to BRC-29

Unless this document says otherwise, BRC-29 applies: derivation prefix and suffix, invoice-number construction, P2PKH per BRC-16, transport, and BRC-100 internalization.

This profile is wire-compatible with a BRC-29 recipient. A wallet that already accepts BRC-29 via internalizeAction does not need a new remittance schema to receive payments under this BRC. What changes is how the sender chooses the key that fills the sender side of BRC-42 for beneficiary outputs.

Ephemeral sender key

For each payment, the sender MUST generate a fresh ephemeral secp256k1 private key e and the corresponding compressed public key E. Under this profile, E is a per-payment pseudonym: it stands in for the sender in remittance and in BRC-42 derivation for that transaction only. It is not anonymity. Anyone who can later prove the sender possessed e (or controlled the device that generated it) at the relevant time can attribute that pseudonym to a person by ordinary evidence.

  • e MUST be sampled independently with a CSPRNG. It MUST NOT be a deterministic function of the sender's identity key or of any other reusable wallet secret. Deterministic derivation would let anyone who later obtains that secret re-derive E and correlate payments.
  • E MUST be the 33-byte compressed secp256k1 public key for e, encoded as 66 lowercase hexadecimal characters (prefix byte 02 or 03).
  • E is used only as the BRC-42 counterparty public key (the "sender identity key") when deriving keys for outputs paid to the beneficiary under this profile.
  • The sender MUST discard e after the payment outputs have been derived, or retain it only under a privacy policy that treats it as payment-local. Reuse of (e, E) across distinct payments is FORBIDDEN; reuse would re-introduce linkability of those payments to each other via a stable alleged sender key.

The sender's long-term identity key MUST NOT be placed in the payment remittance for beneficiary outputs under this profile.

Invoice number and protocol ID

Beneficiary payment outputs use the same invoice-number scheme as BRC-29, so unmodified recipients can derive the unlocking key:

2-3241645161d8-<derivationPrefix> <derivationSuffix>

Equivalently, when calling BRC-100 / SDK key APIs:

  • protocolID = [2, "3241645161d8"]
  • keyID = "<derivationPrefix> <derivationSuffix>" (single space separator)
  • counterparty (from the sender's ephemeral wallet, when deriving the beneficiary output public key) = the beneficiary's identity key

The shared secret for BRC-42 is therefore ECDH(e, beneficiaryIdentityKey) on the send side, and ECDH(beneficiaryIdentityPrivateKey, E) on the receive side. The HMAC-over-invoice and child-key steps are exactly BRC-42. 2 follows BRC-43.

Payment outputs (beneficiary)

  1. Obtain the beneficiary's identity key (how that key is discovered — , BRC-125 PeerPay, or out-of-band — is out of scope).
  2. Generate ephemeral (e, E) and a payment-wide derivationPrefix.
  3. For each beneficiary output, generate a unique derivationSuffix.
  4. Derive the output public key with BRC-42 using private key e, counterparty = beneficiary identity key, and the invoice number above.
  5. Convert that public key to a P2PKH locking script (BRC-16).

In @bsv/sdk, step 4 is typically a ProtoWallet (or equivalent) constructed over the random private key e, then getPublicKey with the beneficiary as counterparty — the same call shape as ordinary BRC-29 output derivation, but with an ephemeral wallet instead of the user's identity wallet.

Inputs and change (sender identity unchanged)

Inputs MUST be selected and signed by the sender's normal BRC-100 wallet under the sender's real identity keyring.

Change outputs MUST be derived and locked under the sender's normal wallet policy (ordinary self/change derivation). They MUST NOT use the ephemeral key as if it were the sender's identity for change. The ephemeral key exists only to stand in as the BRC-42 "sender" when computing beneficiary payment output keys.

A typical construction is therefore:

  1. Compute beneficiary locking scripts with the ephemeral wallet as above.
  2. Call the real wallet's createAction with those locking scripts as explicit outputs, leaving normal change handling to the wallet.
  3. Sign and process with the real wallet so inputs and change behave exactly as in any other payment.

When output indices must be stable for remittance, the sender SHOULD set options.randomizeOutputs to false, as in BRC-29.

Remittance and payment message

For each beneficiary output, remittance MUST use the BRC-29 paymentRemittance shape, with the ephemeral public key in the sender field:

{
  "derivationPrefix": "<payment prefix>",
  "derivationSuffix": "<output suffix>",
  "senderIdentityKey": "<ephemeral public key E, compressed hex>"
}

The field name remains senderIdentityKey for compatibility. Under this profile its value is E, not the originator's long-term identity key. The payment message / internalizeAction arguments are otherwise as in BRC-29 (Atomic BEEF transaction bytes, output index, protocol: "wallet payment", description, optional ). A current-shape example:

{
  "tx": [1, 1, 1, 1],
  "outputs": [
    {
      "outputIndex": 0,
      "protocol": "wallet payment",
      "paymentRemittance": {
        "derivationPrefix": "<payment prefix>",
        "derivationSuffix": "<output suffix>",
        "senderIdentityKey": "<ephemeral public key E, compressed hex>"
      }
    }
  ],
  "description": "Incoming payment"
}

customInstructions on the sender's createAction outputs MAY mirror the same remittance fields (including payee = beneficiary identity key) for the sender's own records. That metadata is not required for the beneficiary to unlock.

Recipient validation

The recipient MUST validate exactly as in BRC-29: recompute the child public key from senderIdentityKey (here E), their own identity key, and the invoice number; check that it matches the output's P2PKH hash; validate the BEEF / material per wallet policy; then internalizeAction.

No additional check that senderIdentityKey is a registered identity is required for unlocking. Success at this layer means the beneficiary can spend the output. It does not authenticate the originator's legal or network identity. Whether the beneficiary accepts the payment for fulfillment after a failed or empty identity-overlay lookup is a UX and policy decision; see User experience: choosing linkability.

Privacy properties (scoped)

Pseudonymous, not anonymous. Implementations and UX copy MUST NOT call this profile (or payments under it) "anonymous." The ephemeral public key E is a pseudonym for one payment. Cryptography here does not erase real-world attribution. If independent evidence places the sender and beneficiary together effecting the payment when the remittance and timestamps match — for example security-camera footage of both parties tapping phones, corroborated by payment time — a fact-finder can infer that the person sending controlled that ephemeral key at that moment. The same is true of device forensics, testimony, or other ordinary proof. Unlinkability means the beneficiary cannot, from remittance alone, recognize the payer's long-term identity or join this payment to the payer's other payments. It does not mean "cannot be proven in court."

Both modes are private between the two parties. Ordinary (linkable) BRC-29 and this unlinkable profile both rely on BRC-42 shared secrets and off-chain remittance. A third party who sees only the chain does not learn the payer's long-term identity key from the payment derivation itself. Linkable MUST NOT be described as "non-private" or "public." The distinction is narrower: whether the beneficiary (and anyone they share remittance with) learns a stable sender identity they can recognize, look up, and correlate across payments.

Toward the beneficiary under this profile, and any party who sees only its remittance plus chain data:

  • The originator's long-term identity key does not appear in the remittance; the remitted sender field is the per-payment pseudonym E.
  • Distinct payments MUST use distinct ephemeral keys, so remittance pseudonyms do not link those payments to each other as the same long-term identity.
  • Change outputs and input remain under the originator's ordinary wallet behavior. This BRC does not claim graph unlinkability against observers who analyze the full transaction (shared inputs, change patterns, timing, amounts).

Toward the beneficiary specifically: the payment is accepted as if it came from whoever E names. That is intentional. This profile trades durable counterparty attribution for per-payment pseudonymity — not anonymity, and not "privacy" versus "no privacy."

Explicit non-goals

  • Not anonymity, mix-net privacy, or resistance to real-world / legal attribution of a per-payment pseudonym.
  • Not a KYC, travel-rule, or issuer-traceable compliance token.
  • Not a fix for third-party chain-graph analysis.
  • Not a change to BRC-42 mathematics or to BRC-100 method signatures.
  • Not a requirement that every BRC-29 payment become unlinkable. Authenticated BRC-29 (real sender identity key in remittance), plus Identity-client / identity-overlay certificate resolution, remains the right choice when the beneficiary should know the counterparty — especially for high-value transfers.

User experience: choosing linkability

Linkability is not a defect of BRC-29 — it is a product feature — and it is not the opposite of privacy. A linkable payment remains a private matter between payer and payee: remittance travels to the beneficiary, child keys come from their shared BRC-42 secret, and bystanders are not thereby told who paid. What linkability adds is attribution to the counterparty: a stable sender identity key lets the beneficiary recognize who paid, attach a human-readable profile via the identity , and decide whether to trust the funds before releasing goods.

Unlinkability (this profile) is the complementary feature: the beneficiary can unlock and accept without learning which long-term identity paid, and cannot tie this payment to the sender's other payments via remittance. The remitted key is still a pseudonym for that payment, not an anonymous void. Wallets and apps that support both MUST treat the choice as "show the recipient my long-term identity" versus "use a one-time pseudonym," never as "private" versus "not private," and never as "anonymous." Present it as an explicit mode rather than an accident of key hygiene.

When to prefer authenticated BRC-29 (linkable)

Use ordinary BRC-29 — remittance senderIdentityKey equal to the originator's long-term identity key — whenever the beneficiary should know who is paying, whether by policy or by the sender's own wish. Typical cases:

  • High-value purchases (vehicles, real-property deposits, large OTC trades)
  • Contracts, invoices, or receipts that must later name the payer
  • Any flow where the beneficiary will refuse "a random key" and require an accountable counterparty
  • Small, voluntary attribution — for example tipping a musician a few dollars under the jurisdiction , but still wanting them to see who tipped

In these flows, after cryptographic internalization checks pass (or in parallel, before releasing value), the beneficiary's app SHOULD resolve the remitted senderIdentityKey through the Identity client against the identity overlay topic: look up that key and present any certificates (BRC-52 and related discovery surfaces on BRC-100, e.g. discoverByIdentityKey) that attest attributes bound to it — legal name, business name, jurisdiction identifiers, or other human-readable or machine-readable fields the overlay makes available. Acceptance policy is then: unlockability is necessary but not sufficient; the resolved identity and its attestations must meet the merchant or user's bar.

A vehicle sale is the canonical example. The dealer does not accept payment from an unbound ephemeral key. They require the remittance to name a real identity key, query the identity overlay for certificates on that key, show the attested attributes to the staff or automated policy engine, and only then treat the payment as coming from a known party.

When to prefer this unlinkable profile

Use this profile for small or casual payments where the beneficiary's only operational need is to receive spendable coins and the sender does not want that beneficiary to attribute the payment to their long-term identity — retail POS under a low threshold, without long-term identity attribution, peer transfers where recognition is unnecessary, metered digital goods, and similar. The sender opts in (or the app defaults) to ephemeral remittance; the beneficiary unlocks without an identity round-trip. This is still a private payment between the two parties; only counterparty attribution is withheld.

Wallets and checkout apps SHOULD treat unlinkable versus linkable as an amount-gated default, not as the only control. Linkability remains desirable in many small-value cases; the threshold only removes the option to stay unlinkable toward the recipient above a line. Both sides of that line remain private between the two individuals involved.

Suggested behavior. For a given user jurisdiction (and, where relevant, the merchant's jurisdiction), the product configures a threshold T — the maximum payment value that may be sent unlinkably under local policy.

  • While paymentValue < T, the app MAY default to this unlinkable profile, but MUST still offer an explicit control to send as authenticated BRC-29 (real long-term senderIdentityKey) at any amount.
  • When paymentValue >= T in that same transaction, the app MUST automatically switch to authenticated BRC-29 and MUST NOT offer unlinkable mode for that send.

Voluntary linkability below T matters. Example: tipping a favorite musician a few dollars. The amount is under the jurisdiction threshold, so unlinkable mode would be allowed — yet the tipper may want the artist to know who paid, resolve their identity key on the overlay, and see a name or profile. That choice adds attribution; it does not make the tip a public broadcast. The UI SHOULD offer "Pay as me (show my identity)" alongside "Pay unlinkably (don't show who I am)" whenever unlinkable mode is permitted, not only when policy forces identity — and MUST avoid labeling the attributed option as somehow not private.

Concretely:

  1. User builds a payment (cart, invoice, tip, or free-amount send) under a jurisdiction profile that defines T.
  2. If paymentValue < T, the default MAY be ephemeral (this BRC); the user can still select linkable / "Pay as me" before signing.
  3. If the user increases the amount, adds line items, or otherwise causes paymentValue >= T within that same transaction, the wallet switches composition to linkable BRC-29 before signing — regenerating beneficiary output keys and remittance under the real identity key — and SHOULD explain the switch ("This amount requires a verified payer identity in your region"). Manual override back to unlinkable MUST NOT be offered above T.
  4. Crossing back below T before send MAY re-enable the unlinkable option (restoring the user's last explicit choice or the default); after broadcast, mode is fixed by what was remitted.

T is not a consensus rule and will differ by jurisdiction and product risk appetite (some regions may set T to zero for certain merchant categories; others may allow a non-trivial casual threshold). This BRC only recommends that implementations express policy this way so users are not left to remember when unlinkable mode is inappropriate. Split payments crafted to stay under T are a compliance concern for the product and obliged entities, not something this wire format can prevent; apps SHOULD apply aggregation rules where local law expects them.

Merchants MAY publish a stricter acceptance floor than the sender's T (for example always require resolved identity above a store policy). Sender auto-switch and recipient acceptance policy are complementary: the sender is forced to upgrade remittance at T, may choose to upgrade earlier for social or commercial reasons, and the recipient still runs overlay lookup when their own threshold or category demands it.

Recipient UX for incoming payments

Because the wire shape is the same, every incoming BRC-29-shaped payment presents a senderIdentityKey that might be either a long-term identity or an ephemeral one. Recipient UX SHOULD:

  1. Always run the BRC-29 unlock / internalizeAction checks (output key derivation, BEEF/SPV).
  2. Optionally resolve identity via the Identity client: query the identity overlay topic for the remitted key and collect certificates / attributes attested for it.
  3. Classify the payer presentation:
    • Resolved identity — one or more acceptable certificates (or a prior trusted binding) associate the key with attributes the user can read. Show that profile ("Paid by Alice GmbH", verified fields, ).
    • Bare key — the key unlocks the invoice but the overlay returns no useful attestations. Show it as an unknown / uncertified payer (display a truncated key if needed), not as a named person.
    • Explicit unlinkable / ephemeral — if the sending app labels the mode in a higher-level envelope, surface "Unlinkable payment" / "One-time payer pseudonym" (or equivalent) — never "anonymous payment" — rather than implying a failed identity lookup, and rather than implying that ordinary linkable payments are non-private.
  4. Apply acceptance policy before fulfillment (shipping, keys, vehicle release): high-value flows MUST require a resolved identity that meets policy; casual flows MAY accept bare or ephemeral keys after unlock alone.

Failing to resolve certificates MUST NOT be conflated with a failed payment. The coins may still be valid and spendable; only the counterparty assurance is missing. Conversely, rich certificates on a key do not replace unlock and SPV checks.

Sender UX

Senders SHOULD always see a clear choice when unlinkable mode is permitted, for example "Pay unlinkably (don't show who I am)" versus "Pay as me (show my identity)". Choosing the authenticated mode shares their long-term identity key with the beneficiary via remittance and invites that beneficiary's Identity-client lookup — including for small amounts where the user wants attribution (tips, gifts, "it was me"). That payment remains private between the two of them. Choosing this profile uses a fresh ephemeral key and SHOULD be described in plain language: the recipient can take the money but sees only a one-time pseudonym, not your long-term identity, from the payment.

When amount-gated auto-switch is enabled, the unlinkable option is available only while the transaction total remains under the jurisdiction threshold T; at or above T the UI SHOULD lock to "Pay as me" (or equivalent) and show why. Below T, "Pay as me" MUST remain selectable even if unlinkable is the default. Copy MUST NOT imply that "Pay as me" is a non-private or public payment. For merchant checkouts that always demand identity, the sender's app SHOULD refuse the unlinkable mode entirely rather than letting the user send an ephemeral payment that will be rejected after overlay lookup.

Mode signaling (optional)

This BRC does not require a new remittance field. Apps MAY nonetheless signal mode in a higher-level payment envelope (for example a sibling field alongside the Atomic BEEF) such as "senderMode": "ephemeral" | "identity" so recipients can skip a pointless overlay lookup on clearly unlinkable payments and can label the UX accurately. Absence of a signal MUST be treated as "unknown": unlock first, then resolve identity if policy requires it.

Implementations

Senders need:

  1. Secure ephemeral key generation (CSPRNG; no deterministic derivation from the identity key).
  2. BRC-42 derivation of beneficiary output keys using that ephemeral key (for example @bsv/sdk ProtoWallet over the random key, then getPublicKey with the beneficiary identity key as counterparty and BRC-29 protocol / ).
  3. Ordinary BRC-100 createAction / signing for inputs and change.
  4. Remittance that places E in senderIdentityKey.

Recipients need no new code path beyond BRC-29 internalization, provided they already accept senderIdentityKey as "whatever key unlocks this invoice."

Security considerations

  • Pseudonymous, not anonymous. UX, docs, and marketing MUST NOT claim anonymity. E is a per-payment pseudonym. Contextual evidence (co-location and NFC/QR timing, cameras, device seizure, admissions) can persuade a court that a particular person held e when the payment was made, even though remittance alone does not name their long-term identity key.
  • No protocol-level binding to long-term identity. A payment under this profile proves that someone who knew e at construction time paid the beneficiary; the protocol does not bind that act to a long-term identity key. Do not use this profile where the beneficiary must recognize or look up who paid from the payment itself.
  • Ephemeral key hygiene. Leaking e before broadcast can allow third parties to derive the same child keys for that invoice. Treat e like any other payment-local private key until outputs are finalized, then discard.
  • Chain-graph leakage. Inputs and change remain under the sender's ordinary wallet. Observers who analyze the full transaction may still correlate this payment with the sender's other activity. Remittance unlinkability does not imply graph unlinkability.
  • Malicious remittance. As with BRC-29, a wrong senderIdentityKey simply fails internalization (output hash mismatch). Substituting someone else's identity key does not let an attacker steal the beneficiary's funds; it only changes which ECDH secret the beneficiary would need, which they will not have unless they are that someone.
  • Social engineering. Because the remittance still looks like an authenticated BRC-29 payment, UX MUST NOT present a bare or ephemeral senderIdentityKey as a named, verified counterparty. High-value acceptance MUST go through Identity-client resolution against the identity overlay (certificates on that key) as described in the UX section; casual acceptance may skip that step deliberately.

References

  • BRC-16 — Pay to Public Key Hash
  • BRC-29 — Simple Authenticated BSV P2PKH Payment Protocol
  • BRC-42 (BKDS)
  • BRC-43 — Security Levels, , Key IDs and Counterparties
  • BRC-52
  • BRC-62 / BRC-95 — BEEF / Atomic BEEF
  • BRC-100
  • BRC-125 — PeerPay URI Scheme for BRC-29 Payments
Was this helpful?

Search Beersy

Search standards by number, title, author or topic