5

Referring to the answer in this question I am looking for (hopefully simple) examples of protocols that are secure in the random oracle model but trivially insecure whenever the random oracle is instantiated with any hash function.

If possible, give a proof in the "game"-scheme. (If possible, give an easy-to-understand explanation to the Canetti–Goldreich–Halevi scheme)

With this, I would like to specifically understand where that difference between a nearly perfect and perfect random oracle lies.

1 Answers1

10

Here is an example that I use in The Joy of Cryptography textbook. Consider the following symmetric-key encryption scheme, where $H$ is a function with input and output length equal to the security parameter.

To encrypt plaintext $M$ under key $K$:

  1. sample random block $R$
  2. interpret $M$ as a Python program, and run it on input $R$ for at most $|M|$ steps
  3. if the output of the program equals $H(R)$ then output $K \| M$
  4. otherwise, encrypt $M$ using standard CBC mode encryption with key $K$

This construction is CPA-secure when $H$ is a random oracle, and here is a sketch of the proof. Consider the moment that an adversary asks for an encryption of $M$ in the CPA security game. The game chooses $R$ at random, so with all but negligible probability, the adversary has not yet queried the random oracle at $R$. Thus the output $H(R)$ is a fresh random value, and independent of the output of Python program $M(R)$, so the two values equal with only negligible probability. In summary, the scheme enters line 4 and behaves exactly like CBC encryption (which is CPA-secure) with all but negligible probability.

On the other hand, if $H$ is any standard-model function, then the scheme is insecure. The adversary just asks for an encryption of a Python implementation of $H$, and the resulting ciphertext will contain the key $K$.

(Technically speaking, take a Python implementation of $H$ and pad its source code with comments until $M$ is long enough so that the $H$-implementation halts in $|M|$ steps. The reason the scheme "runs $M$ for at most $|M|$ steps" is just to gracefully deal with the fact that not all Python programs halt. Alternatively, replace "Python program" with "boolean circuit" and you don't have to worry about non-halting behavior because a boolean circuit always "halts.")

Mikero
  • 14,908
  • 2
  • 35
  • 58