# `MetamorphicCrypto`
[🔗](https://github.com/moss-piglet/metamorphic_crypto/blob/main/lib/metamorphic_crypto.ex#L1)

Zero-knowledge end-to-end encryption for Elixir.

`MetamorphicCrypto` provides NaCl-compatible cryptographic primitives powered
by Rust NIFs with precompiled binaries — no Rust toolchain required.

## Quick Start

    # Generate keys
    key = MetamorphicCrypto.generate_key()
    {public_key, private_key} = MetamorphicCrypto.generate_keypair()

    # Symmetric encryption (XSalsa20-Poly1305)
    {:ok, ciphertext} = MetamorphicCrypto.encrypt("hello", key)
    {:ok, "hello"} = MetamorphicCrypto.decrypt(ciphertext, key)

    # Public-key encryption (X25519 sealed box)
    {:ok, sealed} = MetamorphicCrypto.seal("secret", public_key)
    {:ok, "secret"} = MetamorphicCrypto.unseal(sealed, public_key, private_key)

## Modules

For full control, use the specialized modules directly:

- `MetamorphicCrypto.SecretBox` — symmetric encryption
- `MetamorphicCrypto.BoxSeal` — public-key encryption
- `MetamorphicCrypto.Hybrid` — ML-KEM-768 + X25519 post-quantum
- `MetamorphicCrypto.Seal` — unified seal/unseal (auto-detects format)
- `MetamorphicCrypto.KDF` — Argon2id key derivation
- `MetamorphicCrypto.Keys` — key generation and management
- `MetamorphicCrypto.Recovery` — human-readable recovery keys

## Wire Format

All functions accept and return base64-encoded strings. Ciphertext produced
by this library is byte-compatible with libsodium/NaCl and the
`metamorphic-crypto` WASM module used in browser clients.

# `decrypt`

```elixir
@spec decrypt(ciphertext :: String.t(), key :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}
```

Decrypt a ciphertext back to a UTF-8 string.

## Example

    {:ok, "hello, world!"} = MetamorphicCrypto.decrypt(ciphertext, key)

# `encrypt`

```elixir
@spec encrypt(plaintext :: String.t(), key :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}
```

Encrypt a UTF-8 string with a symmetric key.

Uses XSalsa20-Poly1305 (NaCl secretbox). Returns base64-encoded ciphertext.

## Example

    key = MetamorphicCrypto.generate_key()
    {:ok, ciphertext} = MetamorphicCrypto.encrypt("hello, world!", key)

# `generate_key`

```elixir
@spec generate_key() :: String.t()
```

Generate a random 32-byte symmetric key (base64-encoded).

## Example

    key = MetamorphicCrypto.generate_key()

# `generate_keypair`

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

Generate an X25519 keypair.

Returns `{public_key, private_key}` as base64-encoded strings.

## Example

    {public_key, private_key} = MetamorphicCrypto.generate_keypair()

# `seal`

```elixir
@spec seal(plaintext :: String.t(), public_key :: String.t()) ::
  {:ok, String.t()} | {:error, String.t()}
```

Encrypt a UTF-8 string to a recipient's public key (anonymous sealed box).

The sender remains anonymous — only the recipient can decrypt.

## Example

    {public_key, _private_key} = MetamorphicCrypto.generate_keypair()
    {:ok, sealed} = MetamorphicCrypto.seal("secret message", public_key)

# `unseal`

```elixir
@spec unseal(
  ciphertext :: String.t(),
  public_key :: String.t(),
  private_key :: String.t()
) ::
  {:ok, String.t()} | {:error, String.t()}
```

Decrypt a sealed box using the recipient's keypair.

## Example

    {public_key, private_key} = MetamorphicCrypto.generate_keypair()
    {:ok, sealed} = MetamorphicCrypto.seal("secret", public_key)
    {:ok, "secret"} = MetamorphicCrypto.unseal(sealed, public_key, private_key)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
