Vaultx.Secrets.Transit.Encryption (Vaultx v0.7.0)

View Source

Enterprise encryption services for HashiCorp Vault Transit secrets engine.

This module provides comprehensive encryption and decryption functionality for enterprise applications, including symmetric and asymmetric encryption, high-performance batch operations, key derivation, and convergent encryption support. It implements industry-standard cryptographic algorithms with enterprise-grade security and performance.

Enterprise Encryption Capabilities

  • High-performance symmetric encryption/decryption (AES-GCM, ChaCha20-Poly1305)
  • Asymmetric encryption/decryption (RSA-OAEP, RSA-PKCS1)
  • Batch operations for high-throughput enterprise workloads
  • Context-based key derivation for multi-tenant scenarios
  • Convergent encryption for deterministic, deduplication-friendly results
  • Associated data support for authenticated encryption (AEAD)
  • Key version selection for cryptographic agility
  • Data rewrapping for seamless key rotation

Supported Algorithms

Symmetric Ciphers

  • aes128-gcm96 - AES-128 with GCM (96-bit nonce)
  • aes256-gcm96 - AES-256 with GCM (96-bit nonce, default)
  • chacha20-poly1305 - ChaCha20-Poly1305 AEAD

Asymmetric Ciphers

  • rsa-2048, rsa-3072, rsa-4096 - RSA encryption

Usage Examples

# Basic encryption/decryption
{:ok, result} = Vaultx.Secrets.Transit.Encryption.encrypt("my-key", "dGVzdCBkYXRh")
{:ok, plaintext} = Vaultx.Secrets.Transit.Encryption.decrypt("my-key", result.ciphertext)

# Encryption with context (key derivation)
{:ok, result} = Vaultx.Secrets.Transit.Encryption.encrypt("tenant-key", "dGVzdCBkYXRh",
  context: "dGVuYW50LWlk")

# Convergent encryption (deterministic)
{:ok, result} = Vaultx.Secrets.Transit.Encryption.encrypt("convergent-key", "dGVzdCBkYXRh",
  nonce: "bm9uY2U=")

# Batch encryption
batch_items = [
  %{plaintext: "dGVzdDE="},
  %{plaintext: "dGVzdDI=", context: "Y29udGV4dA=="}
]
{:ok, results} = Vaultx.Secrets.Transit.Encryption.batch_encrypt("my-key", batch_items)

# Rewrap data with latest key version
{:ok, rewrapped} = Vaultx.Secrets.Transit.Encryption.rewrap("my-key", old_ciphertext)

Encryption Options

  • :context - Base64 encoded key derivation context
  • :nonce - Base64 encoded nonce for convergent encryption
  • :key_version - Specific key version to use for encryption
  • :associated_data - Additional authenticated data for AEAD
  • :type - Encryption type ("aead" for AEAD ciphers)

Security Considerations

  • Always use base64 encoding for plaintext and context data
  • Context should be unique per tenant/user for derived keys
  • Nonce must be unique for convergent encryption
  • Associated data is authenticated but not encrypted
  • Key versions allow for gradual key rotation

API Compliance

Fully implements HashiCorp Vault Transit encryption operations:

Summary

Types

Batch decryption item.

Batch encryption item.

Decryption result structure.

Encryption result structure.

Functions

Encrypts multiple plaintext items in a single request.

Decrypts ciphertext data using a named key.

Encrypts plaintext data using a named key.

Re-encrypts ciphertext with the latest version of the named key.

Types

batch_decrypt_item()

@type batch_decrypt_item() :: %{
  ciphertext: String.t(),
  context: String.t() | nil,
  nonce: String.t() | nil,
  associated_data: String.t() | nil
}

Batch decryption item.

batch_encrypt_item()

@type batch_encrypt_item() :: %{
  plaintext: String.t(),
  context: String.t() | nil,
  nonce: String.t() | nil,
  associated_data: String.t() | nil
}

Batch encryption item.

decryption_result()

@type decryption_result() :: %{plaintext: String.t(), key_version: pos_integer()}

Decryption result structure.

encryption_result()

@type encryption_result() :: %{ciphertext: String.t(), key_version: pos_integer()}

Encryption result structure.

Functions

batch_encrypt(key_name, batch_items, opts \\ [])

@spec batch_encrypt(String.t(), [batch_encrypt_item()], keyword()) ::
  {:ok, [encryption_result()]} | {:error, term()}

Encrypts multiple plaintext items in a single request.

Parameters

  • key_name - The name of the encryption key to use
  • batch_items - List of items to encrypt
  • opts - Additional options

Options

  • :mount_path - Transit engine mount path (default: "transit")

Returns

  • {:ok, results} - Batch encryption successful
  • {:error, reason} - Batch encryption failed

Examples

iex> batch_items = [
...>   %{plaintext: "dGVzdDE="},
...>   %{plaintext: "dGVzdDI=", context: "Y29udGV4dA=="}
...> ]
iex> batch_encrypt("my-key", batch_items)
{:ok, [%{ciphertext: "vault:v1:...", key_version: 1}, ...]}

decrypt(key_name, ciphertext, opts \\ [])

@spec decrypt(String.t(), String.t(), keyword()) ::
  {:ok, decryption_result()} | {:error, term()}

Decrypts ciphertext data using a named key.

Parameters

  • key_name - The name of the encryption key to use
  • ciphertext - The ciphertext to decrypt
  • opts - Additional decryption options

Options

  • :mount_path - Transit engine mount path (default: "transit")
  • :context - Base64 encoded key derivation context
  • :nonce - Base64 encoded nonce for convergent encryption
  • :associated_data - Additional authenticated data for AEAD

Returns

  • {:ok, result} - Decryption successful
  • {:error, reason} - Decryption failed

Examples

iex> decrypt("my-key", "vault:v1:...")
{:ok, %{plaintext: "dGVzdCBkYXRh", key_version: 1}}

iex> decrypt("my-key", "vault:v1:...", context: "Y29udGV4dA==")
{:ok, %{plaintext: "dGVzdCBkYXRh", key_version: 1}}

encrypt(key_name, plaintext, opts \\ [])

@spec encrypt(String.t(), String.t(), keyword()) ::
  {:ok, encryption_result()} | {:error, term()}

Encrypts plaintext data using a named key.

Parameters

  • key_name - The name of the encryption key to use
  • plaintext - Base64 encoded plaintext to encrypt
  • opts - Additional encryption options

Options

  • :mount_path - Transit engine mount path (default: "transit")
  • :context - Base64 encoded key derivation context
  • :nonce - Base64 encoded nonce for convergent encryption
  • :key_version - Specific key version to use
  • :associated_data - Additional authenticated data for AEAD
  • :type - Encryption type ("aead" for AEAD ciphers)

Returns

  • {:ok, result} - Encryption successful
  • {:error, reason} - Encryption failed

Examples

iex> encrypt("my-key", "dGVzdCBkYXRh")
{:ok, %{ciphertext: "vault:v1:...", key_version: 1}}

iex> encrypt("my-key", "dGVzdCBkYXRh", context: "Y29udGV4dA==")
{:ok, %{ciphertext: "vault:v1:...", key_version: 1}}

rewrap(key_name, ciphertext, opts \\ [])

@spec rewrap(String.t(), String.t(), keyword()) ::
  {:ok, encryption_result()} | {:error, term()}

Re-encrypts ciphertext with the latest version of the named key.

This is useful for key rotation scenarios where you want to upgrade ciphertext to use the latest key version without decrypting and re-encrypting.

Parameters

  • key_name - The name of the encryption key to use
  • ciphertext - The ciphertext to rewrap
  • opts - Additional options

Options

  • :mount_path - Transit engine mount path (default: "transit")
  • :context - Base64 encoded key derivation context
  • :nonce - Base64 encoded nonce for convergent encryption
  • :key_version - Specific key version to rewrap to

Returns

  • {:ok, result} - Rewrap successful
  • {:error, reason} - Rewrap failed

Examples

iex> rewrap("my-key", "vault:v1:old-ciphertext")
{:ok, %{ciphertext: "vault:v2:new-ciphertext", key_version: 2}}