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.

opensshKdf

The function used in OpenSSH to derive encryption keys from passphrases.

This implementation is compatible with the OpenBSD implementation (https://github.com/openbsd/src/blob/master/lib/libutil/bcrypt_pbkdf.c).

bcrypt.opensshKdf
pub fn opensshKdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void

File

lib/std/crypto/bcrypt.zig:571

Code

pub fn opensshKdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void {
    var tmp: [32]u8 = undefined;
    var tmp2: [32]u8 = undefined;
    if (rounds < 1 or pass.len == 0 or salt.len == 0 or key.len == 0 or key.len > tmp.len * tmp.len) {
        return error.InvalidInput;
    }
    var sha2pass: [Sha512.digest_length]u8 = undefined;
    Sha512.hash(pass, &sha2pass, .{});
    const stride = (key.len + tmp.len - 1) / tmp.len;
    var amt = (key.len + stride - 1) / stride;
    if (math.shr(usize, key.len, 32) >= amt) {
        return error.InvalidInput;
    }
    var key_remainder = key.len;
    var count: u32 = 1;
    while (key_remainder > 0) : (count += 1) {
        var count_salt: [4]u8 = undefined;
        std.mem.writeInt(u32, count_salt[0..], count, .big);
        var sha2salt: [Sha512.digest_length]u8 = undefined;
        var h = Sha512.init(.{});
        h.update(salt);
        h.update(&count_salt);
        h.final(&sha2salt);
        tmp2 = pbkdf_prf.hash(sha2pass, sha2salt);
        tmp = tmp2;
        for (1..rounds) |_| {
            Sha512.hash(&tmp2, &sha2salt, .{});
            tmp2 = pbkdf_prf.hash(sha2pass, sha2salt);
            for (&tmp, tmp2) |*o, t| o.* ^= t;
        }
        amt = @min(amt, key_remainder);
        key_remainder -= for (0..amt) |i| {
            const dest = i * stride + (count - 1);
            if (dest >= key.len) break i;
            key[dest] = tmp[i];
        } else amt;
    }
    crypto.secureZero(u8, &tmp);
    crypto.secureZero(u8, &tmp2);
    crypto.secureZero(u8, &sha2pass);
}