Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

AsconXof128

Ascon-XOF128 as specified in NIST SP 800-232 Section 5

ascon.AsconXof128
pub const AsconXof128 = struct

File

lib/std/crypto/ascon.zig:679

Code

pub const AsconXof128 = struct {
    pub const block_length = 8;

    st: AsconState,
    squeezed: bool,
    buf: [block_length]u8,
    buf_len: usize,

    pub const Options = struct {};

    /// Initialize a new Ascon-XOF128 extendable output function.
    ///
    /// Parameters:
    ///   - options: Configuration options (currently unused)
    ///
    /// Returns: An initialized AsconXof128 instance
    pub fn init(options: Options) AsconXof128 {
        _ = options;

        // IV for Ascon-XOF128: 0x0000080000cc0003
        const iv: u64 = 0x0000080000cc0003;
        const words: [5]u64 = .{ iv, 0, 0, 0, 0 };
        var st = AsconState.initFromWords(words);
        st.permuteR(12);
        return AsconXof128{ .st = st, .squeezed = false, .buf = @splat(0), .buf_len = 0 };
    }

    /// Hash a slice of bytes with variable-length output.
    ///
    /// Parameters:
    ///   - bytes: Input data to hash
    ///   - out: Output buffer (can be any length)
    ///   - options: Configuration options (currently unused)
    ///
    /// Note: Convenience function that combines init, update, and squeeze
    pub fn hash(bytes: []const u8, out: []u8, options: Options) void {
        var st = init(options);
        st.update(bytes);
        st.squeeze(out);
    }

    /// Update the XOF state with additional data.
    ///
    /// Parameters:
    ///   - b: Data to absorb into the XOF state
    ///
    /// Note: Cannot be called after squeeze() has been called
    pub fn update(self: *AsconXof128, b: []const u8) void {
        debug.assert(!self.squeezed); // Cannot update after squeezing

        var i: usize = 0;

        if (self.buf_len > 0) {
            const to_fill = @min(block_length - self.buf_len, b.len);
            @memcpy(self.buf[self.buf_len..][0..to_fill], b[0..to_fill]);
            self.buf_len += to_fill;
            i += to_fill;
            if (self.buf_len == block_length) {
                self.st.addBytes(&self.buf);
                self.st.permuteR(12);
                self.buf_len = 0;
            }
        }

        while (i + block_length <= b.len) : (i += block_length) {
            self.st.addBytes(b[i..][0..block_length]);
            self.st.permuteR(12);
        }

        if (i < b.len) {
            self.buf_len = b.len - i;
            @memcpy(self.buf[0..self.buf_len], b[i..]);
        }
    }

    /// Squeeze output bytes from the XOF.
    ///
    /// Parameters:
    ///   - out: Output buffer to fill with pseudorandom bytes
    ///
    /// Note: Can be called multiple times to generate more output.
    /// After first call, no more data can be absorbed with update().
    pub fn squeeze(self: *AsconXof128, out: []u8) void {
        if (!self.squeezed) {
            var padded: [block_length]u8 = @splat(0);
            @memcpy(padded[0..self.buf_len], self.buf[0..self.buf_len]);
            padded[self.buf_len] = 0x01;
            self.st.addBytes(&padded);
            self.st.permuteR(12);
            self.squeezed = true;
        }

        var i: usize = 0;
        while (i < out.len) {
            const to_copy = @min(8, out.len - i);
            var block: [8]u8 = undefined;
            mem.writeInt(u64, &block, self.st.st[0], .little);
            @memcpy(out[i..][0..to_copy], block[0..to_copy]);
            i += to_copy;

            if (i < out.len) {
                self.st.permuteR(12);
            }
        }
    }
}