A good hash function's outputs don't seem to follow any obvious pattern;
distinct inputs produce unrelated-looking outputs.
One might be tempted to describe these outputs as pseudorandom.
This chapter discusses why a conventional hash function cannot have pseudorandom outputs,
but also why it can be useful to “pretend” otherwise.
12.1.Defining the random oracle model
Pseudorandom outputs for a hash function?
Suppose H is an unsalted hash function with n output bits (the presence of salt doesn't change the conclusions in this section).
How could we formalize the idea that H has pseudorandom outputs?
Perhaps we should use the same approach that we used for pseudorandom functions, and say that the following two libraries must be indistinguishable:
query(X):
return H(X)
≊
query(X):
if L[X] undefined:
L[X]↞{0,1}n
return L[X]
Unfortunately, these libraries can never be indistinguishable; no hash function can have pseudorandom outputs.
Unlike a PRF, a conventional hash function has no secret inputs.
As such, an adversary does not need the library's help to evaluate H.
Consider the following trivial attack:
A
R:=query(0n)
return R==H(0n)
This calling program simply compares the library's return value to the output of H that it can compute on its own.
The two values always match in one library and match only with probability 1/2n in the other, so the attack succeeds.
Hash functions aren't pseudorandom
A deterministic function without any secret inputs can never produce pseudorandom output.
And yet, we pretend:
Despite this unequivocal limitation of hash functions, cryptographers frequently prove things about hash functions with pseudorandom outputs.
The Random Oracle Model
When we prove security in the random oracle model, it means:
We are analyzing a construction that calls a hash function H.
For the purposes of security, we imagine that H is a uniformly chosen function, implemented as a lazy random dictionary.
Such a hash function is called a random oracle.
H is available not only to the construction but also directly to the adversary (through the interface of the library).
An example: PRFs in the random oracle model:
Let's gain some intuition about random oracles by considering the problem of constructing a PRF in the random oracle model.
A PRF is meant to be indistinguishable from a lazy random dictionary.
If a random oracle is a lazy random dictionary, then what is the point of constructing PRFs in the random oracle model?
A random oracle is unkeyed; it is meant to model a public random function that anyone can evaluate.
A PRF is a keyed primitive; it is (indistinguishable from) a random function that only someone who knows the key can evaluate.
Access to a PRF is mediated through its secret key.
If a PRF construction wants to take advantage of a random oracle, it must access the random oracle in a way that makes nontrivial use of a key.
Definition 12.1.1 (Security in the random oracle model)
A function F is a secure PRF in the random oracle model if the following two libraries are indistinguishable:
Lprf-real+roF
K↞{0,1}λ
prf.query(X):
// F itself might also call H
return F(K,X)
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
≊
Lprf-rand+roF
prf.query(X):
if L[X] undefined:
L[X]↞{0,1}m
return L[X]
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
Both subroutines in Lprf-rand+ro give access to lazy random dictionaries, but completely independent ones!
Thus, a secure PRF in the random oracle model uses its key to instantiate a random function that is private and appears completely unrelated to the public random oracle.
Both libraries include H in their interface, because H is meant to be a public object that anyone can access.
Thus, we formalize the random oracle model by taking the usual security definition and adding a lazy random dictionary H to both libraries.
As another example, security of encryption in the random oracle model is defined as follows:
Definition 12.1.2 (Security in the random oracle model)
An encryption scheme Σ has CPA security in the random oracle model
if the following two libraries are indistinguishable:
Lcpa-real+roΣ
K↞Σ.K
cpa.enc(M):
// Σ.Enc might also call H
C:=Σ.Enc(K,M)
return C
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
≊
Lcpa-rand+roΣ
cpa.enc(M):
C↞Σ.C(∣M∣)
return C
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
Philosophy:
The statistician George Box once said,
All models are wrong, but some are useful.
His quote applies well to the random oracle model:
The random oracle model is a model, but all security proofs are with respect to some simplified model of real-world attack scenarios.
A security proof can refer to libraries that model a realistic attack scenario or an absurd one.
The random oracle model is demonstrably “wrong” as a model of reality.
No real-world hash function can behave entirely like a random oracle, for the reasons discussed above.
A security proof that models H as a random oracle does not necessarily guarantee security in the standard model, when H is merely a plain CRHF.
Despite that, the random oracle model has proven useful.
We know of many constructions in the random oracle model which are simpler/more efficient than our best constructions in the standard model.
And many real-world constructions, whose security we do not know how to establish in the standard model, are “explained” by a security proof in the random oracle model.
If random oracles are impossible, what's the point of proving security in the random oracle model?
Adversaries in the random oracle model cannot “look inside” the random oracle like they can a standard-model hash function.
Adversaries do not have access to source code that implements the random oracle itself; they are allowed only black-box access to its functionality (this is why we call it an “oracle”).
Thus, a security proof that models a hash function as a random oracle tells us what security we can expect against attacks that do not depend on specific properties of the hash function.
Is there some kind of advantage to using random oracles?
Random oracles are powerful objects, and they often lead to constructions that are simpler or more efficient than comparable ones in the standard model.
From a technical point of view, hybrid libraries in random-oracle-model security proof can observe how the adversary calls the random oracle, and even sample the oracle's outputs in different ways.
For example, perhaps in a proof it is advantageous to replace a particular value H(A∗) with a ciphertext, for which the library knows the decryption key.
Neither of these proof techniques are possible when H is a standard-model hash function.
The library can neither observe the adversary's calls to the hash function, which happen “inside the adversary's head,” nor strategically choose the hash function's outputs.
I heard that the random oracle model is controversial. Is that true?
Security proofs in the random oracle model are valid proofs, that prove what they purport to prove.
The controversy is how to interpret these proofs in the real world, where random oracles don't exist.
If I want to implement a construction that has a security proof in the random oracle model, I need to replace the random oracle with some concrete hash function, like SHA-3.
Is the result still secure?
This is precisely the leap of faith demanded by the random oracle model.
And it is indeed a leap of faith because it is not always safe to replace a random oracle with a good standard-model hash function.
There are (highly contrived and unnatural) constructions which can be proven secure in the random oracle model, but which simply cannot be secure when the random oracle is replaced with any standard-model hash function.
See exercise 12.6 for one such example, and see the chapter notes for more references about this controversy.
12.2.Using random oracles
In this section we introduce some techniques and concepts used for security proofs in the random oracle model.
12.2.1.PRFs from random oracles
In section 10.4 we showed that F(K,X)=H(K∥X) is not a secure variable-input-length PRF, if H is an unsalted Merkle-Damgård hash.
On the other hand, it is secure if H is a random oracle.
Claim 12.2.1 (PRF in the random oracle model)
F(K,X)=H(K∥X) is a secure variable-input-length PRF in the random oracle model.
In other words, the following two libraries are indistinguishable:
Lprf-real+ro
K↞{0,1}λ
prf.query(X):
// F(K,X)=H(K∥X)
return H(K∥X)
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
≊
Lprf-rand+ro
prf.query(X):
if L[X] undefined:
L[X]↞{0,1}n
return L[X]
H(A):
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
Proof:
The construction F(K,X) calls the random oracle, and the adversary can also call the random oracle directly.
But F calls the random oracle exclusively on inputs that begin with K.
Thus, outputs from prf.query and from H are completely unrelated, unless the adversary manages to call prf.query on input X, and also call H directly on input K∥X.
Since K is chosen uniformly, it is unlikely that the adversary could successfully call H on an input beginning with K.
prf.query calls H, and we can inline the logic of H into prf.query.
H is implemented by a lazy random dictionary H. We can partition H into two separate dictionaries, based on whether the input starts with the prefix K. Values of the form H[K∥X] are now stored in L[X]. Calls to H made within prf.queryalways include the K prefix, but the adversary's direct calls to H may or may not.
Modify H to act as if its inputs never have a prefix K. The library's behavior will change only in the bad event that the calling program calls H on an input that begins with K. We must later show that this bad event has negligible probability.
The value K is used only to decide whether to trigger the bad event, so we can move the choice of K and all the bad event logic to the end of time without affecting its probability.
Lprf-real+ro
K↞{0,1}λ
prf.query(X):
// F(K,X)=H(K∥X)
if
H[K∥X] undefined:
L[X] undefined:
H[K∥X]↞{0,1}n
L[X]↞{0,1}n
return
H(K∥X)
H[K∥X]
L[X]
H(A):
if A begins with K:
bad:=true
write K∥X:=A
if L[X] undefined:
L[X]↞{0,1}n
return L[X]
else:
A:=A∪{A}
if H[A] undefined:
H[A]↞{0,1}n
return H[A]
end of time:
K↞{0,1}λ
for each A∈A:
if A begins with K:bad:=true
The final hybrid is just Lprf-rand+ro with some extra bad-event logic at the end of time.
It suffices to prove that the bad event has only negligible probability.
If the calling program makes q calls to H, then there are at most q items in the set A at the time K is chosen, so the probability of the bad event is at most q/2λ.
Since q is a polynomial in the security parameter, the probability is negligible.
This proof illustrates a common strategy for proofs in the random oracle model.
The random oracle is called in two ways:
The adversary can make direct calls to the random oracle through the library's H interface.
The construction also makes internal calls to the random oracle.
The adversary may have some control over these calls, through its choice of inputs to the construction, but usually not full control.
In the previous example, the adversary could choose inputs X to the PRF, which would then call the random oracle on K∥X, for a value K that the adversary did not know.
A standard strategy in a security proof is to show that no internal call is also made as a direct call (except with negligible probability).
Strategy for Random-Oracle-Model Proofs
Focus on showing that no internal call to the random oracle can also be made as a direct call, except with negligible probability.
Modify the library to behave as if such an overlap is impossible, and trigger a bad event in the case that an overlap happens.
Often this involves rewriting some of the library's internal logic to differentiate between these two kinds of random oracle calls.
12.2.2.CRHFs from random oracles
Random oracles are meant to model hash functions,
so it is natural to ask whether a random oracle is collision-resistant.
Section 10.1 went to great lengths to motivate the need for salt in a collision-resistant hash function.
The purpose of salt was to introduce variability that is chosen after the adversary is fixed, that the adversary cannot predict.
But the random oracle is already chosen after the adversary is fixed, so salt is not needed in the random oracle model.
Claim 12.2.2 (Random oracles are collision-resistant)
A random oracle is a (unsalted) CRHF.
In other words,
the following two libraries are indistinguishable:
A random oracle samples its outputs with replacement, but this behavior is indistinguishable from a function that samples without replacement. The simple three-hop maneuver involving lemma 4.5.7 has been omitted:
After making this change, distinct inputs are guaranteed to have distinct random-oracle outputs. Thus, H(X)==H(X′)if and only ifX==X′.
Finally, H can be returned to its original behavior. The result is Lcrhf-idea+ro, completing the proof.
Lcrhf-real+ro
Lcrhf-ideal+ro
crhf.compare(X,X′):
return
H(X)==H(X′)
X==X′
H(A):
if H[A] undefined:
H[A]↞{0,1}λ
∖Y
Y:=Y∪{H[A]}
return H[A]
12.3.☆ The ideal permutation model
The random oracle model thinks of a deterministic object (a public hash function) as an inherently randomized one (a random oracle).
We therefore say that a random oracle is an idealized object, where in this context “ideal” means “too good to be true.”
No real-world hash function can literally be a random oracle.
We can use similar idealized objects to model other cryptographic primitives as well.
In this section we introduce the ideal permutation model, and in the next section the ideal cipher model.
Definition 12.3.1 (Ideal permutation model)
In the ideal permutation model, adversaries and constructions have access to a uniformly chosen permutation and its inverse.
Such a permutation can be implemented in a lazy manner, similar to the security definition for strong PRPs (section 7.5):
Π+(A):
if P+[A] undefined:
B↞{0,1}n∖B
P+[A]:=B;A:=A∪{A}
P−[B]:=A;B:=B∪{B}
return P+[A]
Π−(B):
if P−[B] undefined:
A↞{0,1}n∖A
P+[A]:=B;A:=A∪{A}
P−[B]:=A;B:=B∪{B}
return P−[B]
You can understand how Π± implements a lazy random permutation through the following invariants:
If P+[A] is defined then P−[P+[A]]=A.
If P−[B] is defined then P+[P−[B]]=B.
A stores the set of values X on which P+[A] is defined.
B stores the set of values Y on which P−[B] is defined.
An ideal permutation is a public object; anyone can evaluate it in both directions.
Below is a construction that uses an ideal permutation to build a keyed PRP, which can be evaluated only by someone who knows the key.
Both random oracles and PRFs involve lazy random dictionaries in their definition.
But a bare random oracle is not a PRF, because a random oracle is public while a PRF should be computable only with its secret key.
Similarly, both ideal permutations and PRPs are defined in terms of lazy random permutations, but a bare ideal permutation is not a PRP.
Just as there are simple ways to build a PRF from a random oracle, there are also simple ways to build a PRP from an ideal permutation:
Construction 12.3.2 (Even-Mansour)
Let Π± be an ideal permutation over {0,1}λ.
Then the Even-Mansour cipher is the keyed permutation F± defined below:
F(K,X)F−1(K,Y)=Π+(K⊕X)⊕K=Π−(K⊕Y)⊕K
Claim 12.3.3 (Security of Even-Mansour)
The Even-Mansour construction is a secure PRP in the ideal permutation model.
Proof:
It is not hard to see that F(K,⋅) and F−1(K,⋅) are inverses, for every K.
So F± is indeed a keyed permutation.
We will show that F is a secure PRF in the ideal permutation model.
This will imply, from lemma 7.2.1, that F is a secure PRP, since its blocklength is λ bits.
The construction F makes internal calls to Π±, and the adversary also makes direct calls to Π±.
Just like in the random oracle model, our goal is to show that these internal and direct calls overlap with only negligible probability.
It will be convenient to first introduce some notation to organize the various inputs and outputs:
X
input in adversary's call to F
U
input in F's internal call to Π+
V
output of F's internal call to Π+
Y
output of adversary's call to F
A
input in adversary's direct call to Π+ (or output of Π−)
B
output of adversary's direct call to Π+ (or input of Π−)
Our strategy in the proof will be to trigger a bad event if a U-value matches an A-value (which also means that the corresponding V-value matches the corresponding B-value).
Whenever this bad event doesn't happen, it means that the construction and the adversary's direct access to Π± should give unrelated responses.
We can introduce a cache in prf.query to avoid recomputing the same thing twice. We can also change Π± to sample their outputs with replacement; the change has negligible effect. Because of this change, the sets A and B are no longer used anywhere, but we retain them for a later hybrid.
We can change prf.query to sample V uniformly instead of calling Π+(U). This changes the library's behavior only if at the end of the execution U∈A, meaning that U was the input to some direct call to Π+ or output of some direct call to Π−. We trigger a bad event in this case, and will later show that its probability is negligible.
L[X] now plays the role of a OTP ciphertext, interpreting V as the uniformly sampled key. Thus, it is distributed uniformly.
We can change Π+ and Π− back to their original implementation, sampling their outputs without replacement.
Every U value has the form U=X⊕K. So instead of keeping track of U-values, we can keep track of just X-values and recompute the U-values later when determining the bad event. That way, K is not needed until the end of time. The result is Lprf-rand+ro, with extra bad-event logic at the end of time.
Lprf-real+ro
K↞{0,1}λ
Lprf-rand+ro
prf.query(X):
// return F(K,A)
if L[X] undefined:
U:=K⊕X
V
:=Π+(U)
↞{0,1}λ
L[X]
:=V⊕K
↞{0,1}λ
U:=U∪{U}
X:=X∪{X}
return
V⊕K
L[X]
Π+(A):
if P+[A] undefined:
B↞{0,1}λ
∖B
∖B
P+[A]:=B;A:=A∪{A}
P−[B]:=A;B:=B∪{B}
return P+[A]
Π−(Y):
if P−[B] undefined:
A↞{0,1}λ
∖A
∖A
P+[A]:=B;A:=A∪{A}
P−[B]:=A;B:=B∪{B}
return P−[B]
end of time:
K↞{0,1}λ
U:={X⊕K∣X∈X}
if U∩A=∅:bad:=true
It remains to show that the bad event has negligible probability.
At the end of time, the sets X and A are fixed, and K is sampled uniformly.
The bad event happens if there is some X∈X and A∈A such that X⊕K=A (equivalently, K=A⊕X).
If the adversary calls the library subroutines q times, then there are at most q choices of X∈X and at most q choices of A∈A, and thus at most q2 choices of K=A⊕X that cause the bad event.
Hence, the bad event has probability at most q2/2λ, which is negligible since q is a polynomial in the security parameter.
Key-alternating ciphers:
The Even-Mansour construction is the second paradigm we've seen for building a PRP;
the previous was the Feistel construction (construction 7.3.3).
To build a PRP with the Feistel construction, you need a good PRF for the round function.
To build a PRP with the Even-Mansour construction, you need a good public, unkeyed permutation.
The Even-Mansour construction is the simplest instance of a key-alternating cipher, in which we alternate between xor'ing the key and applying a fixed, public permutation:
You can consider the Even-Mansour security analysis as justification for the overall key alternation design methodology for PRPs.
Advanced Encryption Standard(AES)
is the world's most widely used PRP/block cipher.
It was standardized in 2001 as a replacement for DES, and is designed as a key-alternating cipher and alternates between xor'ing a key and applying a fixed, public permutation.
Admittedly, it is a bit of a stretch to characterize the Even-Mansour security proof as justification for the security of AES.
Its “permutation” step would be a poor choice for an ideal permutation, since it has too much predictable structure.
But what AES lacks in similarity to an ideal permutation, it makes up for with additional rounds.
12.3.1.Permutation-based cryptography and sponges
Symmetric-key cryptography in practice has traditionally been built on a foundation of PRPs (block ciphers).
Starting with a secure PRP, we have standard constructions (many of them shown and proven secure in the previous chapters) of PRGs, variable-length PRFs, encryption, and more.
The security of all these primitives rests on the security of the underlying PRP, and so the most effort has gone into designing, analyzing, and standardizing good PRPs.
However, a recent trend has been to base cryptographic primitives on unkeyed permutations, usually with large blocklengths (e.g., a recent standard has blocklength 1600 bits).
Starting with such a permutation, there are standard constructions of PRGs, PRFs, hash functions, and other primitives, whose security is proven by modeling the permutation as an ideal one.
Thus, the security of all these primitives relies on the how well this underlying permutation emulates an ideal permutation.
The hope of permutation-based cryptography is that it may be easier to design and acquire confidence in an unkeyed object like a permutation than in a keyed primitive like a PRP.
Many candidate PRPs have been broken or had weaknesses demonstrated based on how they incorporate the key into their computation.
Permutation-based cryptography avoids this possibility.
The candidate permutation is unkeyed, so any constructions that use the permutation must incorporate a key in a provably secure manner.
The Sponge Methodology:
The most common way to construct symmetric-key primitives from a public permutation is with the sponge methodology, whose name is inspired by the metaphor of a sponge absorbing input and squeezing output.
When using an ideal permutation with blocklength n, a sponge function maintains an internal state of n bits.
The state is divided into a top part and bottom part, and we write the state as T∥B.
Usually the bottom is λ bits and the top is longer.
There are two basic operations in the sponge methodology:
In an absorbing step, take the next block of input X (with the same length as T) and update the current state as:
T′∥B′:=Π+((T⊕X)∥B).
In a squeezing step, append the current value of T to the output and update the current state as:
T′∥B′:=Π+(T∥B).
Using these steps, the basic sponge function works as follows:
Starting from an all-zeros state, first absorb the entire input;
then squeeze as much output as needed.
Thus, a sponge function supports inputs of any (block-aligned) length, and produces as much output as requested.
For this reason, sponge functions are also called extensible output functions (XOFs).
A sponge function can be used to build all sorts of cryptographic primitives:
PRG: Absorb the input seed and squeeze as much output as needed.
PRF/MAC: Absorb the key and second PRF input X (concatenated together) and squeeze an output.
CRHF: Absorb the entire input and squeeze one output block.
It is even possible to directly construct CPA/CCA/AE encryption from a sponge function, by alternating between absorbing (to consume plaintext input) and squeezing (to generate ciphertext output).
All of these simple constructions can be proven secure in the ideal permutation model (see exercises 12.11–12.13 for the simplest cases).
SHA-3:
SHA-3 (Secure Hash Algorithm) is the most recent standardized hash function from the US National Institute of Standards & Technology.
It is designed using the sponge methodology, centered around an underlying 1600-bit permutation called Keccak-f.
The standard defines many variants, but the most basic version divides the 1600-bit block into a 1088-bit “top” part and 512-bit “bottom” part.
Thus, hashing requires one call to the permutation for each 1088 bits of input.
12.4.☆ The ideal cipher model
We can model block ciphers as idealized objects as well.
In the security definition for a (strong) PRP, F(K,⋅) and F−1(K,⋅) are indistinguishable from a random permutation and its inverse, when the key is chosen uniformly and kept secret.
In the ideal ciphermodel, F(K,⋅) and F−1(K,⋅) behave like an ideal permutation for every choice of K.
An ideal cipher is like a PRP that is somehow secure, even when the adversary chooses its key!
Definition 12.4.1 (Ideal cipher model)
In the ideal cipher model, constructions and the adversary have access to the following subroutines:
F+(K,A):
if L+[K,A] undefined:
B↞{0,1}λ∖B[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L+[K,A]
F−(K,B):
if L−[K,B] undefined:
A↞{0,1}λ∖A[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L−[K,B]
For each possible value of K, the library implements an independent lazy random permutation at L±[K,⋅].A[K] holds all the values A such that L+[K,A] is defined, and
B[K] holds all the values B such that L−[K,B] is defined.
Collision-resistance from ideal ciphers:
A collision-resistant hash function has no secrets, and this fact makes it hard to construct one from a keyed primitive like a PRF or PRP.
However, there is a way to construct a CRHF from an ideal cipher.
Below is a method for constructing a fixed-input-length, collision-resistant hash function from an ideal cipher.
Such a primitive can be extended to a variable-input-length CRHF using the Merkle-Damgård construction (construction 10.4.3).
In this idealized model, salt is not required for collision resistance.
Construction 12.4.2 (Davies-Meyer)
Let F± be a keyed permutation with blocklength λ.
The Davies-Meyer compression function takes 2λ bits of input and outputs λ bits, and is defined as:
H(A∥B)=F+(A,B)⊕B.
In other words, it treats half of its input as an ideal cipher key, and the other as a block.
Claim 12.4.3 (Security of Davies-Meyer)
The Davies-Meyer function is collision-resistant, when modeling F± as an ideal cipher.
In other words,
Lcrhf-real+ic
crhf.compare(X∥Y,X′∥Y′):
Z:=F+(X,Y)⊕Y// H(X∥Y)
Z′:=F+(X′,Y′)⊕Y′// H(X′∥Y′)
return Z==Z′
F+(K,A):
if L+[K,A] undefined:
B↞{0,1}λ∖B[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L+[K,A]
F−(K,B):
if L−[K,B] undefined:
A↞{0,1}λ∖A[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L−[K,B]
≊
Lcrhf-ideal+ic
crhf.compare(X∥Y,X′∥Y′):
return X∥Y==X′∥Y′
F+(K,A):
if L+[K,A] undefined:
B↞{0,1}λ∖B[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L+[K,A]
F−(K,B):
if L−[K,B] undefined:
A↞{0,1}λ∖A[K]
L+[K,A]:=B;A[K]:=A[K]∪{A}
L−[K,B]:=A;B[K]:=B[K]∪{B}
return L−[K,B]
Proof:
The main idea behind the proof is that the adversary can determine new values of the form H(X∥Y) only by calling the ideal cipher.
In fact, there is a one-to-one correspondence between ideal-cipher expressions of the form F+(K,A)=B and hash expressions of the form H(K∥A)=B⊕A.
And no matter how the adversary calls the ideal cipher, the effect on H's output is uniform:
If the adversary calls F+(K,A), the library samples B, and thus H(K∥A)=B⊕A is uniform.
If the adversary calls F−(K,B), the library samples A, so again H(K∥A)=B⊕A is uniform.
Either way, the adversary can learn only uniform outputs of H.
The starting point of the hybrid proof is Lcrhf-real+ic.
Instead of sampling outputs of F± without replacement, we can sample them with replacement. The change is indistinguishable, using the now-standard birthday reasoning. As a result of the change, the sets A[K] and B[K] are no longer needed and can be removed.
Whenever F± is called, we can compute the associated H-output and store it. Then crhf.compare can refer directly to these stored values.
Instead of sampling ideal cipher output and then computing H[K∥A], we can sample H[K∥A] first and solve for the ideal cipher output. Care is needed in F− because we need to sample H[K∥A] before knowing what A is.
Now all values assigned to H[⋅] are sampled uniformly. We can instead sample them without replacement, with negligible effect on the calling program.
Now all values assigned to H[⋅] are distinct, and therefore H[X∥Y]==H[X′∥Y′] if and only if X∥Y=X′∥Y′.
Lcrhf-real+ic
crhf.compare(X∥Y,X′∥Y′):
Z:=F+(X,Y)⊕Y
Z′:=F+(X′,Y′)⊕Y′
// ensure H[X∥Y] & H[X′∥Y′] are set:
call F+(X,Y)
call F+(X′,Y′)
return
Z==Z′
H[X∥Y]==H[X′∥Y′]
X∥Y==X′∥Y′
F+(K,A):
if L+[K,A] undefined:
H[K∥A]↞{0,1}λ
∖H
H:=H∪{H[K∥A]}
B
↞{0,1}λ
∖B[K]
:=A⊕H[K∥A]
L+[K,A]:=B
;A[K]:=A[K]∪{A}
L−[K,B]:=A
;B[K]:=B[K]∪{B}
H[K∥A]:=A⊕B
return L+[K,A]
F−(K,B):
if L−[K,B] undefined:
H↞{0,1}λ
∖H
H:=H∪{H}
A
↞{0,1}λ
∖A[K]
:=B⊕H
L+[K,A]:=B
;A[K]:=A[K]∪{A}
L−[K,B]:=A
;B[K]:=B[K]∪{B}
H[K∥A]:=
A⊕B
H
return L−[K,B]
The goal of this sequence of hybrids is to eventually reach Lcrhf-ideal+ic.
We can reach that library by “undoing” all the prior changes to F±, in reverse order, while keeping the last line of crhf.compare in its updated form.
These remaining steps in the hybrid sequence are entirely repetitive, so we omit them here.
Exercises
Let H be a hash function with λ-bit inputs, and define F(K,X)=H(K⊕X).
Prove that F is a secure PRF in the random oracle model.
Prove that a random oracle with 2λ output bits is a PRG.
In other words, prove that G(S)=H(S) is a secure PRG in the random oracle model.
Prove that the function G(S)=H(S)∥H(S) is a secure PRG in the random oracle model, when H is a random oracle with λ input/output bits.
“S” is the bitwise complement of the string S.
Prove that the function G(S)=H(S)∥H(S+1) is a secure PRG in the random oracle model, when H is a random oracle with λ input/output bits.
“S+1” means addition mod 2λ.
Let H be a random oracle with λ input bits and 2λ output bits.
Prove that the following function is a secure PRG.
G(S):
X∥Y:=H(S)
return (X⊕S)∥Y
h
In this problem you will construct an encryption scheme that is secure in the random oracle model but is insecure if the random oracle is replaced by any public function.
Prove that the following two libraries are indistinguishable.
In other words, it is hard to write a program that agrees with the random oracle, on a uniformly sampled input, when the random oracle has input and output length λ:
Lro-predict-real
challenge(P):
R↞{0,1}λ
S:=null
interpreting P as a Python program,
run P on input R for ∣P∣ clock cycles;
if P successfully terminates in that time:
assign its output to S
return S==H(R)
H(A):
if H[A] undefined:
H[A]↞{0,1}λ
return H[A]
≊
Lro-predict-ideal
challenge(P):
return false
H(A):
if H[A] undefined:
H[A]↞{0,1}λ
return H[A]
There is nothing particularly special about Python programs here;
what's important is that the adversary provides a program that will terminate in a predictable (and polynomial) amount of time.
Imagine the program is self-contained, and run in a virtual machine, so it has no mechanism by which to call the library's H subroutine.
Let Σ be a CPA-secure encryption scheme that has λ-bit keys and supports arbitrary-length plaintexts.
Prove that the following scheme is a CPA-secure encryption scheme if H is modeled as a random oracle:
Enc∗(K,M):
C:=Σ.Enc(K,M)
R↞{0,1}λ
interpreting M as a Python program,
run M on input R for ∣M∣ clock cycles
if M successfully terminates in that time
... and its output equals H(R):
C′:=K
else:
C′↞{0,1}λ
return C∥C′
Dec∗(K,C∥C′):
// ignore final λ bits
return Σ.Dec(K,C)
Show that if H is implemented by any efficiently computable function, then the scheme is not CPA-secure.
It's important that R is chosen uniformly, after P is chosen.
Understand what would go wrong if R was a fixed, public value, say, R=0λ.
Prove that the following function is collision-resistant in the random oracle model:
F(X1∥X2)=H(0∥X1)⊕H(1∥X2).
Assume that each Xi has exactly n bits.
What would be your recommendation for a suitable output length of H?
The Even-Mansour cipher incorporates the key before and after the ideal permutation.
Both of these steps are necessary.
Show that F(K,X)=Π+(X)⊕K is not a secure PRP if Π± is an ideal permutation.
Show that F(K,X)=Π+(X⊕K) is not a secure PRP if Π± is an ideal permutation.
Prove that the Even-Mansour cipher is a secure strong PRP (definition 7.5.1) in the ideal permutation model.
Suppose we construct a hash function H(X) using the sponge methodology in the ideal permutation model:
H absorbs each block of X and squeezes one block of output.
Does H have the same length-extension property of Merkle-Damgård hash functions?
Explain your answer.
Let Π± be an ideal permutation with blocklength 2λ.
Prove that the following sponge function G is a secure PRG:
G(S):
T1∥B1:=Π+(S∥0λ)
T2∥B2:=Π+(T1∥B1)
return T1∥T2
Each of the variables T1,T2,B1,B2,S is λ bits long.
Let Π± be an ideal permutation with blocklength 2λ, and define the following sponge function:
F(K,X):
T1∥B1:=Π+(K∥0λ)
T2∥B2:=Π+((T1⊕X)∥B1)
return T2
Each of the variables T1,T2,B1,B2,K,X is λ bits long.
Prove that F is a secure PRF.
Show that if F is modified to return all of T2∥B2, then the result is not a secure PRF.
h⋆
Let Π± be an ideal permutation with blocklength 2λ.
Prove that the following sponge function is a secure variable-input-length PRF, for block-aligned inputs:
F(K,X1∥⋯∥Xℓ):
T∥B:=Π+(K∥0λ)
for i=1 to ℓ:
T∥B:=Π+((T⊕Xi)∥B)
return T
Each of K,T,B,X1,…,Xℓ is λ bits long.
Keep track of the B-values seen during computations of F.
Trigger a bad event if the adversary ever encounters one of these B-values in a direct call to Π±.
Let Π± be an ideal permutation with blocklength λ.
Prove that H(X)=Π+(X)⊕X is collision-resistant.
Let H be the Davies-Meyer compression function H(X∥Y)=F+(X,Y)⊕Y.
Show how to efficiently compute an input X∥Y such that H(X∥Y)=Y.
Why doesn't this contradict collision-resistance?
Prove that the function H(X∥Y)=F+(X,Y)⊕X⊕Y is collision-resistant in the ideal cipher model.
Chapter Notes
Fiat and Shamir [101] were the first to explicitly model a hash function as a random object, accessible to both the users and the adversary.
Later, Bellare and Rogaway [26] were the first to advocate for the random oracle model, and show that a variety of heuristic techniques used in practice can be justified by provable security in the random oracle model.
There is controversy within the cryptographic community about the correct interpretation of a security proof in the random oracle model.
Goldreich [111] vehemently opposes the random oracle model on the grounds that it is has been pursued as a fetish.
The Random Oracle model [was] originally suggested as a good sanity check but unfortunately misunderstood as a yardstick for security … in our opinion, the Random Oracle Model has caused more harm than good, because many people confuse it for the “real thing” (while it is merely an extremely idealized sanity check) … Given the sour state of affairs, it seems good to us to abolish the Random Oracle Model. At the very minimum, one should issue a fierce warning that security in the Random Oracle Model does not provide any indication towards security in the standard model.
Koblitz and Menezes [135] are equally vehement in their support: Uninstantiability results like those in exercise 12.6, which are meant to undermine confidence in the random oracle model, are “no cause of concern for practitioners.”
Exercise 12.6 is inspired by the impossibility results of Canetti, Goldreich, and Halevi [58] and of Goldwasser and Kalai [114].
These papers each describe a construction that is secure in the random oracle model but insecure when the random oracle is replaced by any concrete function.
In a related line of work, Nielsen [172] and Bellare, Boldyreva, and Palacio [13] describe cryptographic primitives that can be achieved in the random oracle but that are impossible (by any construction) in the standard model.
The Even-Mansour cipher is named after its creators [98].
They proposed using independent keys before and after the ideal permutation.
Dunkelmann, Keller, and Shamir [89] analyzed the variant of Even-Mansour that we presented in construction 12.3.2, which uses identical keys.
The sponge methodology was first proposed by Bertoni, Daemen, Peeters, and Van Aasche in their design of the Keccak hash function, later standardized as SHA-3 [38,39].
Another suite of sponge-based primitives, called Ascon [86], has also been standardized for lightweight devices.
The ideal cipher model has roots as far back as the seminal work of Claude Shannon [201], who discusses what modern readers may recognize as an idealized block cipher.
The Davies-Meyer construction is attributed to Davies by Winternitz in [218].
Matyas, Meyer, and Oseas [155] also proposed essentially the same construction, the only difference being swapping the roles of the two input blocks.
There are several other methods to build a compression function from an ideal cipher, with one notable one (exercise 12.16) proposed by Miyaguchi, Ohta, and Iwata [165] and independently by Preneel [184], but commonly referred to as “Miyaguchi-Preneel.”
Preneel, Govaerts, and Vandewalle [185], and later Black, Rogaway, and Shrimpton [45], characterized the security of every possible way to construct a compression function from one call to an ideal cipher.