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.

pbkdf_prf

bcrypt.pbkdf_prf
const pbkdf_prf = struct

File

lib/std/crypto/bcrypt.zig:487

Code

const pbkdf_prf = struct {
    const Self = @This();
    pub const mac_length = 32;

    hasher: Sha512,
    sha2pass: [Sha512.digest_length]u8,

    pub fn create(out: *[mac_length]u8, msg: []const u8, key: []const u8) void {
        var ctx = Self.init(key);
        ctx.update(msg);
        ctx.final(out);
    }

    pub fn init(key: []const u8) Self {
        var self: Self = undefined;
        self.hasher = Sha512.init(.{});
        Sha512.hash(key, &self.sha2pass, .{});
        return self;
    }

    pub fn update(self: *Self, msg: []const u8) void {
        self.hasher.update(msg);
    }

    pub fn final(self: *Self, out: *[mac_length]u8) void {
        var sha2salt: [Sha512.digest_length]u8 = undefined;
        self.hasher.final(&sha2salt);
        out.* = hash(self.sha2pass, sha2salt);
    }

    /// Matches OpenBSD function
    /// https://github.com/openbsd/src/blob/6df1256b7792691e66c2ed9d86a8c103069f9e34/lib/libutil/bcrypt_pbkdf.c#L98
    pub fn hash(sha2pass: [Sha512.digest_length]u8, sha2salt: [Sha512.digest_length]u8) [32]u8 {
        var cdata: [8]u32 = undefined;
        {
            const ciphertext = "OxychromaticBlowfishSwatDynamite";
            var j: usize = 0;
            for (&cdata) |*v| {
                v.* = State.toWord(ciphertext, &j);
            }
        }

        var state = State{};

        { // key expansion
            state.expand(&sha2salt, &sha2pass);
            var i: usize = 0;
            while (i < 64) : (i += 1) {
                state.expand0(&sha2salt);
                state.expand0(&sha2pass);
            }
        }

        { // encryption
            var i: usize = 0;
            while (i < 64) : (i += 1) {
                state.encrypt(&cdata);
            }
        }

        // copy out
        var out: [32]u8 = undefined;
        for (cdata, 0..) |v, i| {
            std.mem.writeInt(u32, out[4 * i ..][0..4], v, .little);
        }

        // zap
        crypto.secureZero(u32, &cdata);
        crypto.secureZero(u32, &state.subkeys);

        return out;
    }
}