Hey all — I open-sourced an Elixir library that a few people in my previous threads might find useful.
metamorphic_crypto is a NaCl-compatible encryption library for Elixir with post-quantum support, powered by a Rust NIF core with precompiled binaries. It provides:
- Symmetric encryption — XSalsa20-Poly1305 (NaCl secretbox)
- Public-key encryption — X25519 sealed boxes
- Hybrid post-quantum encryption — ML-KEM-768 + X25519 (NIST FIPS 203)
- Key derivation — Argon2id (libsodium-compatible parameters)
- Recovery keys — human-readable backup codes (like Signal/Matrix)
- Auto-detecting ciphertext — seals with PQ when available, falls back to classical, detects format on decrypt
The Rust core is #![forbid(unsafe_code)], built entirely on audited RustCrypto primitives, and ships via rustler_precompiled — so it’s just mix deps.get for end users. No Rust toolchain, no C compiler, no system packages.
Why I built this: If you’ve ever tried to get enacl compiling on a fresh machine or in CI, you know the pain — libsodium headers, C toolchain, breakage on OTP upgrades. This library produces identical NaCl ciphertext but ships as precompiled binaries. It also adds ML-KEM-768 post-quantum encryption that nothing else on Hex offers.
What it’s for:
- Swap-in for some
enaclfunctions — same wire format, no data migration, no libsodium dependency - Server-side NaCl-compatible crypto in Phoenix apps
- Post-quantum encryption (ML-KEM-768 + X25519, first on Hex)
- Wire compatibility with browser WASM clients (same Rust core compiles to both NIF and WASM)
What it’s NOT: This library runs server-side. It doesn’t give you client-side zero-knowledge encryption by itself. For full ZK where the server never sees plaintext, you need client-side crypto in the browser (we use WASM). But if your server needs NaCl crypto — key generation, sealing to recipients, test fixtures, or a migration path toward ZK — this is the tool.
If you’re using enacl today, the secretbox and sealed box operations are wire-compatible. You can swap those calls with no data migration.
What’s next: I’m transitioning Mosslet (currently using enacl) to this library as a first step — it’s a straightforward swap that gives us precompiled binaries and PQ-readiness before we add the client-side WASM layer.
Zero-Knowledge: This repo also seemed a fitting place to include a Zero-Knowledge Phoenix Guide that walks through implementing full client-side encryption in LiveView — the architecture behind Metamorphic. The guide covers the WASM client setup, key hierarchy, LiveView hooks, and where the server-side library fits in (spoiler: for a full ZK app, the server mostly just stores opaque blobs).
elixir
# mix.exs
{:metamorphic_crypto, "~> 0.1”}
elixir
key = MetamorphicCrypto.generate_key()
{:ok, ct} = MetamorphicCrypto.encrypt("hello", key)
{:ok, "hello"} = MetamorphicCrypto.decrypt(ct, key)
# Post-quantum hybrid
{pk, sk} = MetamorphicCrypto.Hybrid.generate_keypair()
{:ok, sealed} = MetamorphicCrypto.Hybrid.seal("quantum-safe", pk)
{:ok, "quantum-safe"} = MetamorphicCrypto.Hybrid.open(sealed, sk)
Hex: hex.pm/packages/metamorphic_crypto
Happy to answer questions or hear feedback.
For context on the architecture behind this, I wrote about the zero-knowledge LiveView encryption approach and the Mosslet project in earlier posts.






















