mirror of
https://github.com/ziglang/zig.git
synced 2024-11-21 19:42:56 +00:00
Compare commits
7 Commits
865756bec3
...
cd8ebbf8fa
Author | SHA1 | Date | |
---|---|---|---|
|
cd8ebbf8fa | ||
|
f845fa04a0 | ||
|
8303125879 | ||
|
941cbf1c25 | ||
|
002cadb27d | ||
|
68245c22be | ||
|
7e661111ed |
@ -563,15 +563,57 @@ const pbkdf_prf = struct {
|
||||
};
|
||||
|
||||
/// bcrypt-pbkdf is a key derivation function based on bcrypt.
|
||||
/// This is 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).
|
||||
///
|
||||
/// Unlike the password hashing function `bcrypt`, this function doesn't silently truncate passwords longer than 72 bytes.
|
||||
pub fn pbkdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void {
|
||||
try crypto.pwhash.pbkdf2(key, pass, salt, rounds, pbkdf_prf);
|
||||
}
|
||||
|
||||
/// 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).
|
||||
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);
|
||||
}
|
||||
|
||||
const crypt_format = struct {
|
||||
/// String prefix for bcrypt
|
||||
pub const prefix = "$2";
|
||||
@ -847,3 +889,13 @@ test "bcrypt phc format" {
|
||||
verify_options,
|
||||
);
|
||||
}
|
||||
|
||||
test "openssh kdf" {
|
||||
var key: [100]u8 = undefined;
|
||||
const pass = "password";
|
||||
const salt = "salt";
|
||||
const rounds = 5;
|
||||
try opensshKdf(pass, salt, &key, rounds);
|
||||
const expected = [_]u8{ 65, 207, 68, 58, 55, 252, 114, 141, 255, 65, 216, 175, 5, 92, 235, 68, 220, 92, 118, 161, 40, 13, 241, 190, 56, 152, 69, 136, 41, 214, 51, 205, 37, 221, 101, 59, 105, 73, 133, 36, 14, 59, 94, 212, 111, 107, 109, 237, 213, 235, 246, 119, 59, 76, 45, 130, 142, 81, 178, 231, 161, 158, 138, 108, 18, 162, 26, 50, 218, 251, 23, 66, 2, 232, 20, 202, 216, 46, 12, 250, 247, 246, 252, 23, 155, 74, 77, 195, 120, 113, 57, 88, 126, 81, 9, 249, 72, 18, 208, 160 };
|
||||
try testing.expectEqualSlices(u8, &key, &expected);
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ fn read(ma: *MemoryAccessor, address: usize, buf: []u8) bool {
|
||||
switch (linux.E.init(bytes_read)) {
|
||||
.SUCCESS => return bytes_read == buf.len,
|
||||
.FAULT => return false,
|
||||
.INVAL, .PERM, .SRCH => unreachable, // own pid is always valid
|
||||
.INVAL, .SRCH => unreachable, // own pid is always valid
|
||||
.PERM => {}, // Known to happen in containers.
|
||||
.NOMEM => {},
|
||||
.NOSYS => {}, // QEMU is known not to implement this syscall.
|
||||
else => unreachable, // unexpected
|
||||
|
Loading…
Reference in New Issue
Block a user