MetamorphicCrypto.Hybrid (metamorphic_crypto v0.2.1)

Copy Markdown View Source

ML-KEM + X25519 hybrid post-quantum encryption.

Provides quantum-resistant key encapsulation by combining:

  • ML-KEM (NIST FIPS 203) — lattice-based post-quantum KEM
  • X25519 — classical elliptic-curve Diffie-Hellman

Security Levels

LevelML-KEMNIST CategoryEquivalentVersion Tag
Cat-37683~AES-1920x02
Cat-510245~AES-2560x03

Pass :cat3 or :cat5 to choose the security level. The default is :cat3.

Ciphertext formats

v2 (Cat-3): 0x02 || ML-KEM-768 ct (1088 B) || X25519 eph pk (32 B) || nonce (24 B) || secretbox ct
v3 (Cat-5): 0x03 || ML-KEM-1024 ct (1568 B) || X25519 eph pk (32 B) || nonce (24 B) || secretbox ct

Key sizes

ComponentCat-3Cat-5
Public key1216 bytes1600 bytes
Secret key (seed)32 bytes32 bytes

Usage

# Cat-3 (default)
{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair()
{:ok, ct} = MetamorphicCrypto.Hybrid.seal("quantum-safe secret", pk)
{:ok, "quantum-safe secret"} = MetamorphicCrypto.Hybrid.open(ct, sk)

# Cat-5 (ML-KEM-1024, highest security)
{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair(:cat5)
{:ok, ct} = MetamorphicCrypto.Hybrid.seal("top secret", pk, :cat5)
{:ok, "top secret"} = MetamorphicCrypto.Hybrid.open(ct, sk)

Summary

Types

NIST post-quantum security level.

Functions

Generate a hybrid ML-KEM + X25519 keypair.

Generate a hybrid ML-KEM-1024 + X25519 keypair (Cat-5, highest security).

Check if a base64 ciphertext uses the hybrid format (v2 Cat-3 or v3 Cat-5).

Open a hybrid-sealed ciphertext, returning the decrypted UTF-8 string.

Open a hybrid-sealed ciphertext, returning plaintext as base64.

Seal a UTF-8 plaintext string using hybrid post-quantum encryption.

Seal a UTF-8 plaintext string using Cat-5 hybrid post-quantum encryption (ML-KEM-1024).

Seal raw bytes (as base64) using hybrid post-quantum encryption.

Seal raw bytes (as base64) using Cat-5 hybrid post-quantum encryption.

Types

security_level()

@type security_level() :: :cat3 | :cat5

NIST post-quantum security level.

  • :cat3 — ML-KEM-768 + X25519 (~AES-192, NIST Category 3). Default.
  • :cat5 — ML-KEM-1024 + X25519 (~AES-256, NIST Category 5).

Functions

generate_keypair(level \\ :cat3)

@spec generate_keypair(security_level()) :: {String.t(), String.t()}

Generate a hybrid ML-KEM + X25519 keypair.

Accepts an optional security_level/0 (defaults to :cat3).

Returns {public_key_b64, secret_key_b64}.

Examples

# Cat-3 (default)
{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair()

# Cat-5
{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair(:cat5)

generate_keypair_1024()

@spec generate_keypair_1024() :: {String.t(), String.t()}

Generate a hybrid ML-KEM-1024 + X25519 keypair (Cat-5, highest security).

Convenience alias for generate_keypair(:cat5).

Returns {public_key_b64, secret_key_b64}.

Example

{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair_1024()

hybrid_ciphertext?(ciphertext_b64)

@spec hybrid_ciphertext?(ciphertext_b64 :: String.t()) :: boolean()

Check if a base64 ciphertext uses the hybrid format (v2 Cat-3 or v3 Cat-5).

Example

MetamorphicCrypto.Hybrid.hybrid_ciphertext?(ciphertext)
#=> true

open(ciphertext_b64, secret_key_b64)

@spec open(ciphertext_b64 :: String.t(), secret_key_b64 :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Open a hybrid-sealed ciphertext, returning the decrypted UTF-8 string.

Automatically detects whether the ciphertext is Cat-3 (v2) or Cat-5 (v3) based on the version tag byte.

Returns {:ok, plaintext} or {:error, reason}.

Example

{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair()
{:ok, ct} = MetamorphicCrypto.Hybrid.seal("hello PQ", pk)
{:ok, "hello PQ"} = MetamorphicCrypto.Hybrid.open(ct, sk)

open_raw(ciphertext_b64, secret_key_b64)

@spec open_raw(ciphertext_b64 :: String.t(), secret_key_b64 :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Open a hybrid-sealed ciphertext, returning plaintext as base64.

Automatically detects Cat-3 or Cat-5 from the version tag.

Returns {:ok, plaintext_b64} or {:error, reason}.

seal(plaintext, public_key_b64, level \\ :cat3)

@spec seal(plaintext :: String.t(), public_key_b64 :: String.t(), security_level()) ::
  {:ok, String.t()} | {:error, String.t()}

Seal a UTF-8 plaintext string using hybrid post-quantum encryption.

Accepts an optional security_level/0 (defaults to :cat3).

Returns {:ok, ciphertext_b64} or {:error, reason}.

Examples

# Cat-3 (default)
{pk, _sk} = MetamorphicCrypto.Hybrid.generate_keypair()
{:ok, ct} = MetamorphicCrypto.Hybrid.seal("secret data", pk)

# Cat-5
{pk, _sk} = MetamorphicCrypto.Hybrid.generate_keypair(:cat5)
{:ok, ct} = MetamorphicCrypto.Hybrid.seal("secret data", pk, :cat5)

seal_1024(plaintext, public_key_b64)

@spec seal_1024(plaintext :: String.t(), public_key_b64 :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Seal a UTF-8 plaintext string using Cat-5 hybrid post-quantum encryption (ML-KEM-1024).

Convenience alias for seal(plaintext, public_key_b64, :cat5).

Returns {:ok, ciphertext_b64} or {:error, reason}.

Example

{pk, _sk} = MetamorphicCrypto.Hybrid.generate_keypair(:cat5)
{:ok, ct} = MetamorphicCrypto.Hybrid.seal_1024("top secret", pk)

seal_raw(plaintext_b64, public_key_b64, level \\ :cat3)

@spec seal_raw(
  plaintext_b64 :: String.t(),
  public_key_b64 :: String.t(),
  security_level()
) ::
  {:ok, String.t()} | {:error, String.t()}

Seal raw bytes (as base64) using hybrid post-quantum encryption.

Accepts an optional security_level/0 (defaults to :cat3).

Returns {:ok, ciphertext_b64} or {:error, reason}.

seal_raw_1024(plaintext_b64, public_key_b64)

@spec seal_raw_1024(plaintext_b64 :: String.t(), public_key_b64 :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Seal raw bytes (as base64) using Cat-5 hybrid post-quantum encryption.

Convenience alias for seal_raw(plaintext_b64, public_key_b64, :cat5).

Returns {:ok, ciphertext_b64} or {:error, reason}.