ALARA — Distributed Entropy Network System
ALARA is a lightweight distributed entropy system written in Erlang/OTP.
It supervises a pool of worker nodes, each producing cryptographically secure
random bytes via crypto:strong_rand_bytes/1. Contributions from all workers
are mixed with SHA3-256 before being returned, so the output remains
unpredictable even if all but one worker is compromised.
Features
- Cryptographically secure — built exclusively on
crypto:strong_rand_bytes/1(OTPcryptoapplication), never onrand - Distributed mixing — entropy from every worker is combined and hashed with SHA3-256 before use
- OTP-supervised pool — workers restart automatically on failure; the node list is always read live from the supervisor
- Parallel collection — worker requests are issued concurrently to minimise latency
- Clean, minimal API — bytes, bits, or integers; one call each
Requirements
- Erlang/OTP 25+
- Rebar3
Security note — distributed Erlang
When running ALARA across multiple machines or VMs, secure the Erlang distribution channel with TLS (-proto_dist inet_tls) and use a high-entropy cookie. Without TLS, a network attacker can observe or interfere with inter-node traffic.
This library has not yet been formally audited by an independent cryptographer. Treat it as experimental for high-security production environments until such an audit is completed.
Quick Start
1. Add to your project
%% rebar.config
{deps, [{alara, "0.1.7"}]}.2. Build
git clone https://github.com/Green-Mice/alara.git
cd alara
rebar3 compile3. Run the shell
rebar3 shell4. Basic usage
%% alara starts automatically with your application (pool_size defaults to 3).
%% Configure via sys.config if needed:
%% [{alara, [{pool_size, 5}]}]
%% List the live worker PIDs.
Nodes = alara:get_nodes(),
io:format("Workers: ~p~n", [Nodes]).
%% Generate 32 cryptographically secure random bytes.
Bytes = alara:generate_random_bytes(32),
io:format("Bytes: ~p~n", [Bytes]).
%% Generate 64 random bits as a list of 0 | 1 integers.
Bits = alara:generate_random_bits(64),
io:format("Bits: ~p~n", [Bits]).
%% Generate a random non-negative integer using 128 bits of entropy.
%% Result is in [0, 2^128 - 1].
Int = alara:generate_random_int(128),
io:format("Int: ~p~n", [Int]).API Reference
Pool management
| Function | Description |
|---|---|
alara:get_nodes/0 | Return the PIDs of all currently live workers |
alara_node_sup:add_node/0 | Dynamically add a worker to the running pool |
Entropy generation
| Function | Returns | Description |
|---|---|---|
alara:generate_random_bytes/1 | binary() | N random bytes, SHA3-256 mixed |
alara:generate_random_bits/1 | [0|1] | N random bits |
alara:generate_random_int/1 | non_neg_integer() |
Random integer in [0, 2^N - 1] |
Direct worker access
%% Start a standalone worker (no supervisor).
{ok, Pid} = alara_node:start_link().
%% Request raw bytes directly from one worker (no mixing step).
Bytes = alara_node:get_random_bytes(Pid, 16).Architecture
alara_app (application callback)
└── alara_node_sup (supervisor, one_for_one)
├── alara_node (entropy worker — crypto:strong_rand_bytes)
├── alara_node (entropy worker — crypto:strong_rand_bytes)
└── ...alara_node — each worker holds no mutable state. On every request it
calls crypto:strong_rand_bytes/1 and returns the result. There is nothing
to compromise at rest.
alara_node_sup — supervises the worker pool (one_for_one, permanent
restart). Worker requests are issued in parallel; results are concatenated
and hashed with SHA3-256. The node list is always fetched live from
supervisor:which_children/1 — never from a stale cache.
alara — thin API module. Delegates to alara_node_sup with no extra
message hop.
Running Tests
rebar3 eunitLicense
Apache 2.0