Vault & Key Backup
Back up and restore MPC keyshares with password-encrypted cloud storage.
The vault module provides secure keyshare backup and recovery through the EmbarkAI ShareVault service. Keyshares are encrypted client-side before upload — the server never sees plaintext key material.
Configuration
import { configureVaultModule } from '@embarkai/core'
configureVaultModule({
tssUrl: 'https://tss.lumiapassport.com', // optional override
shareVaultUrl: 'https://vault.lumiapassport.com', // optional override
})Default URLs are resolved automatically for supported chains.
Check Backup Status
Verify whether a backup exists for a user before attempting restore:
import { checkBackupExists } from '@embarkai/core'
const { hasBackup, serviceAvailable } = await checkBackupExists(
authenticatedClient,
'user_abc123',
)
if (!serviceAvailable) {
console.warn('Vault service is temporarily unavailable')
} else if (hasBackup) {
console.log('Backup found, ready to restore')
}Back Up a Keyshare
import { backupToVault } from '@embarkai/core'
import type { KeyshareBackupData } from '@embarkai/core'
const backupData: KeyshareBackupData = {
userId: 'user_abc123',
sessionId: 'session_xyz',
keyshare: '...base64-encoded-keyshare...',
ownerAddress: '0xYourEOAAddress',
createdAt: Date.now(),
version: 1,
}
await backupToVault(authenticatedClient, backupData, 'user-chosen-password')Restore a Keyshare
import { restoreFromVault } from '@embarkai/core'
const recovered = await restoreFromVault(
authenticatedClient,
'user_abc123',
'user-chosen-password',
)
console.log('Owner:', recovered.ownerAddress)
console.log('Session:', recovered.sessionId)
// recovered.keyshare is now available for signingIf the password is incorrect, restoreFromVault throws an error. There is no password reset mechanism — the encryption is client-side and the server has no access to the plaintext.
KeyshareBackupData Type
| Field | Type | Description |
|---|---|---|
userId | string | User identifier |
sessionId | string | DKG session that produced this keyshare |
keyshare | string | Base64-encoded keyshare data |
ownerAddress | string | EOA address derived from the TSS public key |
createdAt | number | Timestamp of keyshare creation (ms) |
version | number | Backup format version |
Encryption Details
All encryption happens client-side before any data leaves the device:
- Key Derivation — The user password is stretched using PBKDF2 with 150,000 iterations and SHA-256 to produce a Key Encryption Key (KEK).
- Data Encryption Key — A random 256-bit Data Encryption Key (DEK) is generated per backup.
- Envelope Encryption — The keyshare payload is encrypted with AES-256-GCM using the DEK. The DEK is then wrapped (encrypted) with the KEK.
- Storage — The encrypted envelope (wrapped DEK + ciphertext + IV + salt) is uploaded to the ShareVault. The server stores only ciphertext and cannot decrypt without the password.
This envelope encryption scheme means changing the password only requires re-wrapping the DEK, not re-encrypting the entire payload.
Usage with ServerWalletManager
ServerWalletManager provides convenient shorthand methods that handle KeyshareBackupData assembly automatically:
import { createServerWalletManager, MemoryKeyshareStorage } from '@embarkai/core'
const manager = createServerWalletManager({
apiKey: process.env.EMBARK_API_KEY!,
chainId: 994873017,
storage: new MemoryKeyshareStorage(),
})
// Back up a wallet's keyshare
await manager.backupToVault('treasury_main', 'secure-password')
// Check if a backup exists
const { hasBackup } = await manager.checkBackupExists('treasury_main')
// Restore keyshare to local storage
await manager.restoreFromVault('treasury_main', 'secure-password')Security Notes
- Password strength matters. PBKDF2 slows brute-force attacks, but a weak password is still vulnerable. Enforce minimum length and complexity requirements in your UI.
- No password recovery. The server cannot decrypt backups. If the user forgets their password, the backup is permanently inaccessible.
- One backup per user. A new backup overwrites the previous one. Coordinate backup timing if multiple devices share the same user ID.
- Audit restore attempts. Log failed restore attempts to detect potential brute-force attacks against user passwords.
Next Steps
- Server Wallets — create wallets and use
manager.backupToVault()shorthand - Authentication — set up authenticated sessions required for vault API calls
- Bundler — submit transactions after restoring a keyshare