random:用操作系统随机性填充缓冲区

OS 用熵填充缓冲区并处理部分失败。

Wave Foundation

API

std::random::fill
random_available() -> bool
random_fill(buffer: ptr<u8>, size: i64) -> RandomFillResult

size 是字节数,调用者提供存储。 RandomFillResult 包含正常、已写入和错误。成功后,写入的长度等于请求的长度。失败时,写入标识有效的、填充的前缀;不要使用剩余字节作为随机数据。

random_available 告诉您是否支持OS 随机数功能。单个请求是否成功通过random_fill的结果进行检查。仅使用 OS 熵,并且在失败时不会依赖于时间值或弱 PRNG。即使与null一起传递,size=0也会成功。 null 是负或正长度的错误。

运行示例

import("std::random::fill")::{
    RandomFillResult, random_fill
};

fun main() -> i32 {
    var bytes: array<u8, 16>;
    var result: RandomFillResult = random_fill(&bytes[0], 16);
    if (!result.ok) {
        println("random error={}", result.error);
        return 1;
    }

    println("filled={}", result.written);
    return 0;
}

执行结果:

filled=16

保存为main.wave并运行。每次的字节内容都不同,因此不需要特定值。如果失败,请通过result.error检查原因。如果需要,不要按字面意思输出随机字节,而是使用单独的编码。

如果您的请求不正确

零字节请求会成功,因为不需要写入任何内容。传递具有正长度的null会失败,因为没有目标缓冲区。以下程序在不分配内存的情况下比较这些情况。

import("std::random::fill")::{
    RandomFillResult,
    random_fill
};

fun main() -> i32 {
    var empty: RandomFillResult = random_fill(null, 0);

    if (!empty.ok || empty.written != 0) {
        return 1;
    }

    println("empty request succeeded");

    var invalid: RandomFillResult = random_fill(null, 16);

    if (invalid.ok) {
        return 2;
    }

    println("missing buffer rejected");
    return 0;
}

执行结果:

empty request succeeded
missing buffer rejected

处理部分填充的缓冲区

如果请求16个字节失败,返回written=8,则只填充前8个字节。如果任务是创建一个 16 字节的标识符,那么它不是一个成功的标识符,因此我们丢弃整个结果并报告失败。您不应该将剩余的8个字节填充为0然后将其视为成功。

将随机字节映射到整数范围需要小心。将 % 10 应用于均匀分布的 u8 值会使 0-5 比 6-9 更有可能出现,因为 256 不能被 10 整除。要消除这种偏差,请拒绝值 250-255,再次绘制,然后仅对接受的值应用余数运算。

随机字节的存储和生命周期由调用者管理。使用数组时,在数组范围内处理,使用动态内存时,使用后释放。相反,返回结构并不拥有缓冲区。