Nostr silent payment address

WARNING: I have no idea what I’m doing, this is an exploration of BIP-352 and one way it could be used with nostr public keys

NIP-SP: Nostr-Derived Silent Payments

draft optional

This document defines how to send and receive BIP-352 silent payments using a Nostr public key (npub) as the sole identity input. Every Nostr keypair deterministically maps to a silent-payment address (sp1q…) without any setup, on-chain footprint, or out-of-band publication: the recipient’s BIP-352 scan and spend keys are derived from npub via public additive tweaks, so any sender can construct the recipient’s silent-payment address from their npub alone. Each payment produces a unique Taproot output with full BIP-352 privacy semantics on the receiving side.

Document structure

This NIP is organized in two independent parts.

  • Part 1 — Bitcoin-side (§1–§6) is a self-contained Bitcoin protocol. Given an npub it defines the BIP-352 address; given an nsec it defines how to receive (chain-scan) and spend (PSBT). No Nostr events are involved. A wallet that implements only Part 1 is fully BIP-352-interoperable.
  • Part 2 — Nostr integration (§7–§8) defines optional Nostr event kinds that improve UX on top of Part 1: a per-payment receipt notification (kind 8352) and an encrypted UTXO-cache event (kind 10353). A wallet MAY implement Part 1 without Part 2.

Cross-cutting concerns — security, compatibility, test vectors, references — follow as §9–§12.

⚠️ Critical Security Warning

The derivation in this NIP is NOT hardened. bscan and bspend are both nsec + (publicly known tweak) mod n, so revealing either private key is mathematically equivalent to revealing nsec itself — anyone holding the disclosed key plus the user’s npub can recover nsec with one subtraction (see §9.1 for the derivation).

Consequences a wallet MUST internalize:

  • bscan and bspend MUST be treated with exactly the same care as nsec. They are not “view keys” in the conventional BIP-352 sense; for npub-derived wallets they are full identity-compromising secrets.
  • Silent-payment wallets derived from a Nostr identity MUST NOT use any third-party scanning service that requires the user to hand over bscan. Doing so is operationally identical to publishing the user’s nsec. This includes any remote indexer, hosted wallet, watch-only server, or “scan-for-me” relay that takes bscan as input.
  • Only two scanning architectures are safe: (a) local scanning on the user’s own device, and (b) a “tweak-data” service that returns only public per-transaction tweaks and lets the wallet finish the ECDH locally with bscan never leaving the device. See §5.1.
  • Users who genuinely need a remote scanning service that ingests bscan MUST use a separate BIP-352 wallet whose keys are independent of any Nostr identity — never an npub-derived wallet.

If your wallet UI exposes bscan to the user (e.g. for export), it MUST display the same warnings as for nsec export.

Motivation

Any static single-address derivation from a Nostr key — for example, treating npub directly as a BIP-341 Taproot internal key — gives the user one reusable Bitcoin address. Reusing a single address across multiple payments leaks the cluster of payments to public chain analysis. BIP-352 solves this by producing a unique output per payment, derived non-interactively from the recipient’s two-key silent-payment address.

A direct BIP-352 deployment requires recipients to generate and back up a second pair of keys (scan + spend). This NIP derives both keys deterministically from the user’s existing Nostr keypair via public additive tweaks of npub, so:

  • There is no second secret to back up — nsec remains the sole secret.
  • The recipient does not need to publish anything before they can be paid. Any sender that knows their npub can derive their silent-payment address and pay them.
  • The mapping is symmetric: the sender derives (Bscan, Bspend) from npub; the recipient derives (bscan, bspend) from nsec. Both arrive at the same key pair.

The trade-off relative to a hardened (one-way) derivation is that bscan and bspend are arithmetically linked to nsec via publicly known tweaks. Disclosing either compromises the corresponding Nostr identity, so they MUST be treated with the same care as nsec itself. In particular, this NIP does not permit handing bscan to a remote scanning service (see §5.1 and §9.1).


Part 1 — Bitcoin-Side: Silent Payment Address Derivation and Spending

This part defines everything required to interoperate with BIP-352 against a Nostr-derived silent-payment address. It uses npub and nsec purely as cryptographic inputs; no Nostr relays, events, or network calls are involved.

1. Definitions

Symbol Meaning
n Order of the secp256k1 curve
G secp256k1 generator point
nsec The recipient’s raw Nostr private key (32-byte scalar)
npub The recipient’s Nostr public key (32-byte x-only, per BIP-340)
P_npub The point lift_x(npub) — even-y by BIP-340 convention
d_npub The BIP-340-normalized scalar such that d_npub · G = P_npub
t_scan, t_spend Public per-identity additive tweaks (§2.1)
bscan, bspend Derived BIP-352 scan/spend private keys
Bscan, Bspend Derived BIP-352 scan/spend public keys
tₖ BIP-352 per-output tweak for output index k
m BIP-352 label scalar (0 ⇒ unlabeled / change)
Pₖ The on-chain Taproot output key for output k
H_tagged(tag, msg) BIP-340 tagged hash: SHA256(SHA256(tag) ‖ SHA256(tag) ‖ msg)

All scalars are mod n unless stated otherwise. Public keys are serialized in compressed SEC1 form (33 bytes) except where x-only is required.

d_npub is the BIP-340-normalized form of nsec:

d_npub = nsec        if (nsec · G) has even y
       = n − nsec    otherwise

This is the same normalization Nostr already applies when signing per BIP-340; no new state needs to be stored.

2. Key Derivation

2.1 Additive derivation from npub

Both the per-identity tweaks and the resulting scan/spend keys are derived as follows.

Tweaks (public; either side can compute):

t_scan  = H_tagged("nostr-sp/scan",  npub) mod n
t_spend = H_tagged("nostr-sp/spend", npub) mod n

Sender side (uses only npub):

Bscan   = P_npub + t_scan  · G
Bspend  = P_npub + t_spend · G

Recipient side (uses nsec):

bscan   = (d_npub + t_scan)  mod n
bspend  = (d_npub + t_spend) mod n

By construction, bscan · G = Bscan and bspend · G = Bspend, and both sides arrive at the same (Bscan, Bspend) pair without any communication.

The tagged-hash input is the 32-byte x-only npub. The tagged hash provides strong domain separation between the two tweaks and against any other protocol that uses additive tweaks of npub.

Because npub is publicly known, both tweaks are publicly computable. The privacy of bscan and bspend rests entirely on the privacy of nsec: knowledge of bscan and npub trivially recovers d_npub = (bscan − t_scan) mod n, which is the BIP-340 signing key of the Nostr identity. The same property holds for bspend.

⚠️ bscan and bspend are NOT “view keys” — they are full identity-compromising secrets. Either one, combined with the user’s (publicly known) npub, lets an attacker recover nsec. They MUST NOT be uploaded to any third-party scanning service, hosted wallet, or remote indexer. See the Critical Security Warning at the top of this document and §9.1 for the full security model.

2.2 Edge cases

  • If t_scan = 0, t_spend = 0, bscan = 0, bspend = 0, or any derived scalar is ≥ n, the implementation MUST reject the derivation and surface an error. The probability of this is cryptographically negligible.
  • The change label m = 0 is always implicitly registered, per BIP-352. Recipients MUST scan for the change label.

3. Address Encoding

The silent-payment address is a standard BIP-352 address (Bech32m, HRP "sp" for mainnet, "tsp" for testnet/signet), with payload serP(Bscan) ‖ serP(Bspend) where serP is the 33-byte compressed SEC1 encoding. The address always starts with sp1q… (version 0).

Wallets MAY surface the encoded sp1q… string in their UI, but the npub-derived form is canonical: the address can always be recomputed from npub alone, and implementations SHOULD treat it as a derived view of the identity rather than a separately stored field.

3.1 Network scope

Implementations MUST NOT mix HRPs across networks within a single wallet session. The same nsec can be used to derive addresses for any network supported by BIP-352; the choice of HRP selects the network.

4. Sending

A sender follows the standard BIP-352 sending procedure. Given a recipient npub:

  1. Derive (Bscan, Bspend) from npub per §2.1. No profile lookup, relay query, or declaration event is required.
  2. Choose inputs from the sender’s wallet. All inputs MUST be of types permitted by BIP-352 (P2TR, P2WPKH, P2SH-P2WPKH, P2PKH). Outputs from SegWit version > 1 MUST NOT be spent in the same transaction.
  3. Compute the shared secret per BIP-352:
    a            = a₁ + a₂ + … + aₙ   (sum of input private keys, mod n)
    A            = a · G              (sum of input public keys)
    input_hash   = H_tagged("BIP0352/Inputs", outpointL ‖ A)
    shared       = input_hash · a · Bscan
    
  4. For each output to this recipient at index k (per BIP-352 output ordering rules):
    tₖ = H_tagged("BIP0352/SharedSecret", serP(shared) ‖ ser32(k))
    Pₖ = Bspend + tₖ · G            (no label)
        = Bspend + (tₖ + m) · G     (with label m)
    
  5. Place a P2TR output OP_1 <xonly(Pₖ)> in the transaction.
  6. Sign with SIGHASH_DEFAULT or SIGHASH_ALL. SIGHASH_ANYONECANPAY MUST NOT be used: the shared secret commits to the set of inputs and cannot be re-derived after input substitution.

Recipient capability. Every npub maps to a silent-payment address via §2.1, but the recipient can only spend incoming SP UTXOs if they have a wallet that implements this NIP. This NIP defines no capability signal; how a sender confirms recipient capability — and what they do when it is absent — is out of scope. Paying an SP address whose owner has no SP-aware wallet results in funds that are recoverable only once the recipient adopts one.

5. Receiving (BIP-352 Chain Scan)

The wallet computes bscan and bspend per §2.1 and performs the standard BIP-352 scan over the chain (or a relevant subset such as the last N blocks since the last scan checkpoint). For each candidate transaction:

  1. Identify eligible inputs (per BIP-352) and compute A = ΣAᵢ and input_hash.
  2. Compute shared = input_hash · bscan · A.
  3. For each Taproot output in the transaction, iterate k = 0, 1, … until no match:
    tₖ = H_tagged("BIP0352/SharedSecret", serP(shared) ‖ ser32(k))
    P_check = Bspend + tₖ · G
    If xonly(P_check) matches the Taproot output key:
      → unlabeled UTXO found at this output, store (txid, vout, value, tₖ, m=0)
    Else:
      candidate_label = xonly(output) − P_check
      If candidate_label matches a precomputed label (incl. the change label):
        → labeled UTXO found, store (txid, vout, value, tₖ, m)
    

This is the canonical receive path. A wallet that implements only this section is BIP-352-correct: it will discover every UTXO addressed to its npub-derived SP address. Part 2’s notification mechanism (§7) is purely an optimization layered over this.

5.1 Scanning architectures

⚠️ Because §2.1 is additive (not hardened), bscan carries the full sensitivity of nsec. Anyone given bscan and the user’s npub can compute nsec = (bscan − t_scan) (up to BIP-340 sign) and sign Nostr events as the user. This is true by construction and cannot be mitigated by trust assumptions about the service. Any architecture that ships bscan off the user’s device is therefore equivalent to publishing nsec and is prohibited by this NIP.

Two — and only two — scanning architectures are permitted:

  • Local scan (REQUIRED to support): the wallet ingests block data and runs the algorithm locally. No key material leaves the device. This is the default and the safest mode.
  • Tweak-data service (RECOMMENDED for clients with constrained bandwidth): an external service exposes only public per-transaction tweak data (e.g. input_hash · A) for BIP-352-eligible transactions. The wallet completes the ECDH locally using its private bscan. The service never receives bscan or any other private key material. Wallets choosing this mode MUST verify that the service protocol does not, at any point, ask for bscan.

A full scanning service — where the wallet uploads bscan to a third party that performs the scan and returns matched UTXOs — is PROHIBITED under this NIP, because disclosing bscan is mathematically equivalent to disclosing nsec (§9.1). Wallets MUST NOT offer such a flow against npub-derived keys, MUST NOT accept user configuration that points at such a service, and MUST reject any prompt (UI, NIP-46 bunker request, etc.) that would result in bscan being transmitted off-device.

Users who genuinely need a remote scanning service that ingests the scan key SHOULD use a separate BIP-352 wallet whose (bscan, bspend) are generated independently of any Nostr identity. NIP-SP is deliberately not the right tool for that workflow.

6. Spending

6.1 Output construction and signing chain

Each silent-payment UTXO is a P2TR output whose on-chain key Pₖ was constructed directly per BIP-352 — there is no BIP-341 internal key and no script tree. The full derivation chain from nsec to the spending scalar is:

─── stage 1: BIP-340 parity-normalize the Nostr key ──────────────────
  d_npub = nsec        if (nsec · G) has even y
         = n − nsec    otherwise

─── stage 2: additive spend-key derivation (§2.1) ────────────────────
  t_spend = H_tagged("nostr-sp/spend", npub) mod n
  bspend  = (d_npub + t_spend) mod n

─── stage 3: BIP-352 per-output tweak ────────────────────────────────
  dₖ = (bspend + tₖ + m) mod n

─── stage 4: BIP-340 parity-normalize the output key ─────────────────
  Pₖ      = dₖ · G
  d_sign  = dₖ            if Pₖ has even y
          = n − dₖ        otherwise

─── stage 5: sign ────────────────────────────────────────────────────
  BIP-340 Schnorr signature with d_sign over the BIP-341 sighash.
  NO further BIP-341 TapTweak is applied.

Exactly two parity corrections appear, both at well-defined points: stage 1 against nsec (the standard Nostr/BIP-340 normalization), and stage 4 against the output key (the standard Taproot key-path normalization). All additions in stages 2 and 3 operate on raw scalars mod n without further normalization.

Conformance MUSTs:

  • Implementations MUST NOT apply BIP-341 TapTweak when spending a NIP-SP output. The output key Pₖ is not an internal key.
  • Implementations MUST apply the stage-1 and stage-4 parity normalizations.
  • Implementations MUST verify xonly(dₖ · G) matches the on-chain output key before signing, as a guard against corrupted tweak data.

6.2 PSBT vocabulary

This NIP carries silent-payment metadata in BIP-174 proprietary fields (PSBT_IN_PROPRIETARY, key type 0xFC) under the identifier prefix "nostr_sp" (8 ASCII bytes). This is BIP-174-conformant and forward-compatible: any signer that does not recognize the prefix will ignore the fields per BIP-371’s extensibility clause.

Proprietary key encoding:

key   = 0xFC ‖ compact_size(8) ‖ "nostr_sp" ‖ <subtype> ‖ <subkey_data>
value = <subtype-specific bytes>

Defined subtypes:

Subtype Subkey Value Meaning
0x00 empty 2 bytes: <version 0x00><scheme 0x01> Marker. scheme = 0x01 ⇒ NIP-SP additive derivation (this NIP).
0x01 empty 32 bytes Per-output BIP-352 tweak tₖ.
0x02 empty 32 bytes Label scalar m. Absent ⇒ unlabeled (m = 0).
0x03 empty 32 bytes Expected on-chain output key xonly(Pₖ).

Conformance MUSTs and MUST NOTs at the input level:

  • An input carrying subtype 0x00 MUST also carry subtypes 0x01 and 0x03. Subtype 0x02 is conditional.
  • An input carrying subtype 0x00 MUST NOT carry PSBT_IN_TAP_INTERNAL_KEY (0x17).
  • An input carrying subtype 0x00 MUST NOT carry PSBT_IN_TAP_MERKLE_ROOT (0x18).
  • An input carrying subtype 0x00 MUST carry PSBT_IN_WITNESS_UTXO (0x01).
  • If PSBT_IN_SIGHASH_TYPE (0x03) is present, its value MUST be SIGHASH_DEFAULT (0x00) or SIGHASH_ALL (0x01).
  • After signing, the signer writes a 64- or 65-byte BIP-340 Schnorr signature into PSBT_IN_TAP_KEY_SIG (0x13), unchanged from BIP-371. The finalizer behavior for PSBT_IN_TAP_KEY_SIG is unchanged.

6.3 Signer behavior

A signer (whether local, NIP-07 extension, or NIP-46 bunker) that recognizes the "nostr_sp" prefix processes each marked input as follows:

for each input I in psbt:
    if I has nostr_sp[0x00] with scheme = 0x01:
        require I has WITNESS_UTXO
        require I has nostr_sp[0x01]
        require I has nostr_sp[0x03]
        require I does NOT have TAP_INTERNAL_KEY
        require I does NOT have TAP_MERKLE_ROOT
        require sighash ∈ {DEFAULT, ALL} or absent

        d_npub  = nsec if (nsec · G) has even y else n − nsec
        t_spend = H_tagged("nostr-sp/spend", npub) mod n
        bspend  = (d_npub + t_spend) mod n
        tₖ      = nostr_sp[0x01]
        m       = nostr_sp[0x02] if present else 0
        dₖ      = (bspend + tₖ + m) mod n

        // Guard: derived key must match expected output key
        if xonly(dₖ · G) ≠ nostr_sp[0x03]:
            abort signing with explicit error

        d_sign = dₖ if (dₖ · G) has even y else n − dₖ
        sig    = bip340_schnorr_sign(d_sign, taproot_sighash(psbt, I))
        write PSBT_IN_TAP_KEY_SIG = sig

Signers that do not recognize the prefix MUST NOT attempt to sign such inputs — they will leave the input unsigned, and finalization will fail in a recoverable way (the user can route the PSBT to a signer that does understand NIP-SP).

6.4 Migration to a future BIP-352 PSBT standard

A standardized PSBT vocabulary for BIP-352 is under discussion in the Bitcoin developer community but is not finalized at the time of writing. Once that standard exists, this NIP’s proprietary fields MAY be replaced by the standard equivalents in a future revision. Signers MAY accept either vocabulary during a transition window. Wallets producing PSBTs SHOULD emit only one form at a time, configurable per signer capability.


Part 2 — Nostr Integration: Notifications and UTXO Cache

This part defines two OPTIONAL Nostr event kinds that layer additional UX features on top of Part 1. Neither is required for correctness; a wallet that implements only Part 1 will still discover and spend all incoming silent-payment UTXOs via chain scanning.

  • Kind 8352 (§7) — a sender-to-recipient receipt notification. Lets the recipient credit a specific UTXO without waiting for a chain scan.
  • Kind 10353 (§8) — an encrypted self-published cache of the recipient’s own UTXO state. Enables cross-device sync and faster wallet recovery.

Both kinds use the recipient’s Nostr identity (the same npub that derives the SP address in Part 1) as the receiving / signing key.

7. Kind 8352 — Silent Payment Receipt Notification

Regular event used exclusively as the rumor inside a NIP-59 gift wrap. It MUST NOT be published directly to relays in the clear.

The kind number 8352 is 8000 + 352, encoding the BIP-352 base used throughout this NIP in the regular event range.

This rumor is a private, sender-to-recipient notification of the per-output tweak needed for the recipient to credit a silent-payment UTXO without performing a full chain scan.

{
  "kind": 8352,
  "pubkey": "<sender-pubkey>",
  "content": "",
  "tags": [
    ["i",      "bitcoin:tx:<txid>"],
    ["vout",   "<output-index>"],
    ["amount", "<sats>"],
    ["tweak",  "<32-byte hex>"],
    ["label",  "<32-byte hex>"],
    ["p",      "<recipient-pubkey>"],
    ["alt",    "Silent payment receipt: 50000 sats"]
  ]
}

7.1 Tags

Tag Required Description
i Yes NIP-73 identifier bitcoin:tx:<txid>, with <txid> lowercase hex.
vout Yes Output index in the referenced transaction (decimal integer, ≥ 0).
amount Yes Output value in satoshis (decimal integer).
tweak Yes Per-output BIP-352 tweak tₖ as 64-char lowercase hex.
label No Label scalar m as 64-char lowercase hex. Omit for unlabeled outputs.
p Yes Recipient pubkey. MUST match the gift-wrap recipient.
alt Yes NIP-31 human-readable fallback.

The content field SHOULD be an empty string. A future revision MAY permit a freeform message; for now, implementations SHOULD ignore it.

7.2 Sender behavior

After broadcasting a transaction that contains one or more silent-payment outputs (per §4), the sender MAY publish one kind 8352 rumor per output, each gift-wrapped per NIP-59 to the corresponding recipient pubkey. The tweak and label values are exactly the tₖ and m the sender computed when constructing the output.

Emitting notifications is OPTIONAL. The on-chain transaction is the source of truth; a missing notification cannot prevent the recipient from discovering the UTXO via §5.

7.3 Recipient validation

A wallet that supports this kind MAY use a validated notification to credit a UTXO before its next chain scan completes. For each incoming gift wrap:

  1. Decrypt the gift wrap per NIP-59.
  2. Validate the rumor structure (§7.1).
  3. Fetch the referenced transaction from a Bitcoin data source.
  4. Independently verify that output vout of the transaction pays Pₖ where:
    Pₖ = Bspend + (tweak + label) · G
    
    (label defaults to 0 if absent), and that xonly(Pₖ) equals the Taproot output key of tx.vout[vout].
  5. Verify that the output’s value matches the amount tag (within tolerance of one satoshi, in case of integer conversion drift; SHOULD be exact).
  6. If all checks pass, credit the UTXO to the wallet’s spendable set with (txid, vout, value, tweak, label).

A failed verification MUST NOT cause the wallet to credit a phantom UTXO. The notification is purely an optimization layered over the on-chain truth; wallets that support it SHOULD still run §5 periodically to backfill payments from senders who did not (or could not) emit notifications.

7.4 Spam considerations

Because gift wraps are unsolicited, an attacker can send arbitrary 8352 events to any pubkey. Wallets MUST treat the on-chain verification (§7.3 step 4) as the gate, not the existence of the notification. Implementations SHOULD rate-limit how aggressively they fetch Bitcoin data in response to unsolicited notifications to avoid being used as a DoS amplifier. Logging discarded notifications MAY help detect grief attacks.

8. Kind 10353 — Encrypted Silent Payment UTXO Set (OPTIONAL)

Replaceable event for the recipient’s own wallet state. One canonical event per identity. The visible tags array carries only public metadata; all UTXO state is carried in a NIP-44-encrypted tags array placed in content, following the pattern used by NIP-51 encrypted lists.

The kind number 10353 reflects: replaceable range (10000–19999) + an increment over the BIP-352 base used elsewhere in this NIP.

{
  "kind": 10353,
  "pubkey": "<recipient-pubkey>",
  "content": "<NIP-44 ciphertext of a JSON-encoded tags array>",
  "tags": [
    ["alt", "Encrypted silent payment UTXO set"]
  ]
}

8.1 Encryption

The content field is nip44_encrypt(plaintext, ownPubkey) where plaintext = JSON.stringify(<inner tags array>). Decryption is the inverse. Self-encryption uses the recipient’s own keypair on both sides.

8.2 Inner (encrypted) tag schema

After decryption, the plaintext is a JSON array of tags following the standard Nostr tag shape (each tag is an array of strings).

Tag Cardinality Description
scan_height Exactly one Block height through which scanning has been completed, as a decimal string.
utxo Zero or more One per spendable UTXO. See UTXO Tag below.

The set contains only spendable UTXOs. Implementations MUST NOT include spent UTXOs and MUST NOT carry a status flag. When a UTXO is spent, the wallet republishes the event with that utxo tag removed; absence from the set is the spent signal.

UTXO Tag

Format: ["utxo", "<txid>", "<vout>", "<value>", "<tweak>"] for unlabeled UTXOs, or ["utxo", "<txid>", "<vout>", "<value>", "<tweak>", "<label>"] for labeled UTXOs.

Index Description
0 Tag name: "utxo"
1 Transaction ID, 64-char lowercase hex
2 Output index, decimal string (≥ 0)
3 Output value in satoshis, decimal string
4 Per-output BIP-352 tweak tₖ, 64-char lowercase hex
5 Label scalar m, 64-char lowercase hex. Omit for unlabeled outputs.

Example decrypted plaintext:

[
  ["scan_height", "845231"],
  ["utxo", "abc123…", "2", "50000", "deadbeef…", "001f00…"],
  ["utxo", "def456…", "0", "12000", "cafebabe…"]
]

8.3 Recovery and persistence

The event is purely a wallet-state cache. Loss of this event MUST NOT cause loss of funds — the wallet can always be reconstructed by performing a fresh chain scan per §5. Wallets SHOULD also keep the UTXO set in local persistent storage and use this event primarily for cross-device sync or recovery.


9. Security Considerations

9.1 Scan- or spend-key disclosure equals nsec disclosure

§2.1 derives bscan and bspend via public additive tweaks of nsec. The tweaks t_scan = H_tagged("nostr-sp/scan", npub) and t_spend = H_tagged("nostr-sp/spend", npub) are computable by anyone who knows npub (which is, by definition, public).

The full recovery, given a leaked bscan and the target npub:

t_scan  = H_tagged("nostr-sp/scan", npub) mod n
d_npub  = (bscan − t_scan) mod n             ← BIP-340 signing key
nsec    = d_npub  or  n − d_npub             ← original raw nsec (one of two parities)

d_npub is already sufficient to sign arbitrary Nostr events as the user (BIP-340 only ever uses the even-y normalization). The same procedure recovers d_npub from a leaked bspend using t_spend instead. Both keys are therefore identity-compromising secrets, equal in sensitivity to nsec itself. There is no cryptographic mitigation — the property is intrinsic to additive derivation and is the explicit trade-off this NIP makes in exchange for letting senders derive addresses from npub alone.

Operationally, this means:

  • bscan and bspend MUST be treated with exactly the same care as nsec. They MUST NOT be transmitted to, stored on, or processed by any third party.
  • Remote “full scanning services” — where the user uploads bscan and receives matched UTXOs — are PROHIBITED by this NIP (§5.1). Implementations MUST NOT offer such a flow, MUST NOT accept user configuration that enables it, and MUST refuse NIP-07/NIP-46 requests that would export bscan or bspend to a remote endpoint.
  • The “tweak-data” scanning architecture (the service exposes only public per-transaction inputs; the wallet does the ECDH locally) IS supported and is the recommended way to reduce client-side scanning load.
  • Backup and key-export UI MUST display the same warnings for bscan and bspend as it does for nsec.

Users who want a remote scanner SHOULD instead use a separate BIP-352 wallet whose (bscan, bspend) are not derived from a Nostr identity. The trade-off this NIP makes — sender-side ergonomics over scan-key delegation — is deliberate; users with the opposite preference should not use NIP-SP.

9.2 Notification authenticity

A NIP-59 gift wrap authenticates the sender’s signing pubkey but does not authenticate that the sender actually made the on-chain payment. A malicious sender could send a notification referencing a transaction made by someone else, or a transaction that does not pay the recipient at all. The on-chain verification step (§7.3) is the gate; the notification merely points the wallet at where to look. Wallets MUST NOT trust notification metadata without on-chain verification.

9.3 Sighash discipline

Per BIP-352, transactions paying silent-payment outputs MUST be signed with SIGHASH_DEFAULT or SIGHASH_ALL. ANYONECANPAY breaks the shared-secret derivation. Spending transactions (from silent-payment UTXOs) inherit the same constraint when they themselves contain silent-payment outputs (e.g. change paid to the change label). Wallets SHOULD apply this discipline uniformly.

9.4 Coin selection and on-chain linkage

Consolidating multiple silent-payment UTXOs in a single spending transaction links them on-chain as belonging to the same recipient, partially negating the per-payment privacy that BIP-352 grants on the receiving side. Wallets SHOULD support per-payment spends or, where consolidation is necessary, surface the privacy trade-off to the user.

9.5 Change handling

A spend transaction SHOULD route its change to its own silent-payment address using the BIP-352 change label (m = 0). The wallet will recover its own change on the next scan and will not need any special storage for it. Routing change to any non-SP address controlled by the user is permitted but creates a chain-analysis link between that address and the silent-payment cluster, partially negating the privacy benefit.

9.6 Forward secrecy of NIP-44 ciphertext

The kind 10353 UTXO cache is encrypted with NIP-44, which inherits NIP-44’s threat model: a future compromise of nsec retroactively decrypts all prior events. Wallets that want stronger forward secrecy for the UTXO cache SHOULD use only local storage and skip kind 10353 entirely.

10. Backwards Compatibility

This NIP is purely additive. It defines a new derivation, a new address format use, and two new optional Nostr event kinds. It does not modify or depend on any existing Nostr event kind, address derivation, or wallet behavior.

Because the silent-payment address is publicly derivable from npub, no out-of-band capability negotiation or declaration event is required. Wallets that do not implement Part 1 simply will not scan for and credit incoming SP payments to their derived address until they upgrade.

Wallets that implement Part 1 but not Part 2 remain fully BIP-352-correct: they will discover every UTXO through chain scanning. Part 2 only affects latency-of-credit (kind 8352) and cross-device convenience (kind 10353).

11. Test Vectors

Status: placeholders. To be filled in once a reference implementation lands. Each vector should include nsec, the corresponding npub, the derived (t_scan, t_spend, bscan, bspend, Bscan, Bspend), the encoded sp1q… address, and for at least one example transaction: the inputs, the per-output tweak tₖ, the derived dₖ, the resulting Taproot output key, and a valid Schnorr signature spending it.

Part 1:

TODO: additive derivation vector (npub → t_scan, t_spend, Bscan, Bspend)
TODO: recipient derivation vector (nsec → d_npub → bscan, bspend; verify matches sender side)
TODO: address-encoding vector
TODO: send-side vector (build tx given only the recipient npub)
TODO: receive-side vector (scan match given block data)
TODO: spend-side vector (PSBT roundtrip)

Part 2:

TODO: kind 8352 vector (sender-side rumor + gift-wrap; recipient validates and credits)
TODO: kind 10353 vector (encrypt/decrypt roundtrip of a sample UTXO set)

12. References


Looking for comments…

Searching Nostr relays. This may take a moment the first time this article is opened.