High-performance Rust NIFs for the Macula mesh platform, providing cryptographic primitives, UCAN token operations, and DID document handling.
- Ed25519 Cryptography - Key generation, signing, and verification
- UCAN Tokens - Create, verify, and manipulate capability tokens
- DID Documents - W3C-compliant Decentralized Identifier documents
- Pure Erlang Fallbacks - Works without Rust toolchain (with reduced performance)
Add to your rebar.config:
{deps, [
{macula_nifs, "0.1.0"}
]}.Or from git:
{deps, [
{macula_nifs, {git, "https://github.com/macula-io/macula-nifs.git", {tag, "v0.1.0"}}}
]}.For NIF compilation:
- Rust 1.70+ with cargo
- C compiler (for ed25519-dalek)
If Rust is not available, the library will use pure Erlang fallbacks.
%% Generate Ed25519 keypair
{ok, {PubKey, PrivKey}} = macula_crypto_nif:generate_keypair().
%% Sign a message
{ok, Signature} = macula_crypto_nif:sign(<<"message">>, PrivKey).
%% Verify signature
true = macula_crypto_nif:verify(<<"message">>, Signature, PubKey).
%% SHA-256 hash
Hash = macula_crypto_nif:sha256(<<"data">>).
%% URL-safe base64 encoding
Encoded = macula_crypto_nif:base64_encode(<<"binary data">>).
{ok, Decoded} = macula_crypto_nif:base64_decode(Encoded).
%% Constant-time comparison (timing-attack resistant)
true = macula_crypto_nif:secure_compare(Hash1, Hash2).UCAN (User Controlled Authorization Networks) tokens enable decentralized capability-based authorization.
%% Create a UCAN token
Issuer = <<"did:macula:io.macula.acme">>,
Audience = <<"did:macula:io.macula.customer">>,
Capabilities = [#{<<"with">> => <<"artifact:*">>, <<"can">> => <<"deploy">>}],
{ok, {_PubKey, PrivKey}} = macula_crypto_nif:generate_keypair(),
{ok, Token} = macula_ucan_nif:create(Issuer, Audience, Capabilities, PrivKey).
%% Create with options (expiration, not-before, facts, proofs)
Opts = #{
exp => erlang:system_time(second) + 3600, % 1 hour
nbf => erlang:system_time(second),
nnc => <<"unique-nonce">>,
fct => #{<<"tier">> => <<"pro">>},
prf => [<<"parent-token-cid">>]
},
{ok, Token2} = macula_ucan_nif:create(Issuer, Audience, Capabilities, PrivKey, Opts).
%% Verify token (checks signature, expiration, not-before)
{ok, valid} = macula_ucan_nif:verify(Token, PubKey).
%% Decode token payload (without verification)
{ok, Payload} = macula_ucan_nif:decode(Token).
%% Extract fields
{ok, Iss} = macula_ucan_nif:get_issuer(Token).
{ok, Aud} = macula_ucan_nif:get_audience(Token).
{ok, Caps} = macula_ucan_nif:get_capabilities(Token).
{ok, Exp} = macula_ucan_nif:get_expiration(Token).
{ok, Proofs} = macula_ucan_nif:get_proofs(Token).
%% Compute CID (for proof chains)
CID = macula_ucan_nif:compute_cid(Token).
%% Check expiration
false = macula_ucan_nif:is_expired(Token).Create and manipulate W3C DID Core compliant documents for the Macula identity hierarchy.
%% Create a DID document
Did = <<"did:macula:io.macula.acme">>,
{ok, {PubKey, _PrivKey}} = macula_crypto_nif:generate_keypair(),
{ok, Document} = macula_did_nif:create_document(Did, PubKey).
%% Parse and validate a document
{ok, Validated} = macula_did_nif:parse_document(Document).
%% Extract public key from document
{ok, ExtractedKey} = macula_did_nif:extract_public_key(Document).
%% Get DID and controller
{ok, DidStr} = macula_did_nif:get_did(Document).
{ok, Controller} = macula_did_nif:get_controller(Document).
%% Verify controller relationship
ok = macula_did_nif:verify_controller(Document, <<"did:macula:io.macula">>).
%% Parse DID string into components
{ok, Components} = macula_did_nif:parse_did(<<"did:macula:io.macula.acme.myapp">>).
%% #{<<"method">> => <<"macula">>,
%% <<"identity">> => <<"io.macula.acme.myapp">>,
%% <<"parts">> => [<<"io">>, <<"macula">>, <<"acme">>, <<"myapp">>],
%% <<"depth">> => 4}
%% Check hierarchy relationships
true = macula_did_nif:is_descendant(
<<"did:macula:io.macula.acme.myapp">>,
<<"did:macula:io.macula.acme">>).Macula uses hierarchical DIDs that map to the PKI structure:
did:macula:io.macula (Realm - root of trust)
└── did:macula:io.macula.acme (Organization)
└── did:macula:io.macula.acme.myapp (Application)
Each level is controlled by its parent, enabling delegated authority.
The Rust NIFs provide significant performance improvements over pure Erlang:
| Operation | NIF | Erlang | Speedup |
|---|---|---|---|
| Key Generation | ~10μs | ~100μs | ~10x |
| Sign | ~20μs | ~100μs | ~5x |
| Verify | ~50μs | ~400μs | ~8x |
| SHA-256 | ~5μs | ~15μs | ~3x |
Check if NIFs are loaded:
true = macula_crypto_nif:is_nif_loaded().
true = macula_ucan_nif:is_nif_loaded().
true = macula_did_nif:is_nif_loaded().If NIFs are not available, the pure Erlang fallbacks are used automatically.
| Function | Description |
|---|---|
generate_keypair/0 |
Generate Ed25519 keypair |
sign/2 |
Sign message with private key |
verify/3 |
Verify signature |
sha256/1 |
Compute SHA-256 hash |
sha256_base64/1 |
SHA-256 + URL-safe base64 |
base64_encode/1 |
URL-safe base64 encode |
base64_decode/1 |
URL-safe base64 decode |
secure_compare/2 |
Constant-time comparison |
is_nif_loaded/0 |
Check NIF availability |
| Function | Description |
|---|---|
create/4,5 |
Create UCAN token |
verify/2 |
Verify token signature and validity |
decode/1 |
Decode token without verification |
get_issuer/1 |
Extract issuer DID |
get_audience/1 |
Extract audience DID |
get_capabilities/1 |
Extract capabilities |
get_expiration/1 |
Extract expiration timestamp |
get_proofs/1 |
Extract proof chain |
compute_cid/1 |
Compute content ID |
is_expired/1 |
Check if token is expired |
is_nif_loaded/0 |
Check NIF availability |
| Function | Description |
|---|---|
create_document/2 |
Create DID document |
parse_document/1 |
Parse and validate document |
extract_public_key/1 |
Extract public key |
get_did/1 |
Get DID from document |
get_controller/1 |
Get controller DID |
verify_controller/2 |
Verify controller relationship |
parse_did/1 |
Parse DID string |
is_descendant/2 |
Check hierarchy relationship |
is_nif_loaded/0 |
Check NIF availability |
rebar3 eunitApache-2.0
See CONTRIBUTING.md for guidelines.