Skip to content

End-to-End Encryption

OpenTusk provides client-side encryption for shared vaults using the SEAL protocol (Sui Encryption and Access Library). The server never sees plaintext file contents for encrypted vaults.

Shared vaultsPublic vaults
EncryptionSEAL protocol (IBE)None
Identity modelSui address-basedN/A
Key managementOn-chain Whitelist + key serversN/A
Multi-party accessYes (owner + members)Anyone

Shared vaults use the SEAL protocol for multi-party encryption. Access is controlled by an on-chain allowlist on the Sui blockchain.

Vault owner creates shared vault
└─ Owner's wallet signs create_whitelist_entry() on Sui
├─ Owner added to Whitelist
└─ Cap object transferred to vault owner
File upload (any member):
└─ SEAL IBE encrypt with Whitelist identity + file nonce
└─ Encrypted file + SEAL metadata uploaded to OpenTusk
File download (any member):
└─ Client signs SessionKey with Sui keypair
└─ SEAL key servers verify membership on-chain
└─ Decryption key fragments returned
└─ Client decrypts file locally
ComponentPurposeWhere it lives
WhitelistOn-chain Sui shared object listing authorized Sui addressesSui blockchain
CapAdmin capability for managing the WhitelistVault owner’s wallet (on-chain)
SEAL identityPer-file encryption identity (Whitelist ID + file nonce)OpenTusk API (per file)
SEAL EncryptedObjectSerialized encryption metadata for decryption requestsOpenTusk API (per file, base64)
Key serversThreshold key servers that validate membership and issue decryption fragmentsSEAL network

Shared vaults implement two layers of access control:

  1. Database layer — the vault_members table provides fast API-level authorization. Membership is checked on every API call (upload, download, list files, etc.).
  2. On-chain layer — the Sui Whitelist provides cryptographic authorization. SEAL key servers verify on-chain membership before issuing decryption keys.

When a member is added or revoked, both layers are updated. If the on-chain transaction fails, the API membership still takes effect (logged as a warning) — the on-chain state is eventually consistent.

For shared vaults, the client encrypts before uploading:

  1. Build a SEAL identity from the vault’s Whitelist ID and a per-file nonce
  2. Encrypt the file using SEAL IBE (Identity-Based Encryption)
  3. Upload the ciphertext via the standard upload flow
  4. Include SEAL metadata: sealIdentity, sealEncryptedObject

The SDK, CLI, and MCP server handle this automatically when uploading to a shared vault.

  1. Get the download URL and SEAL metadata from the API
  2. Download the encrypted bytes
  3. Sign a SessionKey with your Sui keypair
  4. SEAL key servers verify your on-chain membership and return decryption key fragments
  5. Decrypt the file locally

The server never sees:

  • Plaintext file contents (shared vaults)
  • Raw decryption keys or your Sui private key

Integrity guarantees:

  • SEAL IBE provides authenticated encryption
  • On-chain Whitelist membership is verified by independent key servers

Threat model:

  • A compromised server only obtains encrypted bytes — useless without key server cooperation
  • Key servers independently verify on-chain membership before issuing decryption fragments
  • Revoking a member’s Sui address from the Whitelist prevents future decryption

SEAL uses the following defaults (configured in packages/shared/src/constants.ts):

ParameterValue
Threshold1-of-1
Key serverOverclock mainnet (open mode)
Move packageopentusk::shared_vault on Sui mainnet

For AI agents using the MCP server, set the OPENTUSK_SUI_PRIVATE_KEY environment variable to enable SEAL encryption/decryption on shared vaults.

Shared vaults with SEAL encryption are ideal for storing sensitive agent outputs — API keys, credentials, security audit results, PII-containing data. The server never sees plaintext.

To store encrypted artifacts:

  1. Create a shared vault (default visibility)
  2. Upload via SDK, CLI, or MCP tools — encryption is automatic
  3. Only members on the on-chain Whitelist can decrypt