Ch12.3: The ibuf_white_hole_engine

What is ibuf_white_hole_engine?

::fast_io::ibuf_white_hole_engine is a cryptographically secure random number engine that reads directly from the operating system's entropy source. The name "white hole" is a metaphor: unlike a black hole that absorbs everything, a white hole emits random bytes.

This engine satisfies the C++ UniformRandomBitGenerator requirement, which means it works seamlessly with all distributions from <random>, such as ::std::uniform_int_distribution, ::std::bernoulli_distribution, and others.

Key Features

Basic Usage


#include <fast_io.h>
#include <fast_io_device.h>
#include <random>

int main() {
    using namespace ::fast_io::io;

    // Create a cryptographically secure random engine
    ::fast_io::ibuf_white_hole_engine eng;

    // Use with uniform_int_distribution
    ::std::uniform_int_distribution<::std::uint32_t> dist(1, 100);

    // Generate random numbers
    for (::std::size_t i{}; i != 10; ++i) {
        println("Random number in [1, 100]: ", dist(eng));
    }

    // Use with bernoulli_distribution for true/false
    ::std::bernoulli_distribution coin_flip(0.5);
    for (::std::size_t i{}; i != 5; ++i) {
        bool heads = coin_flip(eng);
        println("Coin flip: ", ::fast_io::mnp::os_c_str(heads ? "heads" : "tails"));
    }
}

Related Topics

The ibuf_white_hole_engine also works with ::std::shuffle for cryptographically secure container shuffling. See Ch12.5: Shuffling with std::shuffle for details.

How It Works

The engine is implemented as a type alias:


using ibuf_white_hole_engine = basic_white_hole_engine<ibuf_white_hole>;

Where ibuf_white_hole is an input-buffered wrapper around the platform-specific random source. The buffer mode includes buffer_mode::secure_clear, which ensures the buffer is wiped when destroyed.

The operator()() method reads sizeof(::std::size_t) bytes from the buffered source and returns them as a ::std::size_t. Most calls are served from the buffer without a syscall.

Reading Raw Bytes with ibuf_white_hole

If you need raw random bytes (for example, to create cryptographic keys or tokens), you can use ::fast_io::ibuf_white_hole directly as an input stream:


#include <fast_io.h>
#include <fast_io_device.h>
#include <array>

int main() {
    using namespace ::fast_io::io;

    // Create a buffered white hole (input stream)
    ::fast_io::ibuf_white_hole rng;

    // Read 32 random bytes
    ::fast_io::array<::std::byte, 32> buffer;
    ::fast_io::operations::read_all(rng, buffer.data(), buffer.data() + buffer.size());

    // Print as hex
    println("Random bytes (hex):");
    for (::std::size_t i{}; i != buffer.size(); ++i) {
        print(::fast_io::mnp::hex(::fast_io::mnp::upper(buffer[i])), " ");
        if ((i + 1) % 16 == 0) {
            print("\n");
        }
    }

    // Use for generating a UUID (16 bytes)
    ::fast_io::array<::std::byte, 16> uuid_bytes;
    ::fast_io::operations::read_all(rng, uuid_bytes.data(), uuid_bytes.data() + uuid_bytes.size());

    println("\nUUID bytes:");
    for (::std::size_t i{}; i != uuid_bytes.size(); ++i) {
        print(::fast_io::mnp::hex(uuid_bytes[i]));
        if (i == 3 || i == 5 || i == 7 || i == 9) {
            print('-');
        }
    }
    print("\n");
}

ibuf_white_hole is the underlying input stream type. It provides the same buffered, cryptographically secure random bytes as the engine, but through the standard I/O interface (read_all, read_some, etc.).

One-Time Use: native_white_hole

If you only need to generate random bytes once (such as creating a single secret key or token), use ::fast_io::native_white_hole instead of ibuf_white_hole. The native_white_hole is unbuffered and makes direct system calls, which is more efficient when you won't reuse the stream.


#include <fast_io.h>
#include <fast_io_device.h>
#include <array>

int main() {
    using namespace ::fast_io::io;

    // Generate a single API key (32 bytes)
    ::fast_io::native_white_hole rng;
    ::fast_io::array<::std::byte, 32> api_key;
    ::fast_io::operations::read_all(rng, api_key.data(), api_key.data() + api_key.size());

    // Guard ensures api_key is securely cleared when it goes out of scope
    ::fast_io::secure_clear_guard guard(api_key.data(), api_key.size());

    println("Generated API key (32 bytes)");

    // No need to keep rng around - we only used it once
    // The unbuffered approach is more efficient for one-time use
    // api_key will be securely cleared automatically when guard is destroyed
}
Important: Always use ::fast_io::secure_clear_guard to automatically wipe sensitive data like API keys, tokens, or cryptographic keys from memory when they go out of scope. This RAII guard prevents secrets from leaking through memory dumps, swap files, or debugging tools, even if exceptions occur.

When to use native_white_hole vs ibuf_white_hole:

When to Use

Use ibuf_white_hole_engine when:

For reproducible randomness (debugging, testing, simulations), see Ch12.4: Seeding Reproducible Engines.

Key Takeaways