Skip to content

AHasher::write for the fallback algorithm and AES implementations discards up to 15 trailing bytes #288

@yorickpeterse

Description

@yorickpeterse

While working on porting aHash to https://github.com/inko-lang/inko I ran into the following:

aHash/src/fallback_hash.rs

Lines 170 to 192 in a9d649d

fn write(&mut self, input: &[u8]) {
let mut data = input;
let length = data.len() as u64;
//Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE);
//A 'binary search' on sizes reduces the number of comparisons.
if data.len() > 8 {
if data.len() > 16 {
let tail = data.read_last_u128();
self.large_update(tail);
while data.len() > 16 {
let (block, rest) = data.read_u128();
self.large_update(block);
data = rest;
}
} else {
self.large_update([data.read_u64().0, data.read_last_u64()].convert());
}
} else {
let value = read_small(data);
self.large_update(value.convert());
}
}

Specifically the following part appears problematic, at least at first sight:

aHash/src/fallback_hash.rs

Lines 180 to 184 in a9d649d

while data.len() > 16 {
let (block, rest) = data.read_u128();
self.large_update(block);
data = rest;
}

Imagine the input buffer is 18 bytes long. The following condition is then true:

while data.len() > 16 {

Which means it runs this:

aHash/src/fallback_hash.rs

Lines 181 to 183 in a9d649d

let (block, rest) = data.read_u128();
self.large_update(block);
data = rest;

The read_u128 will then return (16 bytes of data, 2 bytes of data). Because of the data = rest assignment, the next hit of while data.len() > 16 translates into 2 > 16 and thus the loop isn't run.

Or more precisely, if the input size is not a multiple of 16 then up to 15 trailing bytes of input are not hashed.

I have a hard time imagining that this is in fact desired. Should that entire method not run in a loop to account for those trailing 15 bytes, or did I perhaps overlook something that causes those trailing bytes to still be hashed?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions