getrandom

repository·master·Indexed 20 days ago

https://github.com/rust-random/getrandom

A low-level, cross-platform Rust library for retrieving cryptographically secure random data from operating system sources. It provides a system entropy interface via functions like fill(), fill_uninit(), u32(), and u64(), as well as the SysRng struct. Supports various opt-in backends (e.g., linux_getrandom, rdrand, windows_legacy) and custom implementations via configuration flags. Version 0.4.3 requires Rust 1.85 or later.

Tokens
4.8K
Snippets
17
Records
21
Agent score
68%

What's inside getrandom

  1. Use getrandom to retrieve random data

    master

    The getrandom crate provides a low-level API for retrieving cryptographically secure random data from the operating system. It is designed to interface with system entropy sources.

    Note: This is a low-level API. For most application-level random number generation needs, it is recommended to use a higher-level library like rand instead.

    fn get_random_u128() -> Result<u128, getrandom::Error> {
        let mut buf = [0u8; 16];
        getrandom::fill(&mut buf)?;
        Ok(u128::from_ne_bytes(buf))
    }
  2. Understand error and panic behavior in getrandom

    master

    Error Handling

    getrandom prioritizes failure over returning insecure bytes. While failures are unlikely on supported platforms, they can occur. If an error occurs, it is likely to persist on subsequent calls. Once a call succeeds, you can reasonably assume future calls will not error.

    Panic Handling

    getrandom aims to eliminate panics in backend implementations. When compiled with optimizations, the generated code should not contain panic branches. If a platform returns an unexpected result, the library is designed to return an error (e.g., Error::UNEXPECTED) rather than panicking.

  3. Update getrandom while respecting MSRV

    master

    To ensure cargo update respects the Minimum Supported Rust Version (MSRV) when updating getrandom, use the CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS=fallback environment variable.

    CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS=fallback cargo update -p getrandom
  4. Use opt-in backends via configuration flags

    master

    You can replace the default getrandom implementation by enabling an opt-in backend using the getrandom_backend configuration flag. This can be done via .cargo/config.toml or the RUSTFLAGS environment variable.

    Available Opt-in Backends:

    • linux_getrandom: Linux/Android using getrandom syscall without /dev/urandom fallback (requires Linux 3.17+ or Android API 23+).
    • linux_raw: Same as linux_getrandom but uses raw asm! syscalls instead of libc.
    • rdrand: x86/x86-64 using RDRAND instruction.
    • rndr: AArch64 using RNDR register.
    • efi_rng: UEFI using EFI_RNG_PROTOCOL (requires std and Nightly).
    • windows_legacy: Windows using RtlGenRandom.
    • custom: User-provided implementation.
    • unsupported: Always returns Err(Error::UNSUPPORTED).
    • extern_impl: Externally-provided implementation (Nightly only).

    Warning: Using an incorrect backend for your target will cause compilation errors. Incorrect configuration can lead to vulnerable applications or panics. Note that setting these in a library will not affect downstream users.

    # Setting via .cargo/config.toml (recommended per-target)
    [target.'cfg(target_os = "linux")']
    rustflags = ['--cfg', 'getrandom_backend="linux_getrandom"']
    # Setting via RUSTFLAGS environment variable
    RUSTFLAGS='--cfg getrandom_backend="linux_getrandom"' cargo build
  5. Override implementations using `extern_impl` (Nightly only)

    master

    Using the nightly-only extern_item_impls feature, you can provide custom implementations for fill_uninit, u32, or u64 to override existing first-party implementations.

    1. Enable the extern_impl opt-in backend.
    2. Use the #[getrandom::implementation::fill_uninit] attribute macro to provide your implementation.
    use core::mem::MaybeUninit;
    
    #[cfg(getrandom_backend = "extern_impl")]
    #[getrandom::implementation::fill_uninit]
    fn my_fill_uninit_implementation(
        dest: &mut [MaybeUninit<u8>]
    ) -> Result<(), getrandom::Error> {
        // ... implementation ...
        Ok(())
    }
  6. Implement a custom backend with the `custom` flag

    master

    If your target is unsupported or you need a specific entropy source, you can provide a custom implementation.

    1. Enable the custom backend via getrandom_backend flag.
    2. Define an extern function with the signature __getrandom_v03_custom in the root crate of your project (e.g., main.rs).

    Important: This function must be defined exactly once for your project. Upstream library crates should not define this outside of tests/benchmarks. The function receives a pointer dest and a length len. The buffer may be uninitialized; you must fully fill it before returning Ok(()).

    use getrandom::Error;
    
    #[unsafe(no_mangle)]
    unsafe extern "Rust" fn __getrandom_v03_custom(
        dest: *mut u8,
        len: usize,
    ) -> Result<(), Error> {
        let buf = unsafe {
            // fill the buffer with zeros to ensure safety if your source expects initialized memory
            core::ptr::write_bytes(dest, 0, len);
            core::slice::from_raw_parts_mut(dest, len)
        };
        
        // Call your actual entropy source
        my_entropy_source(buf)
    }
    
    fn my_entropy_source(buf: &mut [u8]) -> Result<(), getrandom::Error> {
        // ... implementation ...
        Ok(())
    }
  7. Enable WebAssembly support for wasm32/64-unknown-unknown

    master

    The wasm32-unknown-unknown and wasm64-unknown-unknown targets (commonly used with wasm-pack) are not supported by default because they require a JavaScript interface. To enable support using Crypto.getRandomValues via wasm-bindgen, you must enable the wasm_js crate feature.

    WARNING: It is strongly recommended against enabling this feature in libraries (except for tests). Doing so can break non-Web WASM builds and causes significant Cargo.lock bloat due to the wasm-bindgen dependency. The only exception is if your crate already unconditionally depends on wasm-bindgen or js-sys on these targets.

    # Example: enabling the feature in your Cargo.toml
    [dependencies]
    getrandom = { version = "0.2", features = ["wasm_js"] }
  8. Enable MemorySanitizer support for fill_uninit

    master

    If your code uses fill_uninit and you enable MemorySanitizer (via -Zsanitizer=memory), getrandom will automatically handle the unpoisoning of the destination buffer filled by fill_uninit.

    To run sanitizer tests for a crate that depends on getrandom, use the following command:

    RUSTFLAGS="-Zsanitizer=memory" cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu
  9. Override getrandom implementation via `extern_impl`

    master

    If you need to provide a custom implementation for getrandom (e.g., for a specific embedded target), you can use the implementation module. This requires the getrandom_backend = "extern_impl" configuration and is currently limited to nightly Rust.

    You can use attribute macros to overwrite the core functionality. The available macros in getrandom::implementation are:

    • fill_uninit
    • u32
    • u64
    # use core::mem::MaybeUninit;
    # #[cfg(getrandom_backend = "extern_impl")]
    #[getrandom::implementation::fill_uninit]
    fn my_fill_uninit_implementation(
        dest: &mut [MaybeUninit<u8>]
    ) -> Result<(), getrandom::Error> {
        // Your custom implementation logic here
        // ...
        # let _ = dest;
        # Err(getrandom::Error::UNSUPPORTED)
    }
  10. Fill a buffer with random bytes using getrandom::fill

    master

    To populate a byte slice with random data from the system, use the getrandom::fill function. This function returns a Result<(), getrandom::Error>, which should be handled to ensure the system successfully provided entropy.

    fn get_random_u128() -> Result<u128, getrandom::Error> {
        let mut buf = [0u8; 16];
        getrandom::fill(&mut buf)?;
        Ok(u128::from_ne_bytes(buf))
    }
  11. Reference: Supported targets and implementations

    master

    The following table lists the default implementations used by getrandom across various platforms.

    | Target             | Target Triple      | Implementation |
    | ------------------ | ------------------ | -------------- |
    | Linux, Android     | `*‑linux‑*`        | `getrandom` system call if available, otherwise `/dev/urandom` after successfully polling `/dev/random` |
    | Windows 10+        | `*‑windows‑*`      | `ProcessPrng` |
    | Windows 7, 8       | `*-win7‑windows‑*` | `RtlGenRandom` |
    | macOS              | `*‑apple‑darwin`   | `getentropy` |
    | iOS, tvOS, watchOS | `*‑apple‑{ios,tvos,watchos}` | `CCRandomGenerateBytes` |
    | FreeBSD            | `*‑freebsd`        | `getrandom` |
    | OpenBSD            | `*‑openbsd`        | `getentropy` |
    | NetBSD             | `*‑netbsd`         | `getrandom` if available, otherwise `kern.arandom` |
    | Dragonfly BSD      | `*‑dragonfly`      | `getrandom` |
    | Solaris            | `*‑solaris`        | `getrandom` with `GRND_RANDOM` |
    | illumos            | `*‑illumos`        | `getrandom` |
    | Fuchsia OS         | `*‑fuchsia`        | `cprng_draw` |
    | Redox              | `*‑redox`          | `/dev/urandom` |
    | Haiku              | `*‑haiku`          | `/dev/urandom` (identical to `/dev/random`) |
    | Hermit             | `*-hermit`         | `sys_read_entropy` |
    | Hurd               | `*-hurd-*`         | `getrandom` |
    | SGX                | `x86_64‑*‑sgx`     | `RDRAND` |
    | VxWorks            | `*‑wrs‑vxworks‑*`  | `randABytes` after checking entropy pool initialization with `randSecure` |
    | Emscripten         | `*‑emscripten`     | `getentropy` |
    | WASI 0.1           | `wasm32‑wasip1`    | `random_get` |
    | WASI 0.2           | `wasm32‑wasip2`    | `get-random-u64` |
    | SOLID              | `*-kmc-solid_*`    | `SOLID_RNG_SampleRandomBytes` |
    | Nintendo 3DS       | `*-nintendo-3ds`   | `getrandom` |
    | ESP-IDF            | `*‑espidf`         | `esp_fill_random` |
    | PS Vita            | `*-vita-*`         | `getentropy` |
    | QNX Neutrino       | `*‑nto-qnx*`       | `/dev/urandom` (identical to `/dev/random`) |
    | AIX                | `*-ibm-aix`        | `/dev/urandom` |
    | Cygwin             | `*-cygwin`         | `getrandom` (based on `RtlGenRandom`) |
    | Motor OS           | `x86_64-unknown-motor` | `RDRAND` |