AwsEncryptionSdk (AWS Encryption SDK v0.7.0)

View Source

AWS Encryption SDK for Elixir.

This module provides client-side encryption following the official AWS Encryption SDK Specification, enabling interoperability with AWS Encryption SDK implementations in other languages (Python, Java, JavaScript, C, CLI).

Quick Start with Client

The recommended API uses the Client module for commitment policy enforcement:

# Create a keyring
key = :crypto.strong_rand_bytes(32)
{:ok, keyring} = AwsEncryptionSdk.Keyring.RawAes.new("namespace", "key-name", key, :aes_256_gcm)

# Create a CMM
cmm = AwsEncryptionSdk.Cmm.Default.new(keyring)

# Create a client (defaults to strictest commitment policy)
client = AwsEncryptionSdk.Client.new(cmm)

# Encrypt
{:ok, result} = AwsEncryptionSdk.encrypt(client, "secret data",
  encryption_context: %{"purpose" => "example"}
)

# Decrypt
{:ok, decrypt_result} = AwsEncryptionSdk.decrypt(client, result.ciphertext)

Client-Based API

Streaming API

For large files or memory-constrained environments:

# Encrypt a large file
File.stream!("large_file.bin", [], 4096)
|> AwsEncryptionSdk.encrypt_stream(client)
|> Stream.into(File.stream!("encrypted.bin"))
|> Stream.run()

Materials-Based API (Advanced)

For advanced use cases or testing, you can use the materials-based API:

Security

The SDK follows the AWS Encryption SDK specification security requirements:

  • Never releases unauthenticated plaintext
  • Supports key commitment for enhanced security (recommended)
  • Validates all authentication tags before returning data
  • Enforces encryption context validation
  • Commitment policy prevents algorithm downgrade attacks

Guides

Streaming Support

This SDK supports both batch and streaming encryption/decryption:

For large files, use the streaming API to avoid memory issues.

Summary

Functions

Creates a stream that decrypts ciphertext chunks.

Decrypts ciphertext using a keyring directly.

Decrypts an AWS Encryption SDK message using pre-assembled decryption materials.

Encrypts plaintext using a client configuration.

Creates a stream that encrypts plaintext chunks.

Encrypts plaintext using a keyring directly.

Encrypts plaintext using pre-assembled encryption materials.

Functions

decrypt(client_or_ciphertext, ciphertext_or_materials, opts \\ [])

Decrypts an AWS Encryption SDK message.

Accepts either a Client (recommended) or DecryptionMaterials (advanced use).

Parameters

  • client_or_ciphertext - Either:
    • %Client{} - Client with CMM and commitment policy (recommended)
    • ciphertext - Complete encrypted message (for materials-based API)
  • ciphertext_or_materials - Either:
    • ciphertext - Complete encrypted message (when first arg is Client)
    • %DecryptionMaterials{} - Pre-assembled materials (advanced)
  • opts - Options (only used with Client):
    • :encryption_context - Reproduced context to validate

Returns

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

Examples

# With Client (recommended)
keyring = create_keyring()
cmm = Cmm.Default.new(keyring)
client = Client.new(cmm)

{:ok, result} = AwsEncryptionSdk.decrypt(client, ciphertext)

# With materials (advanced, backward compatibility)
materials = create_materials()
{:ok, result} = AwsEncryptionSdk.decrypt(ciphertext, materials)

decrypt_stream(ciphertext_stream, client, opts \\ [])

Creates a stream that decrypts ciphertext chunks.

See AwsEncryptionSdk.Stream.decrypt/3 for details.

Example

File.stream!("encrypted.bin", [], 4096)
|> AwsEncryptionSdk.decrypt_stream(client)
|> Stream.map(fn {plaintext, _status} -> plaintext end)
|> Stream.into(File.stream!("output.bin"))
|> Stream.run()

decrypt_with_keyring(keyring, ciphertext, opts \\ [])

Decrypts ciphertext using a keyring directly.

Convenience function that creates a Default CMM and Client automatically.

Parameters

  • keyring - A keyring struct (RawAes, RawRsa, or Multi)
  • ciphertext - Complete encrypted message
  • opts - Options:
    • :commitment_policy - Override default policy
    • :max_encrypted_data_keys - Override default limit
    • :encryption_context - Reproduced context to validate

Examples

keyring = RawAes.new("ns", "key", key_bytes, :aes_256_gcm)

{:ok, result} = AwsEncryptionSdk.decrypt_with_keyring(keyring, ciphertext,
  commitment_policy: :require_encrypt_allow_decrypt
)

decrypt_with_materials(ciphertext, materials)

@spec decrypt_with_materials(
  binary(),
  AwsEncryptionSdk.Materials.DecryptionMaterials.t()
) ::
  {:ok, AwsEncryptionSdk.Decrypt.decrypt_result()} | {:error, term()}

Decrypts an AWS Encryption SDK message using pre-assembled decryption materials.

This is an advanced API for testing or specialized use cases. In the future, use decrypt/2 with a Client instead.

Parameters

  • ciphertext - Complete encrypted message
  • materials - Decryption materials containing the plaintext data key

Returns

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

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

Encrypts plaintext using a client configuration.

This is the recommended encryption API that enforces commitment policy and integrates with the CMM layer.

For backward compatibility, also accepts EncryptionMaterials as the first argument (delegates to encrypt_with_materials/3).

Parameters

  • client - Client with CMM and commitment policy configuration
  • plaintext - Binary data to encrypt
  • opts - Options (see Client.encrypt/3)

Returns

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

Examples

# Create client and encrypt
keyring = create_keyring()
cmm = Cmm.Default.new(keyring)
client = Client.new(cmm)

{:ok, result} = AwsEncryptionSdk.encrypt(client, "secret data",
  encryption_context: %{"purpose" => "example"}
)

encrypt_stream(plaintext_stream, client, opts \\ [])

Creates a stream that encrypts plaintext chunks.

See AwsEncryptionSdk.Stream.encrypt/3 for details.

Example

File.stream!("input.bin", [], 4096)
|> AwsEncryptionSdk.encrypt_stream(client)
|> Stream.into(File.stream!("output.encrypted"))
|> Stream.run()

encrypt_with_keyring(keyring, plaintext, opts \\ [])

Encrypts plaintext using a keyring directly.

Convenience function that creates a Default CMM and Client automatically.

Parameters

  • keyring - A keyring struct (RawAes, RawRsa, or Multi)
  • plaintext - Binary data to encrypt
  • opts - Options (see Client.encrypt_with_keyring/3)

Examples

keyring = RawAes.new("ns", "key", key_bytes, :aes_256_gcm)

{:ok, result} = AwsEncryptionSdk.encrypt_with_keyring(keyring, "secret",
  encryption_context: %{"purpose" => "test"}
)

encrypt_with_materials(materials, plaintext, opts \\ [])

@spec encrypt_with_materials(
  AwsEncryptionSdk.Materials.EncryptionMaterials.t(),
  binary(),
  keyword()
) :: {:ok, AwsEncryptionSdk.Encrypt.encrypt_result()} | {:error, term()}

Encrypts plaintext using pre-assembled encryption materials.

This is an advanced API for testing or specialized use cases. Most applications should use encrypt/3 with a Client instead.

Parameters

Returns

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

Examples

# Advanced: manually assemble materials
suite = AlgorithmSuite.aes_256_gcm_hkdf_sha512_commit_key()
plaintext_data_key = :crypto.strong_rand_bytes(32)
edk = EncryptedDataKey.new("provider", "key-info", plaintext_data_key)

materials = EncryptionMaterials.new(suite, %{"key" => "value"}, [edk], plaintext_data_key)

{:ok, result} = AwsEncryptionSdk.encrypt_with_materials(materials, "data")