authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-12-30 23:15:25+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-30 22:15:25+00:00
logd86685ac9612c08e33f1d94f7f617d9c0da1b7bd
treeebfd508ec57baa6df1f9ead511bf0c277728bcc8
parente2d7b2bf339dac811b9ae77638f1d29b2ab32a23
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

sha3: define block_length as the rate, not as the state size (#14132)

In sponge-based constructions, the block size is not the same as the state size. For practical purposes, it's the same as the rate. Size this is a constant for a given type, we don't need to keep a copy of that value in the state itself. Just use the constant directly. This saves some bytes and may even be slightly faster. More importantly: Fixes #14128

1 files changed, 12 insertions(+), 10 deletions(-)

lib/std/crypto/sha3.zig+12-10
...@@ -14,17 +14,19 @@ pub const Keccak_512 = Keccak(512, 0x01);...@@ -14,17 +14,19 @@ pub const Keccak_512 = Keccak(512, 0x01);
14fn Keccak(comptime bits: usize, comptime delim: u8) type {14fn Keccak(comptime bits: usize, comptime delim: u8) type {
15 return struct {15 return struct {
16 const Self = @This();16 const Self = @This();
17 pub const block_length = 200;17 /// The output length, in bytes.
18 pub const digest_length = bits / 8;18 pub const digest_length = bits / 8;
19 /// The block length, or rate, in bytes.
20 pub const block_length = 200 - bits / 4;
21 /// Keccak does not have any options.
19 pub const Options = struct {};22 pub const Options = struct {};
2023
21 s: [200]u8,24 s: [200]u8,
22 offset: usize,25 offset: usize,
23 rate: usize,
2426
25 pub fn init(options: Options) Self {27 pub fn init(options: Options) Self {
26 _ = options;28 _ = options;
27 return Self{ .s = [_]u8{0} ** 200, .offset = 0, .rate = 200 - (bits / 4) };29 return Self{ .s = [_]u8{0} ** 200, .offset = 0 };
28 }30 }
2931
30 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {32 pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void {
...@@ -36,7 +38,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {...@@ -36,7 +38,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
36 pub fn update(d: *Self, b: []const u8) void {38 pub fn update(d: *Self, b: []const u8) void {
37 var ip: usize = 0;39 var ip: usize = 0;
38 var len = b.len;40 var len = b.len;
39 var rate = d.rate - d.offset;41 var rate = block_length - d.offset;
40 var offset = d.offset;42 var offset = d.offset;
4143
42 // absorb44 // absorb
...@@ -48,7 +50,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {...@@ -48,7 +50,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
4850
49 ip += rate;51 ip += rate;
50 len -= rate;52 len -= rate;
51 rate = d.rate;53 rate = block_length;
52 offset = 0;54 offset = 0;
53 }55 }
5456
...@@ -61,7 +63,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {...@@ -61,7 +63,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
61 pub fn final(d: *Self, out: *[digest_length]u8) void {63 pub fn final(d: *Self, out: *[digest_length]u8) void {
62 // padding64 // padding
63 d.s[d.offset] ^= delim;65 d.s[d.offset] ^= delim;
64 d.s[d.rate - 1] ^= 0x80;66 d.s[block_length - 1] ^= 0x80;
6567
66 keccakF(1600, &d.s);68 keccakF(1600, &d.s);
6769
...@@ -69,11 +71,11 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {...@@ -69,11 +71,11 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
69 var op: usize = 0;71 var op: usize = 0;
70 var len: usize = bits / 8;72 var len: usize = bits / 8;
7173
72 while (len >= d.rate) {74 while (len >= block_length) {
73 mem.copy(u8, out[op..], d.s[0..d.rate]);75 mem.copy(u8, out[op..], d.s[0..block_length]);
74 keccakF(1600, &d.s);76 keccakF(1600, &d.s);
75 op += d.rate;77 op += block_length;
76 len -= d.rate;78 len -= block_length;
77 }79 }
7880
79 mem.copy(u8, out[op..], d.s[0..len]);81 mem.copy(u8, out[op..], d.s[0..len]);