Encrypted Balances
A detailed technical guide to how Umbra securely stores, updates, and decrypts token balances on Solana using PDAs, MPC, and modern cryptography.
The Umbra protocol is designed to provide end-to-end financial privacy, which requires not only unlinkable transfers but also confidentiality of account balances. Unlike standard wallets that store balances as public, readable numbers on-chain, Umbra treats all user balances as encrypted secrets.
This document provides a detailed overview of the architecture and cryptographic mechanisms that enable Umbra to store, update, and decrypt token balances privately, securely, and in a way that is always recoverable by the user.
The Challenge: Storing Private Data on a Public Chain
Storing a user's balance on a public blockchain presents three fundamental challenges that Umbra's architecture is designed to solve:
- Confidentiality: How can a balance be stored on a public ledger without allowing network validators, block explorers, or any third party to read it?
- Confidential State Updates: How can this balance be modified (e.g., adding funds from a deposit or subtracting for a transfer) without revealing the original amount, the final amount, or the amount of the change?
- Decentralized Recoverability: How can a user find and regain control of their encrypted balances if they restore their wallet on a new device, without relying on a centralized server to map their identity to their on-chain data?
Umbra solves these challenges through a combination of a dual-key architecture, deterministic on-chain storage, and a privacy-preserving computation network.
Key Architecture: Separating Spending and Encryption
To ensure maximum security and adhere to cryptographic best practices, an Umbra wallet's identity is managed by two distinct, specialized cryptographic keypairs. This follows the principle of separation of concerns, ensuring that the keys used for transaction authorization are separate from the keys used for confidentiality.
The Spending Key (Ed25519)
This is the authorization layer. The Ed25519 keypair is the standard for Solana wallets and is used exclusively for signing transactions.
- Purpose: To provide non-repudiable proof of ownership and to authorize the movement of funds or state changes.
- Role: When a user initiates a private transfer, their Ed25519 key is used to sign the transaction, proving they have the authority to do so. This is the key that interacts with the Solana runtime's signature verification logic.
- Security: This key is never used for encryption or key agreement, ensuring its sole purpose remains secure and auditable in the context of transaction signing.
The Encryption Key (X25519)
This is the confidentiality layer. The X25519 keypair is the industry standard for high-speed elliptic-curve Diffie-Hellman (ECDH) key exchange.
- Purpose: To establish secure, ephemeral shared secrets with other parties (like the MPC network) for encrypting and decrypting data.
- Role: This key's public component is used as a seed to derive the deterministic addresses for on-chain storage. Its private component is used to compute the symmetric keys needed to decrypt a user's balance. It never signs transactions.
- Security: By separating this from the spending key, Umbra ensures that the mechanisms for proving ownership are cryptographically distinct from the mechanisms for ensuring privacy.
On-Chain Storage: Deterministic Program-Derived Addresses (PDAs)
Umbra solves the problem of decentralized and recoverable storage using Solana's Program-Derived Addresses (PDAs).
A PDA is a Solana account whose address is not generated from a private key but is instead deterministically "derived" from a set of public seeds (such as strings or public keys) and a program ID. This allows a smart contract to programmatically sign for and control an account without needing to store a private key.
Why PDAs for Privacy? PDAs are ideal for private storage because they are deterministic. A user does not need to store a list of random addresses for each of their private balances. As long as they possess their wallet's keys, they can always re-calculate the exact PDA where their encrypted balance is stored. This design completely solves the wallet recovery problem without relying on a centralized indexer or database.
Umbra uses a hierarchy of PDAs, derived from the user's public keys:
- User Account PDA: A top-level account derived from a user's public key. It acts as a primary, on-chain anchor for a user's Umbra identity.
- Encrypted Token Balance PDA: A separate PDA for each token a user holds privately, derived from the user's public key and the token's mint address. This PDA stores the actual encrypted balance data for that specific token.
The Encryption Scheme: How Balances are Stored
Each Encrypted Token Balance PDA stores the user's balance as a ciphertext generated by the Rescue cipher.
Why the Rescue Cipher? Rescue is a modern, arithmetization-oriented cipher. It is designed to be highly efficient within two key cryptographic contexts:
- Zero-Knowledge Proofs: It has a low number of multiplicative constraints, making it fast and cheap to use inside ZK-SNARK circuits, a crucial feature for other parts of the Umbra protocol.
- Multi-Party Computation (MPC): Its simple algebraic structure is also highly optimized for MPC. Performing computations on secret-shared data is much more efficient with a cipher like Rescue compared to traditional ciphers like AES. This is crucial for enabling performant, secure state updates by the MPC network.
The on-chain PDA stores two pieces of information:
Component | Size | Purpose |
---|---|---|
Ciphertext | 32 bytes | The encrypted token amount, appearing as indistinguishable random data. |
Nonce | 16 bytes | A unique, one-time number used for each encryption operation. |
The Importance of the Nonce A nonce ("number used once") is critical for achieving semantic security (IND-CPA). It ensures that if you encrypt the same balance value multiple times, the resulting ciphertext will be different each time. This prevents on-chain observers from identifying patterns by looking for repeated ciphertexts, which could otherwise be used to leak information about user balances or activities.
The Decryption Process: Client-Side and Secure
Decryption always happens locally on the user's device (e.g., in their browser or mobile wallet). No private keys or unencrypted balances are ever transmitted over a network. The process relies on the Elliptic-Curve Diffie-Hellman (ECDH) key exchange protocol.
Steps:
- Fetch Data: The user's wallet fetches the pair from the relevant on-chain Token Balance PDA.
- Derive Shared Secret: The wallet performs an ECDH key exchange using its own X25519 private key and the MPC network's public key . This produces a shared secret, , known only to the user and the decentralized MPC network.
- Initialize Cipher: The wallet uses this shared secret and the fetched to initialize the Rescue cipher state and derive the symmetric decryption key.
- Decrypt Locally: The wallet decrypts the using the initialized cipher to reveal the plaintext token balance.
State Updates: Privacy-Preserving Math with MPC
To solve the challenge of confidential state updates, Umbra utilizes a threshold Multi-Party Computation (MPC) network. MPC is a subfield of cryptography that allows a group of computers to jointly compute a function over their inputs without any individual computer ever seeing the raw data of others.
How it Works in Umbra: When a user's balance needs to be updated (e.g., adding funds from a claim), the operation is performed homomorphically on the ciphertexts.
- The user's wallet sends an encrypted instruction (e.g., an encrypted representation of ) to the MPC network.
- The MPC nodes fetch the current from the target PDA.
- Using their respective secret shares, the nodes collectively perform a secure computation that effectively "adds" the new encrypted value to the existing ciphertext. This produces a new ciphertext for the updated balance. This entire process is done "in the dark"—the MPC nodes never learn the original balance, the change in balance, or the final balance.
- The new and a fresh are written back to the PDA.
Threshold Security: The system is designed to be secure and live even if some of the MPC nodes are malicious or offline. A certain number of nodes (the "threshold") must cooperate to perform the computation. As long as fewer than this threshold of nodes are compromised, the system's security and privacy remain intact.
Security Guarantees
Property | Guarantee |
---|---|
On-Chain Privacy | Balances are stored as semantically secure ciphertexts, appearing as random data. |
Recoverability | Deterministic PDAs allow users to recover all balances with just their main wallet keys. |
Confidential Updates | The MPC network enables balance updates without ever decrypting state on a server. |
Threshold Security | No single MPC node has enough information to compromise a user's balance. |
Replay Resistance | A unique nonce for each encryption prevents replay attacks and pattern analysis. |
Separation of Duties | Ed25519 keys handle authorization, while X25519 keys handle confidentiality. |
For further details on the underlying cryptographic primitives, please see our dedicated cryptography documentation.
Deep Dive into the Cryptography
Explore the technical implementation details starting with master seed generation and cryptographic foundations