macula_crypto_nif (macula v13.4.0)

View Source

Cryptographic operations for Macula mesh.

This module provides ML-DSA signatures, BLAKE3 and SHA-256 hashing, base64 encoding and constant-time comparison, in a Rust NIF.

NIF vs Erlang

Hashing, encoding and comparison fall back to pure Erlang when the NIF cannot be loaded; the Rust NIF is faster (BLAKE3 about 20x, SHA-256 about 3x). ML-DSA has no fallback, below.

ML-DSA

ML-DSA (FIPS 204) signatures are made and checked by macula-mldsa (D7), and have no Erlang fallback: without the NIF they raise. Sets take OTP's names (mldsa44, mldsa65, mldsa87). A private key is {seed, Seed}, the 32-byte seed new keys are stored as (D6), or {expanded, Key}, the form OTP generates. Signing is hedged, with randomness from the OS, and takes a FIPS 204 context string of at most 255 bytes.

Summary

Functions

Decode URL-safe base64 data. Returns {ok, Data} or {error, invalid_base64}.

Encode data as URL-safe base64 (no padding).

Compute BLAKE3 hash. Returns 32-byte hash binary.

Compute BLAKE3 hash and return as hex string. Returns 64-character hex string.

Check if the NIF is loaded.

A new ML-DSA key, kept as its 32-byte seed.

The public key of an ML-DSA private key in either form. An expanded key whose parts disagree is inconsistent_private_key.

A hedged ML-DSA signature over Message under the context string Context.

Whether Signature is a valid ML-DSA signature over Message under Context. False for anything FIPS 204 rejects, a context over 255 bytes included.

Constant-time comparison of two binaries. Important for security - prevents timing attacks.

Compute SHA-256 hash. Returns 32-byte hash binary.

Compute SHA-256 hash and encode as URL-safe base64. Returns base64-encoded string (no padding).

Types

mldsa_private_key/0

-type mldsa_private_key() :: {seed, <<_:256>>} | {expanded, binary()}.

mldsa_set/0

-type mldsa_set() :: mldsa44 | mldsa65 | mldsa87.

Functions

base64_decode(Encoded)

-spec base64_decode(Encoded :: binary()) -> {ok, binary()} | {error, atom()}.

Decode URL-safe base64 data. Returns {ok, Data} or {error, invalid_base64}.

base64_encode(Data)

-spec base64_encode(Data :: binary()) -> Encoded :: binary().

Encode data as URL-safe base64 (no padding).

blake3(Data)

-spec blake3(Data :: binary()) -> Hash :: binary().

Compute BLAKE3 hash. Returns 32-byte hash binary.

blake3_hex(Data)

-spec blake3_hex(Data :: binary()) -> HexHash :: binary().

Compute BLAKE3 hash and return as hex string. Returns 64-character hex string.

is_nif_loaded()

-spec is_nif_loaded() -> boolean().

Check if the NIF is loaded.

mldsa_generate(Set)

-spec mldsa_generate(mldsa_set()) ->
                        {ok, {PublicKey :: binary(), Seed :: <<_:256>>}} |
                        {error, randomness_unavailable}.

A new ML-DSA key, kept as its 32-byte seed.

mldsa_public_key(Set, _)

-spec mldsa_public_key(mldsa_set(), mldsa_private_key()) ->
                          {ok, PublicKey :: binary()} | {error, wrong_length | inconsistent_private_key}.

The public key of an ML-DSA private key in either form. An expanded key whose parts disagree is inconsistent_private_key.

mldsa_sign(Set, _, Message, Context)

-spec mldsa_sign(mldsa_set(), mldsa_private_key(), Message :: binary(), Context :: binary()) ->
                    {ok, Signature :: binary()} |
                    {error, wrong_length | context_too_long | randomness_unavailable}.

A hedged ML-DSA signature over Message under the context string Context.

mldsa_verify(Set, PublicKey, Message, Signature, Context)

-spec mldsa_verify(mldsa_set(),
                   PublicKey :: binary(),
                   Message :: binary(),
                   Signature :: binary(),
                   Context :: binary()) ->
                      boolean().

Whether Signature is a valid ML-DSA signature over Message under Context. False for anything FIPS 204 rejects, a context over 255 bytes included.

nif_blake3(Data)

nif_blake3_hex(Data)

nif_blake3_streaming(Chunks)

nif_blake3_verify(Data, ExpectedHash)

nif_effective_uid()

-spec nif_effective_uid() -> non_neg_integer() | none.

secure_compare(A, B)

-spec secure_compare(A :: binary(), B :: binary()) -> boolean().

Constant-time comparison of two binaries. Important for security - prevents timing attacks.

sha256(Data)

-spec sha256(Data :: binary()) -> Hash :: binary().

Compute SHA-256 hash. Returns 32-byte hash binary.

sha256_base64(Data)

-spec sha256_base64(Data :: binary()) -> Base64Hash :: binary().

Compute SHA-256 hash and encode as URL-safe base64. Returns base64-encoded string (no padding).