mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Ascon has been selected as new standard for lightweight cryptography in the NIST Lightweight Cryptography competition. Ascon won over Gimli and Xoodoo. The permutation is unlikely to change. However, NIST may tweak the constructions (XOF, hash, authenticated encryption) before standardizing them. For that reason, implementations of those are better maintained outside the standard library for now. In fact, we already had an Ascon implementation in Zig: `std.crypto.aead.isap` is based on it. While the implementation was here, there was no public API to access it directly. So: - The Ascon permutation is now available as `std.crypto.core.Ascon`, with everything needed to use it in AEADs and other Ascon-based constructions - The ISAP implementation now uses std.crypto.core.Ascon instead of keeping a private copy - The default CSPRNG replaces Xoodoo with Ascon. And instead of an ad-hoc construction, it's using the XOFa mode of the NIST submission.
45 lines
1.2 KiB
Zig
45 lines
1.2 KiB
Zig
//! CSPRNG based on the Ascon XOFa construction
|
|
|
|
const std = @import("std");
|
|
const min = std.math.min;
|
|
const mem = std.mem;
|
|
const Random = std.rand.Random;
|
|
const Self = @This();
|
|
|
|
state: std.crypto.core.Ascon(.Little),
|
|
|
|
const rate = 8;
|
|
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 state = std.crypto.core.Ascon(.Little).initXofA();
|
|
var i: usize = 0;
|
|
while (i + rate <= secret_seed.len) : (i += rate) {
|
|
state.addBytes(secret_seed[i..][0..rate]);
|
|
state.permuteR(8);
|
|
}
|
|
const left = secret_seed.len - i;
|
|
if (left > 0) state.addBytes(secret_seed[i..]);
|
|
state.addByte(0x80, left);
|
|
state.permute();
|
|
return Self{ .state = state };
|
|
}
|
|
|
|
pub fn random(self: *Self) Random {
|
|
return Random.init(self, fill);
|
|
}
|
|
|
|
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.clear(0, rate);
|
|
self.state.permuteR(8);
|
|
}
|