> For the complete documentation index, see [llms.txt](https://bsv.brc.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bsv.brc.dev/payments/0228.md).

# Unlinkable Payments under the Identity Paradigm

Deggen (<d.kellenschwiler@bsvassociation.org>) Siggi (<siggi.oskarsson@bsvassociation.org>)

## Abstract

This BRC specifies a sender-side profile of [BRC-29](/payments/0029.md). It produces P2PKH payments that a recipient can internalize with existing [BRC-100](/wallet/0100.md) wallets, while keeping the sender's long-term identity key out of the remittance.

The sender generates a fresh ephemeral secp256k1 key pair per payment, derives the beneficiary outputs with [BRC-42](/key-derivation/0042.md) 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 certificates before accepting high-value payments.

## Motivation

[BRC-29](/payments/0029.md) payments are authenticated in the everyday sense that the remittance names the sender's identity key. The beneficiary derives the unlocking key from an ECDH shared secret between that alleged sender identity key and their own identity key, then an HMAC over the invoice number built from the derivation prefix and suffix. That is the right design when the parties want a durable counterparty 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](/key-derivation/0042.md) 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](/payments/0029.md) applies: derivation prefix and suffix, invoice-number construction, P2PKH locking scripts per [BRC-16](/scripts/0016.md), Atomic BEEF 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](/key-derivation/0042.md) 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](/key-derivation/0042.md). Security level `2` follows [BRC-43](/key-derivation/0043.md).

### Payment outputs (beneficiary)

1. Obtain the beneficiary's identity key (how that key is discovered — Paymail, [BRC-125](/payments/0125.md) 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](/scripts/0016.md)).

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:

```json
{
  "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 labels). A current-shape example:

```json
{
  "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 / SPV 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](#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](/key-derivation/0042.md) 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 outpoints 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 overlay, 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 threshold, 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](/peer-to-peer/0052.md) and related discovery surfaces on [BRC-100](/wallet/0100.md), 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, tips 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.

### Automatic mode switch by amount (recommended UX)

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, certifiers).
   * *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 / key IDs).
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](/scripts/0016.md) — Pay to Public Key Hash
* [BRC-29](/payments/0029.md) — Simple Authenticated BSV P2PKH Payment Protocol
* [BRC-42](/key-derivation/0042.md) — BSV Key Derivation Scheme (BKDS)
* [BRC-43](/key-derivation/0043.md) — Security Levels, Protocol IDs, Key IDs and Counterparties
* [BRC-52](/peer-to-peer/0052.md) — Identity Certificates
* [BRC-62](/transactions/0062.md) / [BRC-95](/transactions/0095.md) — BEEF / Atomic BEEF
* [BRC-100](/wallet/0100.md) — Wallet-to-Application Interface
* [BRC-125](/payments/0125.md) — PeerPay URI Scheme for BRC-29 Payments


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bsv.brc.dev/payments/0228.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
