A proposed WebAssembly System Interface API.
WASI-random is currently in Phase 3.
- Dan Gohman
WASI random must have host implementations which can pass the testsuite on at least Windows, macOS, and Linux.
WASI random must have at least two complete independent implementations.
- Introduction
- Goals
- Non-goals
- API walk-through
- Detailed design discussion
- Considered alternatives
- Stakeholder Interest & Feedback
- References & acknowledgements
WASI Random is a WASI API for obtaining pseudo-random data.
The primary goals of WASI Random are:
- To allow users to use WASI programs to obtain high-quality low-level random data suitable for cryptography.
- To allow source languages to enable DoS protection in their hash-maps in host environments that support it.
WASI Random is not aiming to allow programs to handle errors or to query for availability. It always succeeds (though on platforms where randomness is unavailable, programs may fail to be instantiated or may trap).
WASI Random is not aiming to be a full DRBG API. Such an API could be considered in WASI, but it should be a separate proposal.
WASI Random does not include facilities for feeding entropy back into the system. It is expected that most entropy that applications would observe should also be observable by the host implementation, and so there should be little need to feed it back in. There may be other uses for such an API, but they can be addressed in separate proposals.
WASI Random does not have an async API. It is expected to be implemented with a CSPRNG which is expected to be sufficiently seeded.
WASI Random does not have an explicit facility for domain separation or personalization messages. If such features are desired, it would make sense to define them as custom sections, rather than program data, so that they could easily be excluded from module caching and possibly also from code signing. This would make sense as a separate proposal.
WASI Random does not provide an "entropy API" or a "true random" API directly. The currently expected use cases want a CSPRNG API.
WASI Random does not expose an entropy estimation. It is expected to always have sufficient entropy to seed a CSPRNG.
WASI Random does not provide any facility for replacing random data with deterministic data. It is intended to be usable in use cases where determinism would break application assumptions. Implementations may have debugging facilities which make this API deterministic, however these should only be used for debugging, and not production use.
Return a list of cryptographically-secure pseudo-random bytes:
let len: u32 = your_own_code_to_decide_how_many_bytes_you_want();
let bytes: Vec<u8> = get_random_bytes(len);
Sometimes the bindings for list<u8>
can have some overhead, so
another function is available which returns the same data but as a
u64
:
let data: u64 = get_random_u64();
Return a pair of u64's that can be used to initialize a hash implementation:
let init: (u64, u64) = insecure_random();
let combined: u128 = init.0 as u128 | (init.1 as u128 << 64);
your_own_code_to_initialize_hash_map(combined);
Randomness APIs which can fail, or which can be "nonblocking" and return incomplete results, are error prone and tend to lead applications to resort to fallbacks which don't tend to be well-tested.
CSPRNGs are believed to be good enough that most systems in most situations can provide effectively unlimited random data. The main case where this isn't the case is on systems which have just booted and which have not yet collected sufficient entropy to initialize their CSPRNGs. In these cases, this API is designed with the belief that it's better for implementations to respond to the problem, rather than to pass the responsibility on to applications.
It's implementations' responsibility to handle these situations. They may do so by supplementing the host platform APIs with data collected from other sources, they may refuse to run programs that use Random APIs, or if needed, they may trap programs dynamically to prevent programs from continuing to execute with poor data.
Implementations are encouraged to perform regular reseeding (if the host platform doesn't already do so).
Programs shouldn't need to be aware of which random generator they have, since the data is random and indistinguishable.
WASI programs using the Random API will have imports specific to the Random API,
because they are distinct from imports used for general-purpose stream
.
Reusing the stream
type is tempting, however it's desirable for users of this
API to be provided actually random data, and not the contents of arbitrary
streams which might be substituted, so it doesn't turn out to be useful to unify
this API with stream
.
This also ensures that programs using the Random API can be identified by their imports, as mentioned in the previous question.
Best practices suggest that implementations should provide at least 196 bits of security. However, many host platforms' CSPRNG APIs do not currently document their bits of security, and it doesn't seem desirable to require wasm engines to run their own CSPRNG on a platform which already has one, so for now, the API does not specify a specific number.
This limits the amount of data that can be obtained through it. Since it's
insecure, it's not intended to be used as an alternative to getrandom
.
TODO before entering Phase 3.
Preview1 has a random function, and it's widely exposed in toolchains.
Many thanks for valuable feedback and advice from:
- Zach Lym
- Luke Wagner
- Linux Weekly News' many articles about Linux random APIs including this one.