Merge pull request #398 from mir-protocol/injective_hash_conversion

Use 7 bytes to represent a field element to avoid collisions in hash conversion
This commit is contained in:
wborgeaud 2021-12-20 09:22:53 +01:00 committed by GitHub
commit 30cf4cd0a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,8 +3,6 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::field::field_types::{Field, PrimeField, RichField};
use crate::iop::target::Target;
use crate::util::ceil_div_usize;
use crate::util::serialization::Buffer;
/// Represents a ~256 bit hash output.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
@ -162,10 +160,14 @@ impl<const N: usize> From<BytesHash<N>> for u64 {
impl<F: RichField, const N: usize> From<BytesHash<N>> for Vec<F> {
fn from(hash: BytesHash<N>) -> Self {
let n = hash.0.len();
let mut v = hash.0.to_vec();
v.resize(ceil_div_usize(n, 8) * 8, 0);
let mut buffer = Buffer::new(v);
buffer.read_field_vec(buffer.len() / 8).unwrap()
hash.0
// Chunks of 7 bytes since 8 bytes would allow collisions.
.chunks(7)
.map(|bytes| {
let mut arr = [0; 8];
arr[..bytes.len()].copy_from_slice(bytes);
F::from_canonical_u64(u64::from_le_bytes(arr))
})
.collect()
}
}