feature. See also
. The project being documented here (as the example) is the Zig library itself.
argon2.PhcFormatHasher
const PhcFormatHasher = struct
File
Code
const PhcFormatHasher = struct {
const BinValue = phc_format.BinValue;
const HashResult = struct {
alg_id: []const u8,
alg_version: ?u32,
m: u32,
t: u32,
p: u24,
salt: BinValue(max_salt_len),
hash: BinValue(max_hash_len),
};
pub fn create(
allocator: mem.Allocator,
password: []const u8,
params: Params,
mode: Mode,
buf: []u8,
io: Io,
) HasherError![]const u8 {
if (params.secret != null or params.ad != null) return HasherError.InvalidEncoding;
var salt: [default_salt_len]u8 = undefined;
io.random(&salt);
var hash: [default_hash_len]u8 = undefined;
try kdf(allocator, &hash, password, &salt, params, mode, io);
return phc_format.serialize(HashResult{
.alg_id = @tagName(mode),
.alg_version = version,
.m = params.m,
.t = params.t,
.p = params.p,
.salt = try BinValue(max_salt_len).fromSlice(&salt),
.hash = try BinValue(max_hash_len).fromSlice(&hash),
}, buf);
}
pub fn verify(
allocator: mem.Allocator,
str: []const u8,
password: []const u8,
io: Io,
) HasherError!void {
const hash_result = try phc_format.deserialize(HashResult, str);
const mode = std.meta.stringToEnum(Mode, hash_result.alg_id) orelse
return HasherError.PasswordVerificationFailed;
if (hash_result.alg_version) |v| {
if (v != version) return HasherError.InvalidEncoding;
}
const params = Params{ .t = hash_result.t, .m = hash_result.m, .p = hash_result.p };
const expected_hash = hash_result.hash.constSlice();
var hash_buf: [max_hash_len]u8 = undefined;
if (expected_hash.len > hash_buf.len) return HasherError.InvalidEncoding;
const hash = hash_buf[0..expected_hash.len];
try kdf(allocator, hash, password, hash_result.salt.constSlice(), params, mode, io);
if (!mem.eql(u8, hash, expected_hash)) return HasherError.PasswordVerificationFailed;
}
}