///|
/// Cryptographic random bytes from the operating system entropy pool
/// (/dev/urandom on Linux and macOS).
pub async fn random_bytes(len : Int) -> Bytes raise CryptoError {
if len < 0 {
raise Random("negative byte count \{len}")
}
let file = @fs.open("/dev/urandom", mode=ReadOnly) catch {
e => raise Random("cannot open /dev/urandom: \{e}")
}
defer file.close()
file.read_exactly(len) catch {
e => raise Random("cannot read /dev/urandom: \{e}")
}
}
///|
/// A lowercase-hex random string, two characters per byte — the shape of
/// WeChat Pay's nonce_str.
pub async fn random_hex(byte_len : Int) -> String raise CryptoError {
let bytes = random_bytes(byte_len)
@base16.encode(bytes[:])
}