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.

KMacLike

sha3.KMacLike
fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type

File

lib/std/crypto/sha3.zig:279

Code

fn KMacLike(comptime security_level: u11, comptime default_delim: u8, comptime rounds: u5) type {
    const CShaker = CShakeLike(security_level, default_delim, rounds, "KMAC");

    return struct {
        const Self = @This();

        /// The recommended output length, in bytes.
        pub const mac_length = CShaker.digest_length;
        /// The minimum output length, in bytes.
        pub const mac_length_min = 4;
        /// The recommended key length, in bytes.
        pub const key_length = security_level / 8;
        /// The minimum key length, in bytes.
        pub const key_length_min = 0;
        /// The block length, or rate, in bytes.
        pub const block_length = CShaker.block_length;

        cshaker: CShaker,
        xof_mode: bool = false,

        /// KMAC options can include a context string.
        pub const Options = struct {
            context: ?[]const u8 = null,
        };

        /// Initialize a state for the KMAC function, with an optional context and an arbitrary-long key.
        /// If the context and key are going to be reused, the structure can be initialized once, and cloned for each message.
        /// This is more efficient than reinitializing the state for each message at the cost of a small amount of memory.
        pub fn initWithOptions(key: []const u8, options: Options) Self {
            var cshaker = CShaker.init(.{ .context = options.context });
            const encoded_rate_len = NistLengthEncoding.encode(.left, block_length / 8);
            cshaker.update(encoded_rate_len.slice());
            const encoded_key_len = NistLengthEncoding.encode(.left, key.len);
            cshaker.update(encoded_key_len.slice());
            cshaker.update(key);
            cshaker.fillBlock();
            return Self{
                .cshaker = cshaker,
            };
        }

        /// Initialize a state for the KMAC function.
        /// If the context and key are going to be reused, the structure can be initialized once, and cloned for each message.
        /// This is more efficient than reinitializing the state for each message at the cost of a small amount of memory.
        pub fn init(key: []const u8) Self {
            return initWithOptions(key, .{});
        }

        /// Add data to the state.
        pub fn update(self: *Self, b: []const u8) void {
            self.cshaker.update(b);
        }

        /// Return an authentication tag for the current state.
        pub fn final(self: *Self, out: []u8) void {
            const encoded_out_len = NistLengthEncoding.encode(.right, out.len);
            self.update(encoded_out_len.slice());
            self.cshaker.final(out);
        }

        /// Squeeze a slice of bytes from the state.
        /// `out` can be any length, and the function can be called multiple times.
        pub fn squeeze(self: *Self, out: []u8) void {
            if (!self.xof_mode) {
                const encoded_out_len = comptime NistLengthEncoding.encode(.right, 0);
                self.update(encoded_out_len.slice());
                self.xof_mode = true;
            }
            self.cshaker.squeeze(out);
        }

        /// Return an authentication tag for a message and a key, with an optional context.
        pub fn createWithOptions(out: []u8, msg: []const u8, key: []const u8, options: Options) void {
            var ctx = Self.initWithOptions(key, options);
            ctx.update(msg);
            ctx.final(out);
        }

        /// Return an authentication tag for a message and a key.
        pub fn create(out: []u8, msg: []const u8, key: []const u8) void {
            var ctx = Self.init(key);
            ctx.update(msg);
            ctx.final(out);
        }
    };
}