twenty-first
twenty-first copied to clipboard
bug: digest bytes in do not match bytes out.
In the course of testing hex encode/decode, I discovered that it is possible to create a Digest
from input bytes that subsequently produces different output bytes.
Here is a failing test case, suitable for use in digest.rs.
#[test]
pub fn bytes_in_matches_bytes_out() {
let bytes1: [u8; 40] = [255; 40];
let d1 = Digest::from(bytes1);
let bytes2: [u8; 40] = d1.into();
let d2 = Digest::from(bytes2);
println!("bytes1: {:?}", bytes1);
println!("bytes2: {:?}", bytes2);
assert_eq!(d1, d2);
assert_eq!(bytes1, bytes2);
}
This test fails with:
---- math::digest::digest_tests::bytes_in_matches_bytes_out stdout ----
bytes1: [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
bytes2: [254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0]
thread 'math::digest::digest_tests::bytes_in_matches_bytes_out' panicked at twenty-first/src/math/digest.rs:474:9:
assertion `left == right` failed
left: [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
right: [254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0, 254, 255, 255, 255, 0, 0, 0, 0]
note that:
-
bytes2
is quite different frombytes1
. - digests
d1
andd2
are equal, although d2 was created from bytes2.
Taken together, this suggests that the input value is being normalized into a smaller internal max value.
Importantly, if the first line is changed to:
let bytes1: [u8; 40] = [254; 40];
Then the test passes. So there is something special about [255; 40]. (and possibly other values?)
if bytes1 is somehow an invalid (too large) input, then it seems that Digest::from()
should panic, and/or we should only support try_from()
. At present, we are silently losing/changing information, but only for certain input values.