arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
Merge pull request #40 from 0xPolygonMiden/kaneki-domain-separator

Domain separator during merge
Kaneki (カネキ ケン) 100861945+0xKanekiKen@users.noreply.github.com
Mon, 23 Jan 2023 20:20:38 +0000
commit

6de7730e30353c4c889591a52126415ac4819349

parent

581887916f5b814b6fb035d6ce16f7967a0791bf

2 files changed, 58 insertions(+), 1 deletions(-)

jump to
M src/hash/rpo/mod.rs → src/hash/rpo/mod.rs

@@ -294,6 +294,28 @@ pub fn hash_elements<E: FieldElement<BaseField = Felt>>(elements: &[E]) -> RpoDigest {

<Self as ElementHasher>::hash_elements(elements) } + // DOMAIN IDENTIFIER + // -------------------------------------------------------------------------------------------- + + /// Returns a hash of two digests and a domain identifier. + pub fn merge_in_domain(values: &[RpoDigest; 2], domain: Felt) -> RpoDigest { + // initialize the state by copying the digest elements into the rate portion of the state + // (8 total elements), and set the capacity elements to 0. + let mut state = [ZERO; STATE_WIDTH]; + let it = RpoDigest::digests_as_elements(values.iter()); + for (i, v) in it.enumerate() { + state[RATE_RANGE.start + i] = *v; + } + + // set the second capacity element to the domain value. The first capacity element is used + // for padding purposes. + state[CAPACITY_RANGE.start + 1] = domain; + + // apply the RPO permutation and return the first four elements of the state + Self::apply_permutation(&mut state); + RpoDigest::new(state[DIGEST_RANGE].try_into().unwrap()) + } + // RESCUE PERMUTATION // --------------------------------------------------------------------------------------------
M src/hash/rpo/tests.rs → src/hash/rpo/tests.rs

@@ -1,5 +1,6 @@

use super::{ - Felt, FieldElement, Hasher, Rpo256, RpoDigest, StarkField, ALPHA, INV_ALPHA, STATE_WIDTH, ZERO, + Felt, FieldElement, Hasher, Rpo256, RpoDigest, StarkField, ALPHA, CAPACITY_RANGE, DIGEST_RANGE, + INV_ALPHA, RATE_RANGE, STATE_WIDTH, ZERO, }; use core::convert::TryInto; use rand_utils::rand_value;

@@ -48,6 +49,40 @@ ];

let m_result = Rpo256::merge(&digests); let h_result = Rpo256::hash_elements(&elements); + assert_eq!(m_result, h_result); +} + +#[test] +fn hash_elements_vs_merge_in_domain() { + let elements = [Felt::new(rand_value()); 8]; + + let digests: [RpoDigest; 2] = [ + RpoDigest::new(elements[..4].try_into().unwrap()), + RpoDigest::new(elements[4..].try_into().unwrap()), + ]; + + // pick a random domain value. + let domain = Felt::new(rand_value()); + + // convert the elements into a list of base field elements + let elements = Felt::as_base_elements(&elements); + + // initialize state to all zeros. + let mut state = [ZERO; STATE_WIDTH]; + + // set the second capacity element to the domain. + state[CAPACITY_RANGE.start + 1] = domain; + + // absorb elements into the state. + state[RATE_RANGE.start..RATE_RANGE.end].copy_from_slice(elements); + + // apply permutation to the state. + Rpo256::apply_permutation(&mut state); + + // return the first 4 elements of the state as hash result + let h_result = RpoDigest::new(state[DIGEST_RANGE].try_into().unwrap()); + + let m_result = Rpo256::merge_in_domain(&digests, domain); assert_eq!(m_result, h_result); }