Vault

Vault Transit Engine Deep Dive: Operating Encryption as a Service Safely

2026-04-19
NicheeLab Editorial Team

The Vault Transit engine never stores your application's secrets. It keeps keys safe and exposes only cryptographic operations via API, delivering true "Encryption as a Service".

This article covers the core capabilities, operational design, exam-relevant topics, and minimal commands. It zeroes in on settings that often trip people up in the field, such as derived/convergent, min_decryption_version, and rewrap.

Transit Engine Basics and Encryption as a Service

Transit does not store application data. It only stores keys and metadata, and exposes encrypt, decrypt, sign, HMAC, and data key generation via API/CLI. Applications can delegate stable cryptographic operations without worrying about key management or implementation details.

Representative features include encrypt/decrypt with symmetric keys (e.g., aes256-gcm96), sign/verify with asymmetric keys (RSA/ECDSA/Ed25519), HMAC, and data keys (KMS-style ephemeral keys). Keys are versioned, and you can control rotation as well as the minimum allowed decryption version (min_decryption_version).

  • No data storage: application plaintext/ciphertext is not retained in Vault (audit logs aside)
  • Unified cryptographic API: encrypt/decrypt/sign/verify/hmac/datakey/rewrap
  • Key versioning and rotation: you can also bound the minimum decryptable version
  • Rides on a highly available Vault cluster: HA and performance standbys deliver throughput and availability

EaaS request flow (application ⇔ Vault Transit)

encrypt/decrypt/sign/hmacApplication(s)API/CLI, holds no keysVault (Transit SE)Key Mgmt / Operations, stores no dataStorage (keys only) / Audit log (requests)Applications hold no keys and delegate cryptographic operations to Vault Transit. Vault stores only keys and records audit logs

Enabling Transit with a minimal setup (CLI)

# Enable the Transit engine (default path: transit/)
vault secrets enable transit

# Create the encryption key 'payments' (symmetric aes256-gcm96)
vault write transit/keys/payments type=aes256-gcm96

# Base64-encode plaintext and encrypt
echo -n 'card:4111-1111-1111-1111' | base64 | \
  xargs -I{} vault write transit/encrypt/payments plaintext={

# Decrypt (ciphertext is the return value of encrypt)
vault write transit/decrypt/payments ciphertext=vault:v1:...

# Minimal policy (allow encrypt only)
cat <<'EOF' > transit-app.hcl
path "transit/encrypt/payments" {
  capabilities = ["update"]
}
EOF
vault policy write transit-app transit-app.hcl

Key Lifecycle and Key Settings (versioning / derived / convergent)

Transit keys are versioned, and a new version is issued by rotate. Existing ciphertext can still be decrypted with its original version, but raising min_decryption_version rejects decryption against older versions. That enables planned cryptographic refresh and gradual cutover.

Symmetric keys (aes256-gcm96 default, chacha20-poly1305, etc.) are mainly used for encrypt/decrypt, while asymmetric keys (rsa-*, ecdsa-*, ed25519) are primarily for sign/verify. Enabling exportable or allow_plaintext_backup makes key material retrievable, but the risk is high, so treat those options with extreme caution in production.

derived=true generates a derived key from the per-call context (Base64), which is great for multi-tenant or per-data-class isolation. Combining it with convergent_encryption=true (which requires derived=true) lets a caller-supplied 96-bit nonce produce deterministic encryption (same plaintext maps to same ciphertext). Determinism can leak sensitive information, so use it only when the requirement is clear.

  • rotate: vault write -f transit/keys/<name>/rotate
  • Decryption control: min_decryption_version / min_encryption_version
  • Deletion: only keys with deletion_allowed=true can be deleted (safety guard)
  • Export: keep exportable / allow_plaintext_backup enabled only when strictly necessary
  • derived/context: Base64 encoding is required. Use it to enforce tenant boundaries
  • convergent: pairs with derived. Requires a user-supplied nonce (12 bytes)

Representative key operation commands

# Create a key (derived + convergent encryption)
vault write transit/keys/customer-data \
  type=aes256-gcm96 derived=true convergent_encryption=true

# Rotate and update configuration
vault write -f transit/keys/customer-data/rotate
vault write transit/keys/customer-data/config \
  min_decryption_version=2 deletion_allowed=true

# Inspect the key
vault read transit/keys/customer-data

Primary Use Cases and Comparison with Alternatives

Vault Transit is well suited to application-layer cryptographic operations. Typical use cases include PII protection, payment token encryption, signing/HMAC for webhook secrets, and encrypting sensitive logs. When tokenization or format-preserving encryption is required, the Transform engine may be a better fit.

Rather than competing with cloud KMS or database TDE, the realistic design is to layer them. A clear division of responsibility is: TDE for at-rest encryption, Transit for application-view field encryption, and KMS as the root of trust for key material.

  • Field encryption: encrypt only specific columns in the application (decrypt only when needed)
  • Sign/verify: integrity for webhooks, release artifacts, and audit events
  • HMAC: request tamper detection and MAC-based tokens
  • Data keys: encrypt large data sets with ephemeral keys in the application-side library
SolutionPrimary useOperational notes / caveats
Vault TransitAPI-based encrypt, sign, HMAC, and data keysKeys are managed by Vault. The app's focus is Base64 I/O and permission design
Cloud KMS (used directly)Key protection and data key issuanceCloud-dependent and requires IAM design. The application encryption API still needs to be implemented separately
Application-only crypto libraryMaximum implementation flexibilityKey management, rotation, and auditing are all do-it-yourself, with a risk of vulnerable implementations
Database TDEAt-rest encryptionTransparent to applications, but not suited to selective column-level encryption

Sign/verify and HMAC API call examples (curl)

# Sign (input is Base64). Used with keys such as ed25519 or ecdsa-p256
curl -s \
  -H "X-Vault-Token: $VAULT_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$VAULT_ADDR/v1/transit/sign/release-key" \
  -d '{"input":"'$(echo -n artifact-sha256 | base64)'","hash_algorithm":"sha2-256"}'

# Verify
curl -s \
  -H "X-Vault-Token: $VAULT_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$VAULT_ADDR/v1/transit/verify/release-key" \
  -d '{"input":"'$(echo -n artifact-sha256 | base64)'","signature":"vault:v1:..."}'

# HMAC
curl -s \
  -H "X-Vault-Token: $VAULT_TOKEN" \
  -H "Content-Type: application/json" \
  -X POST "$VAULT_ADDR/v1/transit/hmac/webhook-key" \
  -d '{"input":"'$(echo -n payload | base64)'","algorithm":"sha2-256"}'

Operational Best Practices (Associate / Ops Perspective)

Lock down the path design up front. Choose key names that reflect tenant or system boundaries, and reinforce logical isolation with derived keys. As a baseline, grant least privilege on encrypt/update and tightly restrict decrypt.

Availability depends on the Vault cluster configuration (HA, performance standbys). Transit is close to stateless, so request forwarding during leader failover works well. Always enable audit logging to keep key operations and configuration changes traceable.

Performance is the sum of network round trips and cryptographic processing cost. You can keep latency low by combining the batch API (batch_input) with data keys for application-side encryption. The standard pattern is to encrypt bulk data with data keys and let Vault focus on key management.

  • Least privilege: separate tokens that only have encrypt from tokens that can decrypt
  • Base64 convention: plaintext/context must be Base64. Forgetting to encode is a classic error
  • min_decryption_version: raise it gradually, not all at once, and pair it with a recovery plan
  • exportable / allow_plaintext_backup: off by default, only enable for unavoidable migrations
  • rewrap: a safe path to migrate to a new version without ever exposing plaintext
  • Audit: treat change operations under transit/keys/* as elevated audit targets

Least-privilege policy example (HCL)

# App can encrypt only; SRE can read state and rotate
# For the application
path "transit/encrypt/payments" {
  capabilities = ["update"]
}
# Grant sign / HMAC at minimum privilege on dedicated paths
path "transit/hmac/webhook-key" {
  capabilities = ["update"]
}

# For SRE / operations
path "transit/keys/payments" {
  capabilities = ["read", "update"]  # read: inspect state, update: change config
}
path "transit/keys/payments/rotate" {
  capabilities = ["update"]
}
# Decrypt is restricted to a separate token as a general rule
auth "*" {
  capabilities = []
}

Exam Tips: Frequently Asked Points and Pitfalls

The keyword for Transit is "does not store data". It only provides cryptographic operations, and keys are persisted in Vault's storage. Questions that try to confuse you with Transform, and questions about the behavior of rewrap and the meaning of min_decryption_version, come up frequently.

Make sure you also have a handle on Base64 I/O, batch_input, derived/context, convergent and nonce, the risks of exportable / allow_plaintext_backup, and the role of data keys (offloading bulk data encryption).

  • rewrap: re-encrypt ciphertext to the latest key without seeing the plaintext
  • min_decryption_version: versions older than this value cannot decrypt
  • datakey: returns both plaintext and ciphertext (used for application-side encryption)
  • Signing key usage: Ed25519/ECDSA cover sign/verify, while RSA differs in that it can be used for both signing and encryption
  • Difference from Transform: Transit is encryption; Transform is tokenization / format-preserving

HTTP verbs and endpoints at a glance (review snippet)

# Create / update config: POST /v1/transit/keys/<name>
# Rotate:                  POST /v1/transit/keys/<name>/rotate
# Encrypt:                 POST /v1/transit/encrypt/<name>
# Decrypt:                 POST /v1/transit/decrypt/<name>
# Sign / verify:           POST /v1/transit/sign|verify/<name>
# HMAC:                    POST /v1/transit/hmac/<name>
# Rewrap:                  POST /v1/transit/rewrap/<name>
# Data key:                POST /v1/transit/datakey/plaintext|wrapped/<name>

Hands-on: Encrypt/Decrypt, Rewrap, Data Keys, Batch

The minimal flow is "create key -> encrypt -> decrypt". In production you optimize throughput with post-rotation rewrap, data key usage, and batch encryption.

Below are examples that mix CLI and curl. When practicing for the exam, double-check "which operations avoid handling plaintext (rewrap)" and "which fields are Base64 (plaintext/context/input)".

  • encrypt/decrypt: plaintext is Base64, return value is ciphertext in the vault:v<ver>:... format
  • rewrap: re-wrap old ciphertext to the latest version (no plaintext involved)
  • datakey: encrypt bulk data on the application side and let Vault focus on key management and auditing
  • batch_input: encrypt multiple items at the same endpoint to reduce round trips

Practical commands and requests

# Encrypt (single)
echo -n 'pii:john.doe' | base64 | \
  xargs -I{} vault write transit/encrypt/pii plaintext={

# Decrypt
vault write transit/decrypt/pii ciphertext=vault:v2:...

# Rewrap (move to the latest version without needing plaintext)
vault write transit/rewrap/pii ciphertext=vault:v1:...

# Data key (plaintext key for application-side encryption)
vault write transit/datakey/plaintext/pii bits=256

# Batch encrypt (curl example)
JSON='{"batch_input":[{"plaintext":"'$(echo -n a | base64)'"},{"plaintext":"'$(echo -n b | base64)'"}]}'
curl -s -H "X-Vault-Token: $VAULT_TOKEN" -H "Content-Type: application/json" \
  -X POST "$VAULT_ADDR/v1/transit/encrypt/pii" -d "$JSON"

# Derived key + convergent encryption call (mind the Base64 / binary requirements for context and nonce)
CTX=$(echo -n tenant-123 | base64)
NONCE=$(head -c 12 /dev/urandom | base64)  # 96-bit (12 bytes)
curl -s -H "X-Vault-Token: $VAULT_TOKEN" -H "Content-Type: application/json" \
  -X POST "$VAULT_ADDR/v1/transit/encrypt/customer-data" \
  -d '{"plaintext":"'$(echo -n ssn:123-45 | base64)'","context":"'$CTX'","nonce":"'$NONCE'"}'

Check Your Understanding

Associate / Ops

問題 1

You want to rotate a Vault Transit key and migrate to the latest version. Which is the safe approach that re-protects existing ciphertext with the new version without ever handling plaintext on the application side?

  1. Pass the existing ciphertext to the transit/rewrap endpoint
  2. Issue a new data key via transit/datakey and re-encrypt
  3. Immediately maximize min_decryption_version after keys/<name>/rotate
  4. Enable the Transform engine and switch to tokenization

正解: A

rewrap re-wraps existing ciphertext with the new key version without ever decrypting it to plaintext. Issuing a data key would require handling plaintext on the application side, immediately raising min_decryption_version has heavy operational impact, and Transform serves a different purpose.

Frequently Asked Questions

Does Transit store the application's ciphertext or plaintext?

No. Transit only stores keys and metadata. It does not store the input or output of encrypt/decrypt operations (audit logs capture request metadata, but the plaintext itself is never retained).

Should I use database TDE or Transit?

They serve different purposes. TDE provides at-rest encryption that protects data on disk, while Transit is suited to application-layer field encryption, signing, and HMAC. Many systems combine TDE and Transit for defense in depth.

What happens if Vault is sealed or unavailable?

Transit API calls will fail. Increase availability with an HA configuration (integrated storage, performance standbys), and implement retries and backoff on the client side. There is no expected way to recover plaintext or keys outside of Vault (unless options like exportable are explicitly enabled).

Check what you learned with practice questions

Practice with certification-focused question sets

無料で問題を解いてみる
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Vault

Vault Core Concepts: Sealed/Unsealed, Auth, Secrets (2026)

Vault fundamentals — sealed/unsealed state, auth methods, se...

Vault

Vault Operations Professional (VOP-003): Complete Guide (2026)

Pass the Vault Operations Professional exam — enterprise pat...

Vault

Vault Path-Based Routing: API URL Structure (2026)

How Vault's path-based routing works — mount points, sub-pat...

Vault

Vault Tokens: Auth Token Mechanics (2026)

Token fundamentals — service vs. batch tokens, accessor, ren...

Vault

Vault Token Types: Service, Batch, Periodic (2026)

Service vs. batch tokens compared — performance, ACL behavio...

Browse all Vault articles (101)
© 2026 NicheeLab All rights reserved.