Function opensshKdf [src]
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).
Prototype
pub fn opensshKdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void
Parameters
pass: []const u8
salt: []const u8
key: []u8
rounds: u32
Source
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);
}