Wraith Protocol: Stealth Address Payments on CKB

We just shipped stealth address support for CKB as part of Wraith Protocol, a multichain privacy layer for blockchain payments. Wanted to share what we built and how it works on Nervos.

What are stealth addresses?

Every time someone pays you, a fresh one-time address is generated just for that transaction. The sender uses your public stealth meta-address and elliptic curve math to derive an address that only you can detect and spend from. On-chain, it looks like a transfer to a random new account. There is no link between your identity and the payment.

No mixers. No zero-knowledge circuits. Just ECDH shared secrets and point addition on secp256k1, the same curve CKB already uses.

How it works on CKB

CKB’s Cell model turned out to be a natural fit for stealth addresses. On EVM chains, we need a separate announcer contract to emit events that recipients scan. On CKB, the Cell itself is the announcement.

Here is the flow:

Sending a payment:

  1. Sender takes the recipient’s stealth meta-address (two compressed secp256k1 public keys)

  2. Generates a random ephemeral keypair

  3. Computes an ECDH shared secret with the recipient’s viewing key

  4. Derives a one-time stealth public key via point addition

  5. Creates a Cell with our wraith-stealth-lock script. The lock args are 53 bytes: the ephemeral public key (33 bytes) concatenated with the blake160 hash of the stealth public key (20 bytes)

That is it. The Cell stores the payment amount as capacity, and the lock args carry everything the recipient needs to find it. No separate announcement transaction.

Receiving payments:

  1. Recipient queries all live Cells with the wraith-stealth-lock code hash using CKB’s get_cells RPC

  2. For each Cell, extracts the ephemeral public key from the first 33 bytes of the lock args

  3. Computes the ECDH shared secret using their viewing key

  4. Derives the expected stealth public key

  5. Compares blake160 of the expected key with the last 20 bytes of the lock args

  6. If they match, the Cell belongs to them

Spending:

The recipient derives the stealth private key (spending_key + SHA256(shared_secret) mod n) and signs a transaction consuming the Cell. The wraith-stealth-lock script delegates signature verification to ckb-auth via exec_cell.

What we deployed

wraith-stealth-lock is live on CKB testnet:

  • Code hash: 0x31f6ab9c7e7a26ecba980b838ac3b5bd6c3a2f1b945e75b7cf7e6a46cb19cb87

  • Cell dep tx: 0xde1e8e4bed2d1d7102b9ad3d7a74925ace007800ae49498f9c374cb4968dd32b, index 0

wraith-names-type is also live, providing .wraith name registration on CKB:

  • Code hash: 0xc133817d433f72ea16a2404adaf961524e9572c8378829a21968710d6182e20d

  • Cell dep tx: 0x9acd640d35eadd893b358dddd415f4061fe81cb249e8ace51a866fee314141b8, index 0

Names work as Cells with a type script. The type args contain the blake2b hash of the name, the Cell data holds the 66-byte meta-address, and the lock script proves ownership. No signature scheme needed for ownership verification because CKB’s Cell model handles it natively. Only the owner can consume the Cell.

SDK support

CKB is fully supported in the Wraith SDK, published on npm as @wraith-protocol/sdk. Install it and import from the CKB chain module:


npm install @wraith-protocol/sdk


import {

deriveStealthKeys,

generateStealthAddress,

scanStealthCells,

fetchStealthCells,

encodeStealthMetaAddress,

hashName,

buildRegisterName,

buildResolveName,

STEALTH_SIGNING_MESSAGE,

} from '@wraith-protocol/sdk/chains/ckb';

// Derive stealth keys from a wallet signature

const keys = deriveStealthKeys(signature);

const metaAddress = encodeStealthMetaAddress(keys.spendingPubKey, keys.viewingPubKey);

// Generate a stealth address for someone

const stealth = generateStealthAddress(recipientSpendPub, recipientViewPub);

// stealth.lockArgs = 53-byte args for the wraith-stealth-lock Cell

// Scan for incoming payments

const cells = await fetchStealthCells('ckb');

const mine = scanStealthCells(cells, keys.viewingKey, keys.spendingPubKey, keys.spendingKey);

// Register a .wraith name

const nameData = buildRegisterName({

name: 'alice',

spendingPubKey: keys.spendingPubKey,

viewingPubKey: keys.viewingPubKey,

});

The SDK handles all the cryptography. Developers just call functions and get back the data they need to build CKB transactions.

Demo

The demo app at demo.usewraith.xyz supports CKB with wallet connection via the CCC connector (JoyID, OKX, UniSat, MetaMask). You can switch to CKB in the chain dropdown, connect your wallet, and send stealth payments directly.

The minimum Cell capacity for a stealth-lock Cell is about 95 CKB due to the 53-byte args.

Why CKB was interesting to integrate

A few things stood out:

The Cell model eliminates the announcer pattern. On EVM and Solana, we need a separate contract that emits events so recipients can scan for payments. On CKB, the payment Cell carries the announcement data in its lock args. One transaction does everything.

Ownership is native. On EVM, our WraithNames contract needs on-chain secp256k1 signature verification with point decompression to prove name ownership. On CKB, the lock script handles ownership. If you can spend the Cell, you own the name. No custom signature verification needed in the names type script.

The get_cells RPC is a built-in indexer. We can filter by lock script code hash to find all stealth Cells without deploying a separate subgraph or indexer. On EVM chains, we use Goldsky subgraphs. On Stellar, we query Soroban RPC events. On CKB, the node does it natively.

Same curve, different hashing. CKB uses secp256k1 like EVM but with blake2b (personalized with “ckb-default-hash”) instead of keccak256 for address derivation, and SHA-256 instead of keccak256 for the shared secret hash. The elliptic curve math is identical, which let us reuse most of the EVM crypto module.

What is Wraith Protocol

Wraith is a multichain stealth address protocol with an AI agent platform. The SDK supports EVM chains (Horizen), Stellar, Solana, and now CKB. Smart contracts are deployed on all four chain families.

Beyond the SDK, we run an AI agent platform inside Phala TEE hardware. Agents get their own wallets, stealth identities, and .wraith names, then handle payments through natural language. Keys are derived inside Intel TDX enclaves and never stored.

Everything is open source under MIT license.

Links

Would love feedback from the CKB community. If anyone wants to try sending stealth payments on testnet or has questions about the integration, drop a comment.

11 Likes