Skip to content

std.crypto.hash.sha3: add TurboSHAKE #14824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/std/crypto/benchmark.zig
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const hashes = [_]Crypto{
Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },
Crypto{ .ty = crypto.hash.sha3.Shake128, .name = "shake-128" },
Crypto{ .ty = crypto.hash.sha3.Shake256, .name = "shake-256" },
Crypto{ .ty = crypto.hash.sha3.TurboShake128(null), .name = "turboshake-128" },
Crypto{ .ty = crypto.hash.sha3.TurboShake256(null), .name = "turboshake-256" },
Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" },
Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },
Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },
Expand Down
4 changes: 2 additions & 2 deletions lib/std/crypto/keccak_p.zig
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ pub fn KeccakF(comptime f: u11) type {
/// Apply a (possibly) reduced-round permutation to the state.
pub fn permuteR(self: *Self, comptime rounds: u5) void {
var i = RC.len - rounds;
while (i < rounds - rounds % 3) : (i += 3) {
while (i < RC.len - RC.len % 3) : (i += 3) {
self.round(RC[i]);
self.round(RC[i + 1]);
self.round(RC[i + 2]);
}
while (i < rounds) : (i += 1) {
while (i < RC.len) : (i += 1) {
self.round(RC[i]);
}
}
Expand Down
33 changes: 31 additions & 2 deletions lib/std/crypto/sha3.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ pub const Keccak_512 = @compileError("Deprecated: use `Keccak512` instead");
pub const Shake128 = Shake(128);
pub const Shake256 = Shake(256);

/// TurboSHAKE128 is a XOF (a secure hash function with a variable output length), with a 128 bit security level.
/// It is based on the same permutation as SHA3 and SHAKE128, but which much higher performance.
/// The delimiter is 0x01 by default, but can be changed for context-separation.
pub fn TurboShake128(comptime delim: ?u8) type {
return TurboShake(128, delim);
}

/// TurboSHAKE256 is a XOF (a secure hash function with a variable output length), with a 256 bit security level.
/// It is based on the same permutation as SHA3 and SHAKE256, but which much higher performance.
/// The delimiter is 0x01 by default, but can be changed for context-separation.
pub fn TurboShake256(comptime delim: ?u8) type {
return TurboShake(256, delim);
}

/// A generic Keccak hash function.
pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, comptime rounds: u5) type {
comptime assert(output_bits > 0 and output_bits * 2 < f and output_bits % 8 == 0); // invalid output length
Expand Down Expand Up @@ -76,9 +90,18 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, co

/// The SHAKE extendable output hash function.
pub fn Shake(comptime security_level: u11) type {
return ShakeLike(security_level, 0x1f, 24);
}

/// The TurboSHAKE extendable output hash function.
/// https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/
pub fn TurboShake(comptime security_level: u11, comptime delim: ?u8) type {
return ShakeLike(security_level, delim orelse 0x01, 12);
}

fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds: u5) type {
const f = 1600;
const rounds = 24;
const State = KeccakState(f, security_level * 2, 0x1f, rounds);
const State = KeccakState(f, security_level * 2, delim, rounds);

return struct {
const Self = @This();
Expand Down Expand Up @@ -348,3 +371,9 @@ test "SHAKE-256 single" {
Shake256.hash("hello123", &out, .{});
try htest.assertEqual("ade612ba265f92de4a37", &out);
}

test "TurboSHAKE-128" {
var out: [32]u8 = undefined;
TurboShake(128, 0x06).hash("\xff", &out, .{});
try htest.assertEqual("8ec9c66465ed0d4a6c35d13506718d687a25cb05c74cca1e42501abd83874a67", &out);
}