xCIPHR NFT structure.
The xCIPHR is the credential, an NFT on the XRP Ledger that anchors your encrypted identity. The NFT carries only a compact reference: an encrypted backup of your device-held master key lives off-chain in content-addressed storage, and the NFT URI points to it by content hash. It's immutable, public, and useless to anyone without your device, your iCloud, or your recovery code.
What's actually on the ledger.
An XRPL NFT URI is capped at 256 bytes, far too small for an encrypted seed envelope. So the NFT stores a reference instead: a scheme, a content identifier, and an integrity hash.
Scheme
sciphr:v5 declares the credential format, so wallets know how to resolve and (on your device) open the backup.
CID
A content identifier addressing the envelope in IPFS. Because it's content-addressed, the CID is the content's fingerprint, you can't swap the file without changing the CID.
Hash
A SHA-256 of the envelope, pinned in the URI. Your device verifies it before trusting a fetched envelope, tamper-evidence, on-chain.
Why the NFT stores only a reference
Anchoring by hash keeps the on-chain footprint tiny and immutable while the envelope can live anywhere content-addressed. The ledger guarantees which envelope is yours; the storage layer just holds the bytes. The anchor is a tamper-evident provenance pointer, it proves which backup belongs to your identity, and grants no one the ability to open it.
Click any field.
This is the off-chain envelope the CID resolves to, your master key, sealed with AES-256-GCM, plus the Wallet Backup Key wrapped three independent ways. The sealed master key is sciphrtext 1; each wrapped backup key is a sciphrtext 2. Select a highlighted field to see what it holds, and read Two layers, one secret below for why this is safe.
{ "version": 5, "suite": "AES_256_GCM_WBK_V5", "custodyModel": "xrpl_native_self_custody", "walletAddress": "rhVDMMzr8Xm5…", "walletPublicKey": "ED9434…", "master": { "algorithm": "AES-256-GCM", "nonce": "a3f5c2d8e9b1…", "ciphertext": "U2FsdGVkX1+…base64…" }, "recoverySigner": { "algorithm":"AES-256-GCM", "nonce":"7c1e9a…", "ciphertext":"Qm9k…base64…" }, "wraps": [ { "type": "secure_enclave", "algorithm":"ECIES-P256-X963-SHA256-AESGCM", "ciphertext":"BPx9…" }, { "type": "icloud_keychain", "algorithm":"iCloud-Keychain+AES-256-GCM", "ciphertext":"Aa72…" }, { "type": "recovery_code_argon2id", "algorithm":"Argon2id+AES-256-GCM", "kdf":{"m":4096,"t":3,"p":1}, "ciphertext":"Lp3m…" } ], "createdAt": "2026-06-01T00:00:00Z", "recoveryPolicy": { "signerQuorum":2, "sciphrSignerWeight":1, "disableMasterKeyDefault":false } }
› Select a field to inspect
master.ciphertext
sciphrtext 1 · sealed master key
Your wallet's master key, encrypted with AES-256-GCM under a one-time Wallet Backup Key. Without that key, which only your device, your iCloud, or your recovery code can unwrap, it is irreversible noise.
Why there are two sciphrtexts.
The envelope splits one hard problem into two easy ones. Your master key is encrypted once, and the key that opens it is protected many ways. We name the two encrypted layers sciphrtext 1 and sciphrtext 2. It's the same envelope-encryption pattern hardware security modules and modern messengers rely on, given a name.
Your XRPL master key, sealed with AES-256-GCM under a one-time, random 256-bit Wallet Backup Key. This is the only copy of the secret, and it is pure sciphrtext. Published to the whole world it stays sealed, because the key that opens it is never stored beside it and never reaches SciPHR.
The Wallet Backup Key itself, wrapped three independent ways, your Secure Enclave, your iCloud Keychain, and your recovery code. Each wrap is its own sciphrtext, and any one of them restores the key. That key then opens sciphrtext 1. Three doors to one key, all of them yours.
Why seal the secret only once
Encrypting the master key separately for each recovery path would put three copies of the actual secret on-chain, and the security would only ever be as strong as the weakest path. Sealing it once under a random 256-bit key keeps the secret's exposure as small as it can be, while the recovery redundancy lives where it is cheap and safe, on the small key.
Why one sciphrtext is safe
sciphrtext 1 is sealed with AES-256-GCM, an authenticated cipher, under a 256-bit key used exactly once with a fresh 96-bit nonce. Brute-forcing a 256-bit key is physically infeasible, the authentication tag makes any tampering fail loudly, and the integrity hash anchored in the NFT proves the bytes are unchanged. The envelope itself is public, hash-anchored in your NFT, and replicated across content-addressed storage, so it is not something you can quietly lose, and your XRPL signer-list quorum is enforced on-chain, independent of any single key. One sciphrtext is the smallest possible exposure for the one thing that must stay secret.
Every key in the envelope.
| Key | Holds | Why it's safe to publish |
|---|---|---|
| version / suite | Envelope format (5) and cipher suite (AES_256_GCM_WBK_V5). | Metadata only, lets resolvers recognize and parse the envelope. Legacy V2/V3/V4 envelopes are rejected outright. |
| custodyModel | Declares XRPL-native self-custody (xrpl_native_self_custody). | A public statement of design; SciPHR holds no key that opens this. |
| walletAddress / walletPublicKey | Your public XRPL address and the Ed25519 public key of the master wallet. | Public by definition; the matching private key never leaves your device. |
| master.algorithm | The seal cipher, AES-256-GCM. | Naming an algorithm reveals nothing; the security is in the keys. |
| master.ciphertext | Your master key, AES-256-GCM-encrypted under the Wallet Backup Key. | Irreversible without the WBK, which only your device, iCloud, or recovery code can unwrap. |
| master.nonce | 96-bit nonce for the master seal; the 128-bit GCM auth tag is appended to the sciphrtext. | Public by design, uniqueness and tamper-evidence; useless alone. |
| recoverySigner | Your XRPL recovery-quorum signer, an independent random key sealed under the same Wallet Backup Key as the master. | Not derived from your recovery code. Any backup path that unwraps the WBK reconstructs it, so treat every restore factor as master-equivalent. |
| wraps[] · secure_enclave | The Wallet Backup Key, wrapped to your Secure Enclave P-256 key via ECIES. | The key that opens it never leaves the chip. Unwraps only on your physical device, behind a live biometric. |
| wraps[] · icloud_keychain | The WBK, wrapped for iCloud Keychain sync. | End-to-end encrypted in your Apple circle of trust; with Advanced Data Protection, no escrow key exists. |
| wraps[] · recovery_code_argon2id | The WBK, wrapped by an Argon2id key (m=4096, t=3, p=1) derived from your recovery code. | Only you hold the code. Memory-hard derivation resists brute force; the parameters are public. |
| recoveryPolicy | Signer-list quorum and the never-default DisableMasterKey flag. | Enforced on-chain; SciPHR's signer weight sits below quorum and can't act alone. |
The trick
To restore, your own device unwraps the Wallet Backup Key, with the Secure Enclave, your iCloud Keychain, or your recovery code, and only then opens the master key. The WBK only ever exists inside wraps that SciPHR cannot read, and it never reaches SciPHR in the clear. Publish the whole envelope and the key stays sealed.
What the credential holds.
- Immutable anchor, the NFT URI can't be altered once minted.
- Content-addressed, the CID is the envelope's fingerprint; the URI pins its SHA-256.
- Three recovery paths, the backup opens with your device, your iCloud, or your recovery code.
- Portable, the identity moves with you across devices.
- No plaintext master key anywhere in the envelope.
- No Wallet Backup Key in the clear.
- No key that SciPHR can read.
- No personal data; the identity itself lives in the DID.
Lifecycle on-chain
Minted once during onboarding, the xCIPHR persists for the life of the identity. It survives lost devices, app reinstalls, and platform changes, because it never depended on any of them. To use the identity, your device signs locally; to recover it, you restore the master key from this envelope or re-key via the signer list; to retire it, the owner burns or transfers the NFT with a valid on-chain signature.