Skip to main content
8 of 19
greatly simplified, and now hopefully working
fgrieu
  • 145.6k
  • 12
  • 319
  • 611

[greatly simplified, and now hopefully working]

Improving on the line of thought in that other answer, we can craft something that exactly matches the requirement. We'll use $7$ arbitrary distinct non-zero $256$-bit strings $k_0\dots k_6$, and a $256$-bit PRF $P(k,m)$ such as $\mathtt{HMAC}_\mathtt{SHA­256}(k,m)$.

For $j\in\{1,2\}$, define $\hat H_j(s,x)$ as the $512$-bit string $(Z||P(k_j,s))\oplus x$, where $Z$ is the all-zero 256-bit string, $||$ stands for concatenation, $\oplus$ stands for bitwise-XOR, and $x$ is restricted to $512$-bit strings. We have the desired property $\hat H_1(s_1,\hat H_2(s_2,x))=\hat H_2(s_2,\hat H_1(s_1,x))$. However these $\hat H_1$, $\hat H_2$ make rather poor hash functions. In particular, the output is linearly malleable using the second input; and we'd want to waive the restriction on $x$.

We need added camouflage. Define a $512$-bit permutation $E()$ as the 4-round Feistel cipher with round functions $P(k_3,r)\dots P(k_6,r)$, and $D()$ the reverse permutation. These are PRP.

Now for $j\in\{1,2\}$, define $H_j(s,x)$ as $E(\hat H_j(s,D(x)))$ when $x$ is a 512-bit string, and $E(\hat H_j(s,Z||P(k_0,x)))$ otherwise. The desired property $H_1(s_1,H_2(s_2,x))=H_2(s_2,H_1(s_1,x))$ is met. Knowledge of some of the $k_i$ constants is hopefully necessary to distinguish $H_1$ and $H_2$ from a random oracle, except for consequences of that property.

The motivation is that when one invents a value $x$ that did not came out of either function and feeds it to the second input, either $x\mapsto D(x)$ or $x\mapsto P(k_0,x)$ will mess it uncontrollably. I do not claim a security proof.

fgrieu
  • 145.6k
  • 12
  • 319
  • 611