authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-03-07 10:04:45+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-07 10:04:45+01:00
log36d47dd1991f0ccd7a9673075624f09500cc415e
tree2937c64a27ae39b830d4b3c91a68f31b7c5986ed
parent6218e4004608000ba2e42e07ed1bd56745626820
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

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


3 files changed, 35 insertions(+), 4 deletions(-)

lib/std/crypto/benchmark.zig+2
...@@ -27,6 +27,8 @@ const hashes = [_]Crypto{...@@ -27,6 +27,8 @@ const hashes = [_]Crypto{
27 Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },27 Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },
28 Crypto{ .ty = crypto.hash.sha3.Shake128, .name = "shake-128" },28 Crypto{ .ty = crypto.hash.sha3.Shake128, .name = "shake-128" },
29 Crypto{ .ty = crypto.hash.sha3.Shake256, .name = "shake-256" },29 Crypto{ .ty = crypto.hash.sha3.Shake256, .name = "shake-256" },
30 Crypto{ .ty = crypto.hash.sha3.TurboShake128(null), .name = "turboshake-128" },
31 Crypto{ .ty = crypto.hash.sha3.TurboShake256(null), .name = "turboshake-256" },
30 Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" },32 Crypto{ .ty = crypto.hash.Gimli, .name = "gimli-hash" },
31 Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },33 Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },
32 Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },34 Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },
lib/std/crypto/keccak_p.zig+2-2
...@@ -175,12 +175,12 @@ pub fn KeccakF(comptime f: u11) type {...@@ -175,12 +175,12 @@ pub fn KeccakF(comptime f: u11) type {
175 /// Apply a (possibly) reduced-round permutation to the state.175 /// Apply a (possibly) reduced-round permutation to the state.
176 pub fn permuteR(self: *Self, comptime rounds: u5) void {176 pub fn permuteR(self: *Self, comptime rounds: u5) void {
177 var i = RC.len - rounds;177 var i = RC.len - rounds;
178 while (i < rounds - rounds % 3) : (i += 3) {178 while (i < RC.len - RC.len % 3) : (i += 3) {
179 self.round(RC[i]);179 self.round(RC[i]);
180 self.round(RC[i + 1]);180 self.round(RC[i + 1]);
181 self.round(RC[i + 2]);181 self.round(RC[i + 2]);
182 }182 }
183 while (i < rounds) : (i += 1) {183 while (i < RC.len) : (i += 1) {
184 self.round(RC[i]);184 self.round(RC[i]);
185 }185 }
186 }186 }
lib/std/crypto/sha3.zig+31-2
...@@ -18,6 +18,20 @@ pub const Keccak_512 = @compileError("Deprecated: use `Keccak512` instead");...@@ -18,6 +18,20 @@ pub const Keccak_512 = @compileError("Deprecated: use `Keccak512` instead");
18pub const Shake128 = Shake(128);18pub const Shake128 = Shake(128);
19pub const Shake256 = Shake(256);19pub const Shake256 = Shake(256);
2020
21/// TurboSHAKE128 is a XOF (a secure hash function with a variable output length), with a 128 bit security level.
22/// It is based on the same permutation as SHA3 and SHAKE128, but which much higher performance.
23/// The delimiter is 0x01 by default, but can be changed for context-separation.
24pub fn TurboShake128(comptime delim: ?u8) type {
25 return TurboShake(128, delim);
26}
27
28/// TurboSHAKE256 is a XOF (a secure hash function with a variable output length), with a 256 bit security level.
29/// It is based on the same permutation as SHA3 and SHAKE256, but which much higher performance.
30/// The delimiter is 0x01 by default, but can be changed for context-separation.
31pub fn TurboShake256(comptime delim: ?u8) type {
32 return TurboShake(256, delim);
33}
34
21/// A generic Keccak hash function.35/// A generic Keccak hash function.
22pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, comptime rounds: u5) type {36pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, comptime rounds: u5) type {
23 comptime assert(output_bits > 0 and output_bits * 2 < f and output_bits % 8 == 0); // invalid output length37 comptime assert(output_bits > 0 and output_bits * 2 < f and output_bits % 8 == 0); // invalid output length
...@@ -76,9 +90,18 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, co...@@ -76,9 +90,18 @@ pub fn Keccak(comptime f: u11, comptime output_bits: u11, comptime delim: u8, co
7690
77/// The SHAKE extendable output hash function.91/// The SHAKE extendable output hash function.
78pub fn Shake(comptime security_level: u11) type {92pub fn Shake(comptime security_level: u11) type {
93 return ShakeLike(security_level, 0x1f, 24);
94}
95
96/// The TurboSHAKE extendable output hash function.
97/// https://datatracker.ietf.org/doc/draft-irtf-cfrg-kangarootwelve/
98pub fn TurboShake(comptime security_level: u11, comptime delim: ?u8) type {
99 return ShakeLike(security_level, delim orelse 0x01, 12);
100}
101
102fn ShakeLike(comptime security_level: u11, comptime delim: u8, comptime rounds: u5) type {
79 const f = 1600;103 const f = 1600;
80 const rounds = 24;104 const State = KeccakState(f, security_level * 2, delim, rounds);
81 const State = KeccakState(f, security_level * 2, 0x1f, rounds);
82105
83 return struct {106 return struct {
84 const Self = @This();107 const Self = @This();
...@@ -348,3 +371,9 @@ test "SHAKE-256 single" {...@@ -348,3 +371,9 @@ test "SHAKE-256 single" {
348 Shake256.hash("hello123", &out, .{});371 Shake256.hash("hello123", &out, .{});
349 try htest.assertEqual("ade612ba265f92de4a37", &out);372 try htest.assertEqual("ade612ba265f92de4a37", &out);
350}373}
374
375test "TurboSHAKE-128" {
376 var out: [32]u8 = undefined;
377 TurboShake(128, 0x06).hash("\xff", &out, .{});
378 try htest.assertEqual("8ec9c66465ed0d4a6c35d13506718d687a25cb05c74cca1e42501abd83874a67", &out);
379}