We are adding Seal as an independent secondary backup path for the KMS root seed.
The existing KMS recovery path remains backed by Threshold Network. Seal gives us a second recovery route with a separate key-server threshold path, enforced through a Sui Move access-control contract.
The protected value is a 64-byte KMS root seed. We store it directly as the Seal payload.
Access Control Model
Today, access control is managed by the Solidity KmsRoot contract. KmsRoot verifies TEE attestations from valid KMS root servers and uses that to gate access to recovery material.
For the Seal path, we are building the analogous access control surface in Move on Sui.
Solidity:
KmsRoot
verifies TEE attestations from valid KMS root servers
gates access to KMS recovery material
Move on Sui:
KmsRoot-equivalent package
verifies TEE attestations from valid KMS root servers
exposes Seal approval entrypoint
gates Seal key release
The Move package will expose a narrowly scoped seal_approve function. Seal key servers execute or validate the approval transaction before returning key shares.
Seal Identity
The Seal identity for a backup is:
full_id = package_id || backup_id
package_id is the deployed Sui package containing the Move KmsRoot-equivalent policy. backup_id is our application-level identifier for a specific KMS backup generation.
This means access is bound to both:
- the deployed Move policy package
- the specific backup identity
Encryption Flow
Encryption happens inside a TEE as usual. Seal key servers do not see the blob and are not queried during encryption except indirectly through public-key metadata lookup.
input:
package_id
backup_id
key_server_ids
threshold
kms_recovery_blob[64]
client:
fetch key-server public keys from Sui
Seal-encrypt kms_recovery_blob
return EncryptedObject + recovery_key
storage:
persist bcs(EncryptedObject)
discard recovery_key
Seal internally uses a KEM/DEM construction. It generates a fresh symmetric content key, encrypts the 64-byte blob locally, and stores threshold-wrapped key material in the EncryptedObject.
The returned recovery_key is a local escape hatch for the generated content key. We explicitly drop it and do not log, persist, export, or colocate it with the backup artifact. Keeping it would bypass the Seal threshold/access-policy path.
Reencryption Flow
Since we wish to retain the same root seed as the current KMS, we first decrypt in a TEE using Threshold Network and reencrypt it using the encryption flow above.
The reencryption enclave will be made public for verification along with approval transactions in KmsRoot to allow it to decrypt.
Restore Flow
Restore is where Seal key servers participate.
input:
bcs(EncryptedObject)
SessionKey
approval PTB calling Move seal_approve
client:
submit fetch-key requests to Seal key servers
key servers validate approval policy
collect threshold key responses
reconstruct content key locally
decrypt 64-byte KMS recovery blob
The approval PTB proves that the caller satisfies the Move KmsRoot-equivalent policy, including valid TEE attestation checks for authorized KMS root servers.
Backup Artifact Metadata
Each stored backup artifact records:
package_id
backup_id
threshold
key_server_ids
committee aggregator URLs, if applicable
bcs(EncryptedObject)
policy/package version metadata
Security Properties
- Seal is an additional recovery path, not a replacement for the existing threshold backup.
- The 64-byte KMS recovery blob is never sent to Seal key servers.
- Restore requires both Move-policy approval and threshold Seal key-server availability.
- Access control mirrors the existing Solidity
KmsRootmodel, but is enforced through Sui Move. - The encrypted artifact is useless without satisfying the Seal approval policy.
- We avoid custom crypto and use the normal Seal SDK decrypt path.
Implementation Notes
- The Move package mirrors the existing Solidity
KmsRootauthorization model. - Package and key-server configuration are pinned per backup generation.
- The Rust client path is audited for request headers, key-server metadata validation, and recovery-key handling.
- Integration coverage encrypts a generated 64-byte blob, drops the recovery key, restores through the approval PTB, and verifies byte equality.