Skip to content

Conversation

@a1denvalu3
Copy link
Contributor

@a1denvalu3 a1denvalu3 commented Nov 4, 2025

Pay-to-Blinded-Key (P2BK) Implementation for Enhanced Privacy

Overview

This PR implements NUT-26: Pay-to-Blinded-Key, a privacy enhancement for P2PK (NUT-11) transactions that enables "silent payments" in Cashu. P2BK allows tokens to be locked to a public key without exposing which public key they're locked to, even to the mint itself.

Key Features

  • Enhanced Privacy: Tokens can be sent to recipients without the mint learning the recipient's public key
  • Canonical Slot Mapping: Supports multi-key proofs with proper slot organization
  • Backward Compatible: Works with existing mints without requiring protocol changes on the mint side

Technical Implementation

  • ECDH Key Derivation: Uses Elliptic Curve Diffie-Hellman to derive shared secrets between sender and receiver
  • Blinding Operations: Implements cryptographic blinding of public keys using random scalar multiplication
  • Key Recovery: Enables receivers to recover the correct signing key through the shared ECDH secret
  • Validation: Includes comprehensive tests for key derivation, blinding, and signing operations

User-Facing Changes

  • Added use_p2bk option to the wallet's send operations to toggle P2BK functionality
  • When enabled, all P2PK transactions will use blinded keys for enhanced privacy

Checklist

@a1denvalu3 a1denvalu3 marked this pull request as ready for review November 5, 2025 18:07
@a1denvalu3 a1denvalu3 marked this pull request as draft November 6, 2025 07:28
@a1denvalu3 a1denvalu3 marked this pull request as ready for review November 6, 2025 17:15
Copy link
Collaborator

@thesimplekid thesimplekid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice just noticed one thing.

@thesimplekid thesimplekid added this to the 0.15.0 milestone Nov 17, 2025
@a1denvalu3 a1denvalu3 force-pushed the blinded-p2pk branch 2 times, most recently from 79b207d to d00be74 Compare December 30, 2025 09:53
@thesimplekid thesimplekid added new nut This PR is held pending the merge of a new or updated NUT needs rebase labels Jan 11, 2026
@robwoodgate
Copy link

robwoodgate commented Jan 12, 2026

Please note: keyset id has now been removed from the blinding factor calculation in the NUT spec.
Is also now tentatively renamed NUT-28, as BECH32 PR was merged first.

fix and format

fix for ffi crate

align r_i derivation

database migrations and crud update for `p2pk_e`

strip p2pk_e at the exit door

fix tests

fix typo

use p2bk for receiving

remove unused import

fix for SIG_ALL

changes to payment request

remove useless field

Fix NUT-26 Pay-to-Blinded-Key implementation issues

This commit fixes several issues in the NUT-26 implementation:
1. Resolved type mismatches with XOnlyPublicKey handling
2. Fixed scalar operations by using proper methods instead of direct operations
3. Implemented proper key negation for BIP-340 compatibility
4. Added P2BK support to the wallet's send options
5. Added integration test for P2BK ECDH key derivation

The changes enable private 'silent payments' through blinded key operations
that enhance privacy by preventing the mint from knowing the actual recipient.

Implement NUT-26 Pay-to-Blinded-Key (P2BK) enhancements

- Fixed ephemeral key handling to properly respect SIG_ALL flag
  - Use shared ephemeral key for all proofs when SIG_ALL is present
  - Use per-proof ephemeral keys when SIG_ALL is not present
- Implemented blinding for all types of public keys in conditions:
  - Primary public key (slot 0)
  - Additional pubkeys (slots 1 to N)
  - Refund keys (slots N+1 to 10)
- Added unit tests for nut26 core functions
- Added nut26 support to payment_request implementations

tests

format

try a fix

format

clippy

format

fix t vectors tests

send: extract p2bk application from confirm function

import parity -> strict documentation check

connect to cdk-cli

format

remove apply blinding from send

correct blinding of outputs pubkeys (not inputs) to a transaction

There is a bug I can't find

fixed the bug

clippy

more clippy + test fix

allow HTLC to be blinded as well

clippy

fix slot assignment

feature wallet on tests

remove nut26 flag from payment request, as per spec update.

format

remove default trait

add missing p2pk_e

add more missing `p2pk_e`s

use_p2bk flag

rename to 28
description: Option<String>,
transports: Vec<Transport>,
nut10: Option<Nut10SecretRequest>,
nut28: Option<bool>,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Payment request support has been removed from the spec for now

let mut engine = Sha256::engine();
engine.input(b"Cashu_P2BK_v1");
engine.input(&z_x);
engine.input(&keyset_id.to_bytes());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keyset_id was removed in latest spec

@ye0man ye0man added this to CDK Jan 15, 2026
@github-project-automation github-project-automation bot moved this to Backlog in CDK Jan 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs rebase new nut This PR is held pending the merge of a new or updated NUT

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants