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.

Hkdf

The Hkdf construction takes some source of initial keying material and derives one or more uniform keys from it.

hkdf.Hkdf
pub fn Hkdf(comptime Hmac: type) type

File

lib/std/crypto/hkdf.zig:14

Code

pub fn Hkdf(comptime Hmac: type) type {
    return struct {
        /// Length of a master key, in bytes.
        pub const prk_length = Hmac.mac_length;

        /// Return a master key from a salt and initial keying material.
        pub fn extract(salt: []const u8, ikm: []const u8) [prk_length]u8 {
            var prk: [prk_length]u8 = undefined;
            Hmac.create(&prk, ikm, salt);
            return prk;
        }

        /// Initialize the creation of a master key from a salt
        /// and keying material that can be added later, possibly in chunks.
        /// Example:
        /// ```
        /// var prk: [hkdf.prk_length]u8 = undefined;
        /// var hkdf = HkdfSha256.extractInit(salt);
        /// hkdf.update(ikm1);
        /// hkdf.update(ikm2);
        /// hkdf.final(&prk);
        /// ```
        pub fn extractInit(salt: []const u8) Hmac {
            return Hmac.init(salt);
        }

        /// Derive a subkey from a master key `prk` and a subkey description `ctx`.
        pub fn expand(out: []u8, ctx: []const u8, prk: [prk_length]u8) void {
            assert(out.len <= prk_length * 255); // output size is too large for the Hkdf construction
            var i: usize = 0;
            var counter = [1]u8{1};
            while (i + prk_length <= out.len) : (i += prk_length) {
                var st = Hmac.init(&prk);
                if (i != 0) {
                    st.update(out[i - prk_length ..][0..prk_length]);
                }
                st.update(ctx);
                st.update(&counter);
                st.final(out[i..][0..prk_length]);
                counter[0] +%= 1;
                assert(counter[0] != 1);
            }
            const left = out.len % prk_length;
            if (left > 0) {
                var st = Hmac.init(&prk);
                if (i != 0) {
                    st.update(out[i - prk_length ..][0..prk_length]);
                }
                st.update(ctx);
                st.update(&counter);
                var tmp: [prk_length]u8 = undefined;
                st.final(tmp[0..prk_length]);
                @memcpy(out[i..][0..left], tmp[0..left]);
            }
        }
    };
}