Overview
Nyx aims to bring privacy to Ethereum users with minimum friction and trust.
It helps users bridge and manage assets between their public and private accounts.
At a high level, accessing a user’s Nyx account requires both their Ethereum wallet and passkey.
The Nyx backend helps users use Nyx across devices and browsers, while remaining completely agnostic to users’ asset and transaction information.
Read below to learn the details.
Public account
The public account on Nyx is an Ethereum account.
Users start by simply connecting their existing Ethereum wallet, be it an in-browser wallet, a hardware wallet, an MPC wallet, or a WalletConnect-compatible mobile wallet.
As a result, anything happening on the public account is visible to the world, just like any other Ethereum account.
Private account
The private account on Nyx is powered by Aztec, a privacy-first L2 on Ethereum.
Aztec provides the foundation to build verifiable smart contracts with private state, while leveraging the decentralized security of Ethereum for the overall soundness of the network state.
For more details on Aztec, please see Aztec Overview.
Governance
Aztec has native account abstraction, which allows arbitrary transaction authorization logic.
The Nyx private account is a special Aztec account that authorizes transactions through EIP-712 typed data signatures from the user’s public account.
Each Aztec account is also associated with a set of privacy keys that deal with encrypting and nullifying private notes.
The Nyx private account derives its privacy keys from an account secret, which is generated on the client side during provisioning.
The Nyx backend stores an encrypted copy of the account secret, which can only be decrypted on the user’s device.
Read more in the Backend section below.
In summary, the Nyx private account is derived from the public account connected by the user, plus an account secret.
In order to decrypt and view the private account state, the account secret is required.
On top of that, to send a transaction from the Nyx private account, a valid message signature from the user’s connected Ethereum wallet is also required.
Privacy
At a high level, all of the following transaction data are hidden from the world:
- Sender address.
- Private function calls.
- Private state changes.
For instance, in a simple transaction where Alice privately sends Bob 1 USDC, only Alice and Bob would know what happened.
The world only sees someone sent a transaction that nullified some encrypted notes and created some new encrypted notes.
This is achieved through client-side execution and proving inside the Aztec PXE.
Aztec also supports public functions and state, but we won’t go into details here as it does not apply to Nyx operations.
Backend
The Nyx backend exists to help users manage and sync their account secret across devices, among other off-chain state that are needed to operate their Nyx account.
It does this while remaining completely agnostic to any sensitive user data.
In particular, it never sees any of the following user data:
- Public account address.
- Private account address.
- Private account state.
- Account secret.
This is achieved through a combination of zero-knowledge proofs and end-to-end encryption, which we’ll explore more below.
Wallet ID
To maintain off-chain state for Nyx users, every connected public account is associated with a Nyx wallet ID, which is the Poseidon hash of the public account address.
By nature of the hash function, the Nyx backend cannot deduce the actual public account address from this wallet ID.
Ownership proof
In order to access data belonging to a Nyx wallet ID, the user needs to first authenticate with the Nyx backend.
This involves signing a one-time message using their connected Ethereum wallet, which proves ownership of the public account and thus its derived Nyx wallet ID.
However, instead of directly sending over the signature, which would leak the user’s public account address to the Nyx backend, a zero-knowledge proof is generated.
This proof proves the existence of the valid signature and links it to the Nyx wallet ID, without leaking the actual signature nor the address.
Wallet encryption key
Each Nyx wallet has an associated encryption key, which is used to encrypt any sensitive data before they leave the user’s device.
This includes the account secret, the contact book, and any other data that are required for Nyx operations but may leak the user’s private account state or activities.
The Nyx backend will only ever see the ciphertexts of such data.
The wallet encryption key is generated on the client side when provisioning the user’s private account for the first time, and never leaves the user’s device in plaintext.
WebAuthn credentials
During the provisioning of a Nyx private account, the user must also enroll a WebAuthn credential, or passkey.
Nyx requires passkeys that support the PRF extension, which includes many popular providers such as
- YubiKey
- Ledger Security Key app
- Apple Passwords
- Google Password Manager
- 1Password
- …
The passkey is used to encrypt the wallet encryption key before the ciphertext is sent to the Nyx backend for backup.
The key material is derived from the PRF evaluation result of the passkey, which is never persisted nor transmitted.
Thus the passkey must be present for decryption.
Users are strongly encouraged to enroll multiple passkeys to ensure continued
access to their Nyx private account in case of a passkey loss, because the Nyx
team has no way of recovering it.
Because Ledger Security Key app is a supported passkey option, Ledger users
can choose to consolidate all of their Nyx account access control on a single
Ledger device (recoverable from a single seed phrase).
Sample access flows
We include some sample flows to help illustrate how the various pieces fit together when accessing a Nyx private account.
Unlock private account
The goal of unlocking the private account is to gather all necessary information for Aztec PXE, running inside the Nyx frontend, to be able to read their private state, and to execute and prove transactions from the user’s private account.
Send private transaction
Once the private account has been unlocked, each transaction from it requires sign-off from the user’s connected Ethereum wallet just like transactions from their public account.