ProtoRune.Security.Crypto (proto_rune v0.5.2)

Copy Markdown

Authenticated encryption utilities for session tokens at rest.

Uses AES-256-GCM from :crypto (OTP standard library, no extra dependencies). Ciphertexts are versioned, authenticated, and Base64-encoded so they can be stored as plain text by any ProtoRune.Security.TokenStore backend.

Keys are 32-byte binaries. Generate one with generate_key/0 and keep it outside the token storage itself (environment variable, secret manager, etc). encode_key/1 and decode_key/1 convert keys to and from Base64 for exactly that purpose.

Summary

Types

A 32-byte AES-256 key.

Functions

Decodes a Base64-encoded key produced by encode_key/1.

Decrypts a blob produced by encrypt/2.

Encodes a key as Base64 for storage in environment variables or config.

Encrypts a binary payload with AES-256-GCM.

Generates a random 32-byte encryption key.

Types

key()

@type key() :: <<_::256>>

A 32-byte AES-256 key.

Functions

decode_key(encoded)

@spec decode_key(String.t()) ::
  {:ok, key()} | {:error, :invalid_key_size | :invalid_key_encoding}

Decodes a Base64-encoded key produced by encode_key/1.

Returns {:error, :invalid_key_size} when the decoded key is not 32 bytes and {:error, :invalid_key_encoding} when the input is not valid Base64.

decrypt(blob, key)

@spec decrypt(String.t(), key()) ::
  {:ok, binary()} | {:error, :invalid_key | :invalid_blob | :decrypt_failed}

Decrypts a blob produced by encrypt/2.

Returns {:error, :decrypt_failed} when the key is wrong or the blob was tampered with, and {:error, :invalid_blob} when the input is not a blob produced by encrypt/2.

encode_key(key)

@spec encode_key(key()) :: String.t()

Encodes a key as Base64 for storage in environment variables or config.

encrypt(plaintext, key)

@spec encrypt(binary(), key()) :: {:ok, String.t()} | {:error, :invalid_key}

Encrypts a binary payload with AES-256-GCM.

Returns a Base64-encoded blob containing the format version, the random IV, the authentication tag, and the ciphertext.

Examples

{:ok, blob} = Crypto.encrypt("secret", key)
{:ok, "secret"} = Crypto.decrypt(blob, key)

generate_key()

@spec generate_key() :: key()

Generates a random 32-byte encryption key.

Examples

key = Crypto.generate_key()
byte_size(key)
#=> 32