Type Function Composition [src]
The composition of two hash functions: H1 o H2, with the same API as regular hash functions.
The security level of a hash cascade doesn't exceed the security level of the weakest function.
However, Merkle–Damgård constructions such as SHA-256 are vulnerable to length-extension attacks,
where under some conditions, H(x||e) can be efficiently computed without knowing x.
The composition of two hash functions is a common defense against such attacks.
This is not necessary with modern hash functions, such as SHA-3, BLAKE2 and BLAKE3.
Prototype
pub fn Composition(comptime H1: type, comptime H2: type) type
Parameters
H1: type
H2: type
Source
pub fn Composition(comptime H1: type, comptime H2: type) type {
return struct {
const Self = @This();
H1: H1,
H2: H2,
/// The length of the hash output, in bytes.
pub const digest_length = H1.digest_length;
/// The block length, in bytes.
pub const block_length = H1.block_length;
/// Options for both hashes.
pub const Options = struct {
/// Options for H1.
H1: H1.Options = .{},
/// Options for H2.
H2: H2.Options = .{},
};
/// Initialize the hash composition with the given options.
pub fn init(options: Options) Self {
return Self{ .H1 = H1.init(options.H1), .H2 = H2.init(options.H2) };
}
/// Compute H1(H2(b)).
pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
var d = Self.init(options);
d.update(b);
d.final(out);
}
/// Add content to the hash.
pub fn update(d: *Self, b: []const u8) void {
d.H2.update(b);
}
/// Compute the final hash for the accumulated content: H1(H2(b)).
pub fn final(d: *Self, out: *[digest_length]u8) void {
var H2_digest: [H2.digest_length]u8 = undefined;
d.H2.final(&H2_digest);
d.H1.update(&H2_digest);
d.H1.final(out);
}
};
}