Ascon-Hash256 as specified in NIST SP 800-232 Section 5
pub const AsconHash256 = struct
pub const AsconHash256 = struct {
pub const digest_length = 32;
pub const block_length = 8;
st: AsconState,
pub const Options = struct {};
/// Initialize a new Ascon-Hash256 hasher.
///
/// Parameters:
/// - options: Configuration options (currently unused)
///
/// Returns: An initialized AsconHash256 hasher
pub fn init(options: Options) AsconHash256 {
_ = options;
// IV for Ascon-Hash256: 0x0000080100cc0002
const iv: u64 = 0x0000080100cc0002;
const words: [5]u64 = .{ iv, 0, 0, 0, 0 };
var st = AsconState.initFromWords(words);
st.permuteR(12);
return AsconHash256{ .st = st };
}
/// Compute Ascon-Hash256 hash of input data in one call.
///
/// Parameters:
/// - b: Input data to hash
/// - out: Output buffer for 32-byte hash digest
/// - options: Configuration options (currently unused)
pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
var h = init(options);
h.update(b);
h.final(out);
}
/// Update the hash state with additional data.
///
/// Parameters:
/// - b: Data to add to the hash
///
/// Note: Can be called multiple times before final()
pub fn update(self: *AsconHash256, b: []const u8) void {
var i: usize = 0;
// Process full 64-bit blocks
while (i + 8 <= b.len) : (i += 8) {
self.st.addBytes(b[i..][0..8]);
self.st.permuteR(12);
}
// Store partial block for finalization
if (i < b.len) {
var padded: [8]u8 = @splat(0);
const remaining = b.len - i;
@memcpy(padded[0..remaining], b[i..]);
padded[remaining] = 0x01;
self.st.addBytes(&padded);
} else {
// Add padding block
var padded: [8]u8 = @splat(0);
padded[0] = 0x01;
self.st.addBytes(&padded);
}
}
/// Finalize the hash and output the digest.
///
/// Parameters:
/// - out: Output buffer for 32-byte hash digest
///
/// Note: After calling final(), the hasher should not be used again
pub fn final(self: *AsconHash256, out: *[digest_length]u8) void {
// Final permutation after padding
self.st.permuteR(12);
// Extract hash output (4 × 64 bits = 256 bits)
var h: [4]u64 = undefined;
for (0..4) |i| {
h[i] = self.st.st[0];
self.st.permuteR(12);
}
// Write output
for (0..4) |i| {
mem.writeInt(u64, out[i * 8 ..][0..8], h[i], .little);
}
}
}