Module crypto

Data Types

cipher_aead()


cipher_aead() = aes_128_gcm | aes_192_gcm | aes_256_gcm | aes_128_ccm | aes_192_ccm | aes_256_ccm | chacha20_poly1305

cipher_iv()


cipher_iv() = aes_128_cbc | aes_192_cbc | aes_256_cbc | aes_128_cfb128 | aes_192_cfb128 | aes_256_cfb128 | aes_128_ctr | aes_192_ctr | aes_256_ctr | aes_128_ofb | aes_192_ofb | aes_256_ofb

cipher_no_iv()


cipher_no_iv() = aes_128_ecb | aes_192_ecb | aes_256_ecb

cmac_subtype()


cmac_subtype() = aes_128_cbc | aes_128_ecb | aes_192_cbc | aes_192_ecb | aes_256_cbc | aes_256_ecb

crypto_opt()


crypto_opt() = {encrypt, boolean()} | {padding, padding()}

crypto_opts()


crypto_opts() = boolean() | [crypto_opt()]

crypto_state()

abstract datatype: crypto_state()

digest()


digest() = binary()

ec_named_curve()


ec_named_curve() = secp256k1 | secp256r1 | secp384r1 | secp521r1 | brainpoolP256r1 | brainpoolP384r1 | brainpoolP512r1

ecdh_params()


ecdh_params() = ec_named_curve() | edwards_curve_dh()

ecdsa_digest_type()


ecdsa_digest_type() = sha1() | sha2()

ecdsa_params()


ecdsa_params() = ec_named_curve()

ecdsa_private()


ecdsa_private() = binary()

ecdsa_public()


ecdsa_public() = binary()

eddsa_params()


eddsa_params() = edwards_curve_ed()

eddsa_private()


eddsa_private() = binary()

eddsa_public()


eddsa_public() = binary()

edwards_curve_dh()


edwards_curve_dh() = x25519

Supported EdDSA curve (Ed25519 via libsodium when AVM_USE_LIBSODIUM is enabled).

edwards_curve_ed()


edwards_curve_ed() = ed25519

hash_algorithm()


hash_algorithm() = md5 | sha | sha224 | sha256 | sha384 | sha512

hash_state()

abstract datatype: hash_state()

mac_state()

abstract datatype: mac_state()

mac_subtype()


mac_subtype() = cmac_subtype() | hash_algorithm() | ripemd160

mac_type()


mac_type() = cmac | hmac

padding()


padding() = none | pkcs_padding

sha1()


sha1() = sha

sha2()


sha2() = sha224 | sha256 | sha384 | sha512

Function Index

compute_key/4 Compute a shared secret.
crypto_final/1 Finalize a streaming cipher operation.
crypto_init/3 Initialize a streaming cipher operation for ciphers that do not use an IV.
crypto_init/4 Initialize a streaming cipher operation.
crypto_one_time/4 Encrypted/decrypt data using given cipher and key.
crypto_one_time/5 Encrypted/decrypt data using given cipher, key, IV.
crypto_one_time_aead/6 Encrypt data using an AEAD cipher with the default tag length.
crypto_one_time_aead/7 Encrypt or decrypt data using an AEAD cipher.
crypto_update/2 Feed data into a streaming cipher operation.
generate_key/2 Generate a public/private key pair.
hash/2 Hash data using a specified hash algorithm.
hash_equals/2 Compare two MACs or hashes for equality in constant time.
hash_final/1 Finalize a streaming hash computation and return the digest.
hash_init/1 Initialize a streaming hash computation.
hash_update/2 Update a streaming hash computation with new data.
info_lib/0 Get the name and version of the libraries used by crypto.
mac/4 Compute a MAC.
mac_final/1 Finalize a streaming MAC operation and return the MAC value.
mac_finalN/2 Finalize a streaming MAC operation with a custom output length.
mac_init/3 Initialize a streaming MAC operation.
mac_update/2 Add data to a streaming MAC calculation.
pbkdf2_hmac/5 Derive a key using PBKDF2-HMAC (RFC 8018 §5.2).
sign/4 Create a digital signature.
strong_rand_bytes/1 Generate N cryptographically secure random octets and return the result in a binary.
verify/5 Verify a digital signature.

Function Details

compute_key/4


compute_key(Type::ecdh | eddh, OtherPublicKey::binary(), MyPrivateKey::binary(), Param::ecdh_params()) -> binary()

Type: the key agreement type
OtherPublicKey: peer public key (binary)
MyPrivateKey: local private key (binary)
Param: curve/parameter selection

returns: Returns the shared secret as a binary.

Compute a shared secret.

Supported forms:

  • eddh with x25519

  • ecdh with x25519 | secp256k1 | secp256r1 | secp384r1 | secp521r1 | brainpoolP256r1 | brainpoolP384r1 | brainpoolP512r1

The public/private key binaries must be in the same format as returned by generate_key/2.

For x25519, the returned value is the raw shared secret. Applications should derive a symmetric key from it with a KDF before use.

crypto_final/1


crypto_final(State::crypto_state()) -> binary()

State: an opaque cipher state returned from crypto_init/3 orcrypto_init/4

returns: Returns any remaining bytes (e.g. a padded final block) as a binary, or <<>> if there are none.

Finalize a streaming cipher operation.

For block ciphers with {padding, none} an error is raised if the total data fed was not a multiple of the block size.

AtomVM limitation: after crypto_final/1 returns, the state is permanently finalized. Calling crypto_final/1 again, or calling crypto_update/2 on the same state, raises a badarg error. OTP allows reuse of the state after crypto_final/1.

crypto_init/3


crypto_init(Cipher::cipher_no_iv(), Key::iodata(), FlagOrOptions::crypto_opts()) -> crypto_state()

Cipher: a supported cipher (no IV required, e.g. ECB modes)
Key: the encryption / decryption key
FlagOrOptions: either true for encryption, false for decryption, or a proplist with options such as {encrypt, boolean()} and{padding, padding()}.

returns: Returns an opaque crypto_state() reference for use with crypto_update/2 and crypto_final/1.

Initialize a streaming cipher operation for ciphers that do not use an IV.

This is equivalent to crypto_init(Cipher, Key, <<>>, FlagOrOptions).

crypto_init/4


crypto_init(Cipher::cipher_no_iv() | cipher_iv(), Key::iodata(), IV::iodata(), FlagOrOptions::crypto_opts()) -> crypto_state()

Cipher: a supported cipher
Key: the encryption / decryption key
IV: an initialization vector (use <<>> for ciphers that do not require one)
FlagOrOptions: either true for encryption, false for decryption, or a proplist with options such as {encrypt, boolean()} and{padding, padding()}.

returns: Returns an opaque crypto_state() reference for use with crypto_update/2 and crypto_final/1.

Initialize a streaming cipher operation.

The returned state is mutable: crypto_update/2 and crypto_final/1 mutate it in place. After crypto_final/1 the state must not be reused.

AtomVM padding support: {padding, pkcs_padding} is supported only with CBC ciphers (e.g. aes_128_cbc, aes_192_cbc, aes_256_cbc). Requesting PKCS7 padding with ECB or any other cipher mode raises a badarg error. This differs from OTP, which silently accepts the option for non-CBC modes.

crypto_one_time/4


crypto_one_time(Cipher::cipher_no_iv(), Key::iodata(), Data::iodata(), FlagOrOptions::crypto_opts()) -> binary()

Cipher: a supported cipher
Key: the encryption / decryption key
Data: to be crypted or encrypted
FlagOrOptions: either just true for encryption (or false for decryption), or a proplist for any additional option

returns: Returns crypted or encrypted data.

Encrypted/decrypt data using given cipher and key

crypto_one_time/5


crypto_one_time(Cipher::cipher_iv(), Key::iodata(), IV::iodata(), Data::iodata(), FlagOrOptions::crypto_opts()) -> binary()

Cipher: a supported cipher that makes use of IV
Key: the encryption / decryption key
IV: an initialization vector
Data: to be crypted or encrypted
FlagOrOptions: either just true for encryption (or false for decryption), or a proplist for any additional option such as padding.

returns: Returns crypted or encrypted data.

Encrypted/decrypt data using given cipher, key, IV.

crypto_one_time_aead/6


crypto_one_time_aead(Cipher::cipher_aead(), Key::iodata(), IV::iodata(), InText::iodata(), AAD::iodata(), EncFlag::true) -> {binary(), binary()}

Cipher: an AEAD cipher
Key: the encryption key
IV: nonce / initialization vector
InText: plaintext to encrypt (iodata)
AAD: additional authenticated data (iodata)
EncFlag: true for encryption

returns: Returns {CipherText, Tag} on success.

Encrypt data using an AEAD cipher with the default tag length.

Supported ciphers: aes_128_gcm, aes_192_gcm, aes_256_gcm, aes_128_ccm, aes_192_ccm, aes_256_ccm, chacha20_poly1305.

crypto_one_time_aead/7


crypto_one_time_aead(Cipher::cipher_aead(), Key::iodata(), IV::iodata(), InText::iodata(), AAD::iodata(), TagOrTagLength::non_neg_integer() | binary(), EncFlag::boolean()) -> {binary(), binary()} | binary() | error

Cipher: an AEAD cipher
Key: the encryption / decryption key
IV: nonce / initialization vector
InText: plaintext (encrypt) or ciphertext (decrypt) (iodata)
AAD: additional authenticated data (iodata)
TagOrTagLength: integer tag length when encrypting, tag binary when decrypting
EncFlag: true for encryption, false for decryption

returns: Encryption: {CipherText, Tag}. Decryption: plaintext binary, or error on authentication failure.

Encrypt or decrypt data using an AEAD cipher.

When decrypting, authentication failure returns the atom error rather than raising an exception, matching OTP behaviour.

crypto_update/2


crypto_update(State::crypto_state(), Data::iodata()) -> binary()

State: an opaque cipher state returned from crypto_init/3 orcrypto_init/4
Data: the data to encrypt or decrypt (iodata)

returns: Returns the encrypted/decrypted bytes produced so far as a binary.

Feed data into a streaming cipher operation.

For block ciphers the output may be shorter than the input if an incomplete block is buffered internally.

generate_key/2


generate_key(Type::ecdh | eddh | eddsa, Param::ecdh_params() | eddsa_params()) -> {binary(), binary()}

Type: the key algorithm family
Param: curve/parameter selection

returns: Returns a tuple {PublicKey, PrivateKey}.

Generate a public/private key pair.

Supported forms:

  • eddh with x25519

  • ecdh with x25519 | secp256k1 | secp256r1 | secp384r1 | secp521r1 | brainpoolP256r1 | brainpoolP384r1 | brainpoolP512r1

  • eddsa with ed25519

Keys are returned as raw key material, not PEM, DER, or public_key records.

Key generation draws from the platform entropy source. Consult your platform documentation to ensure the hardware RNG is properly seeded before generating keys.

hash/2


hash(Type::hash_algorithm(), Data::iolist()) -> digest()

Type: the hash algorithm
Data: the data to hash

returns: Returns the result of hashing the supplied data using the supplied hash algorithm.

Hash data using a specified hash algorithm.

hash_equals/2


hash_equals(Mac1::binary(), Mac2::binary()) -> boolean()

Mac1: first MAC or hash binary
Mac2: second MAC or hash binary

returns: Returns true if the two binaries are equal, false otherwise.

Compare two MACs or hashes for equality in constant time.

Both arguments must be binaries of the same length; otherwise an error is raised. The comparison is performed in constant time to prevent timing side-channel attacks.

hash_final/1


hash_final(State::hash_state()) -> digest()

State: an opaque hash state returned from hash_init/1 orhash_update/2

returns: Returns the final hash digest as a binary.

Finalize a streaming hash computation and return the digest.

The state is not consumed; calling hash_final/1 again on the same state will produce the same digest.

hash_init/1


hash_init(Type::hash_algorithm()) -> hash_state()

Type: the hash algorithm

returns: Returns an opaque hash state that can be passed to hash_update/2 and hash_final/1.

Initialize a streaming hash computation.

hash_update/2


hash_update(State::hash_state(), Data::iolist()) -> hash_state()

State: an opaque hash state returned from hash_init/1 or a previous call to hash_update/2
Data: the data to feed into the hash computation

returns: Returns a new opaque hash state with the supplied data folded in.

Update a streaming hash computation with new data.

The original State is not modified; a new state is returned so the same state can be forked into independent hash computations.

info_lib/0


info_lib() -> [{binary(), integer(), binary()}]

returns: Returns a list of tuples describing the crypto libraries used by crypto.

Get the name and version of the libraries used by crypto.

Returns a list of one or more tuples {Name, VerNum, VerStr} where:

  • Name is the library name as a binary (for example, <<"mbedtls">> or <<"libsodium">>)

  • VerNum is the numeric version according to the library’s versioning scheme

  • VerStr is the version string as a binary

AtomVM may return multiple entries, for example one for Mbed TLS and one for libsodium.

Example: [{<<"mbedtls">>, 50790144, <<"Mbed TLS 3.6.1">>}]

mac/4


mac(Type::mac_type(), SubType::mac_subtype(), Key::binary(), Data::iodata()) -> binary()

Type: MAC algorithm family (cmac or hmac)
SubType: MAC subtype (cipher for CMAC, digest for HMAC)
Key: MAC key bytes
Data: message bytes (iodata)

returns: Returns the computed MAC as a binary.

Compute a MAC.

Supported forms:

  • mac(cmac, Cipher, Key, Data) where Cipher selects AES key size: aes_128_(cbc|ecb) | aes_192_(cbc|ecb) | aes_256_(cbc|ecb) (key length must match the selected size)

  • mac(hmac, Digest, Key, Data) where Digest is a supported hash atom (AtomVM accepts ripemd160 in addition to the hash/2 digests)

mac_final/1


mac_final(State::mac_state()) -> binary()

State: MAC state from mac_init/3 or mac_update/2

returns: Returns the computed MAC as a binary.

Finalize a streaming MAC operation and return the MAC value.

mac_finalN/2


mac_finalN(State::mac_state(), MacLength::pos_integer()) -> binary()

State: MAC state from mac_init/3 or mac_update/2
MacLength: desired output length in bytes

returns: Returns the computed MAC truncated to MacLength bytes.

Finalize a streaming MAC operation with a custom output length.

mac_init/3


mac_init(Type::mac_type(), SubType::mac_subtype(), Key::iodata()) -> mac_state()

Type: MAC algorithm family (cmac or hmac)
SubType: MAC subtype (cipher for CMAC, digest for HMAC)
Key: MAC key bytes (iodata)

returns: Returns an opaque MAC state for use with mac_update/2 and mac_final/1.

Initialize a streaming MAC operation.

mac_update/2


mac_update(State::mac_state(), Data::iodata()) -> mac_state()

State: MAC state from mac_init/3 or a previous mac_update/2
Data: data to add (iodata)

returns: Returns an updated MAC state.

Add data to a streaming MAC calculation.

pbkdf2_hmac/5


pbkdf2_hmac(DigestType::hash_algorithm(), Password::iodata(), Salt::iodata(), Iterations::pos_integer(), KeyLen::pos_integer()) -> binary()

DigestType: hash algorithm (sha, sha256, etc.)
Password: password bytes (iodata)
Salt: salt bytes (iodata)
Iterations: iteration count (positive integer)
KeyLen: desired output length in bytes (positive integer)

returns: Returns the derived key as a binary of KeyLen bytes.

Derive a key using PBKDF2-HMAC (RFC 8018 §5.2).

Supported digest types are the same as for hash/2.

sign/4


sign(Algorithm::ecdsa | eddsa, DigestType::ecdsa_digest_type() | none, Msg::iodata(), Key::[ecdsa_private() | ecdsa_params()] | [eddsa_private() | eddsa_params()]) -> binary()

Algorithm: signing algorithm (ecdsa or eddsa)
DigestType: hash algorithm identifier for ecdsa, or none for eddsa
Msg: message bytes (iodata)
Key: signing key material

returns: Returns the signature as a binary.

Create a digital signature.

AtomVM currently supports:

  • Algorithm = ecdsa

  • Key = [PrivateKeyBin, Curve] where Curve is one of secp256k1 | secp256r1 | secp384r1 | secp521r1 | brainpoolP256r1 | brainpoolP384r1 | brainpoolP512r1

  • Algorithm = eddsa (requires build with libsodium support)

  • Key = [PrivateKeyBin, ed25519] and DigestType = none

Signature encoding depends on Algorithm:

  • ecdsa returns a DER-encoded signature

  • eddsa with ed25519 returns a raw 64-byte Ed25519 signature

ECDSA signing requires a random nonce internally. The quality of this nonce depends on the platform entropy source. Consult your platform documentation to ensure the hardware RNG is properly seeded; a predictable nonce can lead to private key recovery.

strong_rand_bytes/1


strong_rand_bytes(N::non_neg_integer()) -> binary()

N: desired length of cryptographically secure random data

returns: Returns Cryptographically secure random data of length N

Generate N cryptographically secure random octets and return the result in a binary.

The quality of the output depends on the platform entropy source. Consult your platform documentation to ensure the hardware RNG is properly seeded before using this function for key material or other security-sensitive purposes.

verify/5


verify(Algorithm::ecdsa | eddsa, DigestType::ecdsa_digest_type() | none, Msg::iodata(), Signature::binary(), Key::[ecdsa_public() | ecdsa_params()] | [eddsa_public() | eddsa_params()]) -> boolean()

Algorithm: verification algorithm (ecdsa or eddsa)
DigestType: hash algorithm identifier for ecdsa, or none for eddsa
Msg: message bytes (iodata)
Signature: signature to verify
Key: verification key material

returns: Returns true if the signature is valid, otherwise false.

Verify a digital signature.

AtomVM currently supports:

  • Algorithm = ecdsa

  • Key = [PublicKeyBin, Curve] where Curve is one of secp256k1 | secp256r1 | secp384r1 | secp521r1 | brainpoolP256r1 | brainpoolP384r1 | brainpoolP512r1

  • Algorithm = eddsa (requires build with libsodium support)

  • Key = [PublicKeyBin, ed25519] and DigestType = none

Signature encoding depends on Algorithm:

  • ecdsa expects a DER-encoded signature

  • eddsa with ed25519 expects a raw 64-byte Ed25519 signature

Invalid signatures yield false (not an exception).