HashiCorp Vault — Transform Engine
The Transform secrets engine provides format-preserving encryption (FPE) and tokenization — protecting sensitive data while maintaining its format for existing systems.
Transform vs Transit
| Feature | Transit | Transform |
|---|---|---|
| Output format | Base64 ciphertext | Same format as input |
| SSN in, SSN out | ❌ vault:v1:abc... |
✅ 123-45-6789 → 987-65-4321 |
| Credit card format | ❌ | ✅ Preserves 16-digit format |
| Database compatible | ❌ (schema changes needed) | ✅ Drop-in replacement |
Transformation Types
| Type | Description | Example |
|---|---|---|
| FPE | Format-preserving encryption | 4111-1111-1111-1111 → 8923-4521-7890-3456 |
| Masking | Irreversible masking | 4111-1111-1111-1111 → XXXX-XXXX-XXXX-1111 |
| Tokenization | Replace with random token | 4111-1111-1111-1111 → tok_a8f3b2c1 |
Enable Transform Engine
vault secrets enable transform
Format-Preserving Encryption (FPE)
Create a Transformation
# Create a role
vault write transform/role/payments transformations=card-number
# Create an FPE transformation for credit cards
vault write transform/transformations/fpe/card-number \
template=credit-card-number \
tweak_source=internal \
allowed_roles=payments
# Create a template (defines the format)
vault write transform/template/credit-card-number \
type=regex \
pattern='(\d{4})-(\d{4})-(\d{4})-(\d{4})' \
alphabet=numerics
Encode (Encrypt)
vault write transform/encode/payments \
value="4111-1111-1111-1111" \
transformation=card-number
# Returns: 8923-4521-7890-3456 (same format!)
Decode (Decrypt)
vault write transform/decode/payments \
value="8923-4521-7890-3456" \
transformation=card-number
# Returns: 4111-1111-1111-1111
Tokenization
Replace sensitive data with opaque tokens stored in Vault:
# Create a tokenization transformation
vault write transform/transformations/tokenization/ssn-token \
allowed_roles=hr \
max_ttl=0
# Create role
vault write transform/role/hr transformations=ssn-token
# Tokenize
vault write transform/encode/hr \
value="123-45-6789" \
transformation=ssn-token
# Returns: tok_2N4hYz8RXu3JkLm
# Detokenize
vault write transform/decode/hr \
value="tok_2N4hYz8RXu3JkLm" \
transformation=ssn-token
# Returns: 123-45-6789
Masking
Irreversible data masking:
# Create a masking transformation
vault write transform/transformations/masking/card-mask \
template=credit-card-number \
masking_character="X" \
allowed_roles=support
vault write transform/role/support transformations=card-mask
# Mask
vault write transform/encode/support \
value="4111-1111-1111-1111" \
transformation=card-mask
# Returns: XXXX-XXXX-XXXX-1111
Warning: Masking is irreversible — the original value cannot be recovered.
Common Templates
| Template | Pattern | Use Case |
|---|---|---|
| Credit card | \d{4}-\d{4}-\d{4}-\d{4} |
PCI compliance |
| SSN | \d{3}-\d{2}-\d{4} |
PII protection |
| Phone | \d{3}-\d{3}-\d{4} |
Contact info |
API Usage
# Encode via API
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"value": "4111-1111-1111-1111", "transformation": "card-number"}' \
"$VAULT_ADDR/v1/transform/encode/payments" | jq
# Batch encode
curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{
"batch_input": [
{"value": "4111-1111-1111-1111", "transformation": "card-number"},
{"value": "5500-0000-0000-0004", "transformation": "card-number"}
]
}' \
"$VAULT_ADDR/v1/transform/encode/payments" | jq
Quick Reference
| Command | Description |
|---|---|
vault secrets enable transform |
Enable transform engine |
vault write transform/encode/ROLE value=DATA |
Encode (encrypt/tokenize/mask) |
vault write transform/decode/ROLE value=DATA |
Decode (decrypt/detokenize) |
vault write transform/transformations/fpe/NAME ... |
Create FPE transformation |
vault write transform/transformations/tokenization/NAME ... |
Create tokenization |
vault write transform/transformations/masking/NAME ... |
Create masking |
Note: Transform is a Vault Enterprise feature.
Next: Practice Exercises