Transit Engine
1. What is it?
The Transit Engine provides encryption-as-a-service without storing the plaintext. It encrypts and decrypts data in transit using named versioned keys — the plaintext data never rests in the vault; only the cryptographic key does. This pattern is inspired by the HashiCorp Vault transit secrets engine and is ideal for database-transparent encryption.
2. What is it for?
Database-transparent encryption
Encrypt a column value before INSERT and decrypt it on SELECT, without storing plaintext anywhere in the database.
Application key delegation
Applications encrypt and decrypt without managing key material — all key operations stay in QuantumAPI.
Separating key management from data storage
Store ciphertext in your own infrastructure while QuantumAPI retains exclusive control over the keys.
Audited, versioned encryption for compliance
Every transit operation is logged with the key name and version, providing a complete encryption audit trail.
3. Key concepts
| Term | Definition |
|---|---|
| Transit key | A named key managed by the Transit Engine. Referenced by name (not UUID) in all transit operations. |
| Key version | Each rotation creates a new version. The version number is embedded in the ciphertext prefix so the correct version is used for decryption. |
| Convergent encryption | Optional mode where the same plaintext + context always produces the same ciphertext. Useful for searchable encryption but reduces semantic security. |
| Derived keys | Per-context sub-keys derived from the transit key using a context value. Isolates ciphertext across different contexts. |
| Re-wrap | Re-encrypts existing ciphertexts with the latest key version without decrypting them server-side to plaintext. |
| Batch operations | Encrypt or decrypt multiple independent records in a single API call. |
4. How to use it
Creating a transit key
Open Transit Engine
Enter a key name
Choose algorithm
Configure options
Save
Encrypting via transit
Reference the transit key by name:
POST /api/v1/transit/encrypt/orders-db
{ "plaintext": "SGVsbG8gV29ybGQ=" }Decrypting via transit
The key version is embedded in the ciphertext and selected automatically:
POST /api/v1/transit/decrypt/orders-db
{ "ciphertext": "vault:v1:..." }Rotating the transit key
Rotation creates a new key version. Existing ciphertexts can still be decrypted using their embedded version number.
Re-wrapping ciphertexts
After rotation, re-wrap existing ciphertexts to the new key version without exposing plaintext:
POST /api/v1/transit/rewrap/orders-db
{ "ciphertext": "vault:v1:..." }
# Returns: { "ciphertext": "vault:v2:..." }5. Field reference
| Field | Type | Required | Description |
|---|---|---|---|
| Key name | string | Yes (on create) | Name of the transit key. Used as the identifier in all transit operations. |
| plaintext | Base64 string | Yes (encrypt) | Data to encrypt, Base64-encoded. |
| ciphertext | string | Yes (decrypt/rewrap) | The ciphertext returned by a previous encrypt call. Contains an embedded key version prefix. |
| keyVersion | integer | No | Key version to use for encryption. Defaults to the latest version. |
| context | Base64 string | No | Context for derived keys or convergent encryption. Must match on decrypt. |
6. Relationships
Encryption Keys
Transit keys are a specialised view of encryption keys. They are listed in both sections.
Encrypt / Decrypt
The Transit Engine uses the same underlying encrypt/decrypt primitives but adds key versioning and re-wrap capabilities.
API Keys
API Keys with scope transit:invoke are required to use transit encrypt/decrypt/rewrap endpoints.
SDKs
The TypeScript, Python, .NET, and Rust SDKs all include a TransitClient for transit operations.
7. FAQ
Is the Transit Engine the same as Encrypt / Decrypt?
They share the same underlying cryptography, but the Transit Engine adds key versioning, re-wrap, convergent encryption, and name-based key references. Use Encrypt/Decrypt for ad-hoc operations and the Transit Engine for long-running data workflows where key version management matters.
When should I use the Transit Engine vs direct Encrypt / Decrypt?
Use the Transit Engine when: (1) you store ciphertexts long-term and need to rotate keys without re-encrypting from scratch; (2) you need convergent (deterministic) encryption for searchable fields; (3) you want per-context key derivation. Use direct Encrypt/Decrypt for stateless, one-off operations.
What is convergent encryption and is it safe?
Convergent encryption produces the same ciphertext for the same plaintext + context, enabling equality lookups on encrypted columns. It is safe when context is unique per record (e.g. record ID). Without unique context, an attacker who knows some plaintexts can identify matching ciphertexts.
How do I re-encrypt old data after a key rotation?
Use the re-wrap API endpoint. It takes an existing ciphertext (any version) and returns a new ciphertext encrypted with the latest key version, without ever exposing the plaintext to the caller.
8. API / CLI reference
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/transit/keys | Create a new transit key. |
| GET | /api/v1/transit/keys | List all transit keys. |
| GET | /api/v1/transit/keys/{name} | Get transit key details and versions. |
| POST | /api/v1/transit/keys/{name}/rotate | Rotate the transit key. |
| DELETE | /api/v1/transit/keys/{name} | Delete a transit key. |
| POST | /api/v1/transit/encrypt/{name} | Encrypt data using the transit key. |
| POST | /api/v1/transit/decrypt/{name} | Decrypt data using the transit key. |
| POST | /api/v1/transit/rewrap/{name} | Re-wrap ciphertext with the latest key version. |
| POST | /api/v1/transit/encrypt/{name}/batch | Batch encrypt multiple records. |
| POST | /api/v1/transit/decrypt/{name}/batch | Batch decrypt multiple records. |
qapi transit keys create orders-db --algorithm AES-256-GCM
qapi transit encrypt orders-db --plaintext <base64>
qapi transit decrypt orders-db --ciphertext <ciphertext>
qapi transit keys rotate orders-db
qapi transit rewrap orders-db --ciphertext <old-ciphertext>