diff options
| author | e4m2 <git@e4m2.com> | 2024-02-08 14:43:20 +0100 |
|---|---|---|
| committer | e4m2 <git@e4m2.com> | 2024-02-08 14:43:20 +0100 |
| commit | 9af077d71eaf2c004d63405fc5c017e237cb9c6c (patch) | |
| tree | e9a82339e59f49ae2b6fc57c893b3e16afaed9aa /lib/std/Random/Ascon.zig | |
| parent | 919a3bae1c5f2024b09e127a15c752d9dc0aa9a6 (diff) | |
| download | zig-9af077d71eaf2c004d63405fc5c017e237cb9c6c.tar.gz zig-9af077d71eaf2c004d63405fc5c017e237cb9c6c.zip | |
std.rand: Move to std.Random
Diffstat (limited to 'lib/std/Random/Ascon.zig')
| -rw-r--r-- | lib/std/Random/Ascon.zig | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/std/Random/Ascon.zig b/lib/std/Random/Ascon.zig new file mode 100644 index 0000000000..6a3cb13165 --- /dev/null +++ b/lib/std/Random/Ascon.zig @@ -0,0 +1,59 @@ +//! CSPRNG based on the Reverie construction, a permutation-based PRNG +//! with forward security, instantiated with the Ascon(128,12,8) permutation. +//! +//! Compared to ChaCha, this PRNG has a much smaller state, and can be +//! a better choice for constrained environments. +//! +//! References: +//! - A Robust and Sponge-Like PRNG with Improved Efficiency https://eprint.iacr.org/2016/886.pdf +//! - Ascon https://ascon.iaik.tugraz.at/files/asconv12-nist.pdf + +const std = @import("std"); +const mem = std.mem; +const Random = std.rand.Random; +const Self = @This(); + +const Ascon = std.crypto.core.Ascon(.little); + +state: Ascon, + +const rate = 16; +pub const secret_seed_length = 32; + +/// The seed must be uniform, secret and `secret_seed_length` bytes long. +pub fn init(secret_seed: [secret_seed_length]u8) Self { + var self = Self{ .state = Ascon.initXof() }; + self.addEntropy(&secret_seed); + return self; +} + +/// Inserts entropy to refresh the internal state. +pub fn addEntropy(self: *Self, bytes: []const u8) void { + comptime std.debug.assert(secret_seed_length % rate == 0); + var i: usize = 0; + while (i + rate < bytes.len) : (i += rate) { + self.state.addBytes(bytes[i..][0..rate]); + self.state.permuteR(8); + } + if (i != bytes.len) self.state.addBytes(bytes[i..]); + self.state.permute(); +} + +/// Returns a `std.rand.Random` structure backed by the current RNG. +pub fn random(self: *Self) Random { + return Random.init(self, fill); +} + +/// Fills the buffer with random bytes. +pub fn fill(self: *Self, buf: []u8) void { + var i: usize = 0; + while (true) { + const left = buf.len - i; + const n = @min(left, rate); + self.state.extractBytes(buf[i..][0..n]); + if (left == 0) break; + self.state.permuteR(8); + i += n; + } + self.state.permuteRatchet(6, rate); +} |
