Cryptographic primitives for WhatsApp Web protocol communication.
Provides a clean Elixir API wrapping Erlang's :crypto module for all symmetric
and asymmetric operations: AES (GCM, CBC, CTR), HMAC, hashing, HKDF key derivation,
PBKDF2, Curve25519 ECDH, and Ed25519 signing.
HKDF (RFC 5869) is implemented in pure Elixir since OTP does not expose it directly.
All other operations delegate to :crypto (backed by OpenSSL/LibreSSL).
Summary
Functions
Decrypt AES-256-CBC and remove PKCS7 padding.
Encrypt with AES-256-CBC and PKCS7 padding.
Decrypt AES-256-CTR (symmetric with encrypt).
Encrypt with AES-256-CTR (stream cipher, no padding needed).
Decrypt AES-256-GCM. Expects ciphertext <> 16-byte tag as input.
Encrypt with AES-256-GCM. Returns {:ok, ciphertext <> 16-byte tag}.
Sign a message with an Ed25519 private key.
Verify an Ed25519 signature. Returns true if valid, false otherwise.
Expand a 32-byte media key to 112 bytes using HKDF with a type-specific info string.
Generate a key pair for the given curve.
HMAC-based Key Derivation Function (RFC 5869) using SHA-256.
HKDF expand step: expand a pseudorandom key to the desired length.
HKDF extract step: derive a pseudorandom key from input keying material.
Compute HMAC-SHA256.
Compute HMAC-SHA512.
Compute MD5 digest.
PBKDF2 key derivation with HMAC-SHA256.
Apply PKCS7 padding to align data to the given block size.
Remove PKCS7 padding. Returns {:error, :invalid_padding} if padding is malformed.
Generate n cryptographically strong random bytes.
Compute SHA-256 digest.
Compute X25519 shared secret from a private key and a peer's public key.
Types
Functions
@spec aes_cbc_decrypt(<<_::256>>, <<_::128>>, binary()) :: {:ok, binary()} | {:error, :decrypt_failed}
Decrypt AES-256-CBC and remove PKCS7 padding.
Returns {:error, :decrypt_failed} on invalid padding.
Encrypt with AES-256-CBC and PKCS7 padding.
Decrypt AES-256-CTR (symmetric with encrypt).
Encrypt with AES-256-CTR (stream cipher, no padding needed).
@spec aes_gcm_decrypt(<<_::256>>, binary(), binary(), binary()) :: {:ok, binary()} | {:error, :decrypt_failed}
Decrypt AES-256-GCM. Expects ciphertext <> 16-byte tag as input.
Returns {:ok, plaintext} or {:error, :decrypt_failed} if authentication fails.
Encrypt with AES-256-GCM. Returns {:ok, ciphertext <> 16-byte tag}.
The 16-byte authentication tag is appended to the ciphertext, matching the WhatsApp wire format where tag is suffixed.
Sign a message with an Ed25519 private key.
Verify an Ed25519 signature. Returns true if valid, false otherwise.
@spec expand_media_key(<<_::256>>, BaileysEx.Media.Types.media_type()) :: media_keys()
Expand a 32-byte media key to 112 bytes using HKDF with a type-specific info string.
Returns a map with :iv (16 bytes), :cipher_key (32 bytes),
:mac_key (32 bytes), and :ref_key (32 bytes).
Generate a key pair for the given curve.
:x25519— Curve25519 key pair for Diffie-Hellman key exchange:ed25519— Ed25519 key pair for digital signatures
@spec hkdf(binary(), binary(), pos_integer(), binary()) :: {:ok, binary()}
HMAC-based Key Derivation Function (RFC 5869) using SHA-256.
Derives length bytes of keying material from input keying material (ikm),
optional salt, and application-specific info.
When salt is empty or omitted, a zero-filled salt of hash length (32 bytes) is used
per the RFC specification.
@spec hkdf_expand(<<_::256>>, binary(), pos_integer()) :: binary()
HKDF expand step: expand a pseudorandom key to the desired length.
Iteratively produces output blocks using HMAC-SHA256 with counter bytes. Maximum output length is 255 * 32 = 8160 bytes.
HKDF extract step: derive a pseudorandom key from input keying material.
Uses HMAC-SHA256 with the given salt (or 32 zero bytes if salt is empty).
Compute HMAC-SHA256.
Compute HMAC-SHA512.
@spec md5(iodata()) :: <<_::128>>
Compute MD5 digest.
@spec pbkdf2_sha256(binary(), binary(), pos_integer(), pos_integer()) :: {:ok, binary()}
PBKDF2 key derivation with HMAC-SHA256.
Used for pairing code derivation (131,072 iterations).
@spec pkcs7_pad(binary(), pos_integer()) :: binary()
Apply PKCS7 padding to align data to the given block size.
Adds 1 to block_size bytes of padding, where each padding byte's value
equals the number of padding bytes added.
@spec pkcs7_unpad(binary(), pos_integer()) :: {:ok, binary()} | {:error, :invalid_padding}
Remove PKCS7 padding. Returns {:error, :invalid_padding} if padding is malformed.
@spec random_bytes(non_neg_integer()) :: binary()
Generate n cryptographically strong random bytes.
@spec sha256(iodata()) :: <<_::256>>
Compute SHA-256 digest.