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
This commit is contained in:
Frank Denis 2022-12-30 23:15:25 +01:00 committed by GitHub
parent e2d7b2bf33
commit d86685ac96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -14,17 +14,19 @@ pub const Keccak_512 = Keccak(512, 0x01);
fn Keccak(comptime bits: usize, comptime delim: u8) type { fn Keccak(comptime bits: usize, comptime delim: u8) type {
return struct { return struct {
const Self = @This(); const Self = @This();
pub const block_length = 200; /// The output length, in bytes.
pub const digest_length = bits / 8; pub const digest_length = bits / 8;
/// The block length, or rate, in bytes.
pub const block_length = 200 - bits / 4;
/// Keccak does not have any options.
pub const Options = struct {}; pub const Options = struct {};
s: [200]u8, s: [200]u8,
offset: usize, offset: usize,
rate: usize,
pub fn init(options: Options) Self { pub fn init(options: Options) Self {
_ = options; _ = options;
return Self{ .s = [_]u8{0} ** 200, .offset = 0, .rate = 200 - (bits / 4) }; return Self{ .s = [_]u8{0} ** 200, .offset = 0 };
} }
pub fn hash(b: []const u8, out: *[digest_length]u8, options: Options) void { 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 {
pub fn update(d: *Self, b: []const u8) void { pub fn update(d: *Self, b: []const u8) void {
var ip: usize = 0; var ip: usize = 0;
var len = b.len; var len = b.len;
var rate = d.rate - d.offset; var rate = block_length - d.offset;
var offset = d.offset; var offset = d.offset;
// absorb // absorb
@ -48,7 +50,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
ip += rate; ip += rate;
len -= rate; len -= rate;
rate = d.rate; rate = block_length;
offset = 0; offset = 0;
} }
@ -61,7 +63,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
pub fn final(d: *Self, out: *[digest_length]u8) void { pub fn final(d: *Self, out: *[digest_length]u8) void {
// padding // padding
d.s[d.offset] ^= delim; d.s[d.offset] ^= delim;
d.s[d.rate - 1] ^= 0x80; d.s[block_length - 1] ^= 0x80;
keccakF(1600, &d.s); keccakF(1600, &d.s);
@ -69,11 +71,11 @@ fn Keccak(comptime bits: usize, comptime delim: u8) type {
var op: usize = 0; var op: usize = 0;
var len: usize = bits / 8; var len: usize = bits / 8;
while (len >= d.rate) { while (len >= block_length) {
mem.copy(u8, out[op..], d.s[0..d.rate]); mem.copy(u8, out[op..], d.s[0..block_length]);
keccakF(1600, &d.s); keccakF(1600, &d.s);
op += d.rate; op += block_length;
len -= d.rate; len -= block_length;
} }
mem.copy(u8, out[op..], d.s[0..len]); mem.copy(u8, out[op..], d.s[0..len]);