5
Pseudorandomness

Pseudorandom Generators

One-time pad is not a particularly useful encryption scheme. Among other problems, the key must be as long as the plaintext, which presents a kind of chicken-and-egg situation: I can't privately send you nn bits of information unless we already privately share nn bits of information. This chapter is about overcoming this limitation of OTP:

How can we use a short key to securely encrypt a (single) long plaintext?

5.1. Defining pseudorandomness

OTP encrypts its plaintexts using the xor operation, which requires its two arguments to have the same length. So if we want an encryption method similar to OTP, but with a key that is shorter than the plaintext, we need some way to expand the key into a longer string:

What would need to be true about this mysterious “key expansion” method?

  • It would need to be deterministic, so that both the sender and receiver can expand their key in the same way.

  • Its output distribution would need to be uniform, since that is a crucial property for the security of OTP.

Unfortunately, it's not possible to achieve both of these properties simultaneously. Suppose the expansion method is a deterministic function G:{0,1}n{0,1}n+G: \bits^n \to \bits^{n+\ell}, so its outputs are \ell bits longer than its inputs. Then there are 2n+2^{n+\ell} strings of length n+n+\ell, but only (at most) 2n2^n possible outputs of GG. So the outputs of GG can never induce a uniform distribution.

But let's not give up hope just because our goal is impossible!

Indistinguishable is Close Enough

When the thing we really want is impractical or even impossible, we can usually settle for something that is indistinguishable from the thing we really want.

We want a deterministic function, with outputs that are longer than its inputs, and whose outputs can induce a uniform distribution. This is impossible, but perhaps it is possible to have a function with an output distribution that is merely indistinguishable from uniform.

Definition 5.1.1 (Pseudorandom)

In cryptography, something is pseudorandom if it is indistinguishable from the uniform distribution. (The Oxford English Dictionary defines the prefix pseudo- as “apparently but not really.”)

A pseudorandom generator is the missing piece that enables us to encrypt long plaintexts with a short key.

Definition 5.1.2 (Psuedorandom generator)

Let G:{0,1}λ{0,1}λ+G : \bits^\secpar \to \bits^{\secpar+\ell} be a deterministic function with >0\ell > 0, meaning that its outputs are \ell bits longer than its inputs. GG is a secure pseudorandom generator (PRG) if the following two libraries are indistinguishable:

Lprg-real\lib{prg-real}
prg.sample()\prgsamp(\,):
S{0,1}λ\seed \gets \bits^\secpar
return G(S)G(\seed)
\indist
Lprg-rand\lib{prg-rand}
prg.sample()\prgsamp(\,):
Y{0,1}λ+Y \gets \bits^{\secpar+\ell}
return YY

The value \ell is called the PRG's stretch. The input S\seed to the PRG is called the seed.

Let's first understand the attack scenario that this definition formalizes.

  • A victim (or the Lprg-real\lib{prg-real} library) samples a seed uniformly from {0,1}λ\bits^\secpar and uses it as input to GG.

  • Since the only input to the PRG is its seed, which is chosen and managed by the victim, there are no inputs left for the adversary to control. Thus, the subroutines in the Lprg-*\lib{prg-*} libraries take no arguments.

  • The adversary sees the output of GG, which is supposed to be indistinguishable from the uniform distribution.

  • The victim uses a seed only once. If the adversary calls prg.sample\prgsamp more than once, a fresh seed is chosen each time.

English translation of the PRG Security Definition

A PRG's outputs are indistinguishable from the uniform distribution, to an adversary who sees only the output, when the seed is chosen uniformly and used for only one evaluation of the PRG.

The Lprg-real\lib{prg-real} library generates outputs according to the distribution illustrated below on the left, the Lprg-rand\lib{prg-rand} library according to the distribution illustrated on the right.

This picture presents a global view of a PRG, which can lead to some confusion. Suppose the PRG has input length λ=128\secpar=128 and stretch =128\ell = 128, and therefore output length 256. Then only 2128/2256=1/21282^{128}/2^{256} = 1/2^{128} fraction of strings are possible outputs of the PRG—these correspond to the dots in the left picture. You might wonder how the two distributions could possibly be indistinguishable if one includes only a 1/21281/2^{128} fraction of the possible outcomes.

But an adversary doesn't have a global view of this PRG picture—it has only a tiny glimpse. In our concrete example, an ambitious adversary might observe 2642^{64} PRG outputs, which is still only a 1/2641/2^{64} fraction of the pseudorandom distribution! More generally, an adversary can observe only polynomially many samples from these exponentially large distributions: a negligible fraction of both the pseudorandom and uniform distributions. A more accurate depiction of the adversary's perspective looks like this:

The adversary observes only a small number of samples from the two distributions, illustrated here as the darkly shaded dots.

Things to remember about the PRG security definition: First, the libraries in definition 5.1.2 give the PRG output directly to the adversary. Remember, when an attack scenario allows the adversary to see a value, we are saying that we want security to hold no matter how that value is used elsewhere. So the PRG security definition says (when the seed value is managed appropriately), “PRG output is a safe substitute for truly uniform randomness, in any situation.”

Second, a PRG is only as good as the quality of its seed. Security rests on the fact that the seed is sampled uniformly from {0,1}λ\bits^\secpar; how to do this effectively on a real computer is an important question, out of scope from the perspective of the PRG security definition. Security also rests on the seed remaining secret and not being reused.

5.2. Do PRGs exist?

I can't give any example of a PRG whose security can be proven in the same way that we can prove the security of OTP. If such a PRG existed, it would resolve the most famous unsolved question in computer science (see exercise 5.3). The P vs NP question is about what problems a polynomial-time algorithm can/can't solve, and the PRG security definition is about what a polynomial-time adversary can/can't do. So we cannot prove security from “first principles”; we can only conjecture about the security of any particular PRG.

Although we deal in conjectures, these conjectures don't have to be frivolous; they can be informed by strong circumstantial evidence. For example, we can sometimes prove that a PRG resists certain special types of attacks. We can expose a PRG to intense public scrutiny; if no attacks are found despite serious attempts, we gain more confidence about its security.

PRGs are only the first of many primitives and security goals that we'll study. Each of these primitives suffers from the same P vs NP barrier: We can't prove from “first principles” that any particular algorithm achieves any of these security goals. For each primitive, we can identify promising candidate algorithms and conjecture that they are secure.

But cryptography is not a large collection of unconnected, ad hoc conjectures about security. One of the pillars of provable security is that we can use mathematical proofs to reduce the number of conjectures.

Provable security means conditional statements about security

In most cases, we cannot prove security properties from first principles. What we can do is prove conditional statements like the following:

If A is secure, then B, which uses A as a component, is also secure.

In this way, B doesn't require a completely new conjecture about security. Its security reduces to a previously established conjecture about A's security.

Using provably secure constructions of this kind, we can minimize the number of assumptions. Ideally, we would conjecture about just one kind of primitive, then use it to build all the others we care about. We study many different primitives, so there are many choices for which one to choose as the “axiom” of provable security.

Valuing mathematical elegance and order of presentation: PRGs are the simplest primitive with security that can't be proven from first principles. We can use PRGs to provably build everything else in the symmetric-key part of this book. For example, we show how to use a PRG to build a PRF (don't worry what that means right now) and prove that the resulting PRF is secure if the underlying PRG is secure. Then we show how to use a PRF to build symmetric-key encryption and prove that the encryption is secure if the underlying PRF is secure, and so on.

Thus, the security of PRFs and symmetric-key encryption (and other primitives) ultimately reduces to the security of the simpler underlying PRG. In other words, if secure PRGs exist, then surely secure PRFs and secure symmetric-key encryption (and other primitives) exist as well. The conjecture that secure PRFs exist is therefore not an extra conjecture; we get PRFs for free, assuming that secure PRGs exist.

In this book, we start with the simplest primitives (PRGs) and build “upward” in conceptual complexity. Most of the constructions you will see are oriented in this direction: building something more complex from something simpler.

Valuing practical efficiency: It is instructive to understand how, for example, secure symmetric-key encryption can be built from PRGs alone. However, real-world encryption schemes are not built in this way; the result would be far too inefficient because PRGs are too low-level. In practice, symmetric-key encryption is built from objects of intermediate complexity—typically PRPs, which are introduced later in chapter 7. These PRPs serve as the “ground truth” for cryptographic constructions in practice; we standardize highly optimized PRPs and use them to construct other things of both higher and lower complexity, with security proofs that reduce security to that of the underlying PRP.

5.3. Application: Pseudo-OTP

We originally motivated PRGs as a way to encrypt long plaintexts using a short key. Let's return to that motivation and formalize the details.

Construction 5.3.1 (Pseudo-OTP)

Let GG be a PRG with stretch \ell, so G:{0,1}λ{0,1}λ+G: \bits^\secpar \to \bits^{\secpar+\ell}. Then pseudo-OTP is the following encryption scheme:

K={0,1}λM={0,1}λ+C={0,1}λ+\begin{aligned} \K &= \bits^\secpar \\ \M &= \bits^{\secpar+\ell} \\ \C &= \bits^{\secpar+\ell}\end{aligned}
Enc(K,M)\Enc(\key,\ptxt):
C:=G(K)M\ctxt := G(\key) \oplus \ptxt
return C\ctxt
Dec(K,C)\Dec(\key,\ctxt):
M:=G(K)C\ptxt := G(\key) \oplus \ctxt
return M\ptxt

The key in pseudo-OTP is only λ\secpar bits, but it can be used to encrypt a plaintext of length λ+\secpar+\ell. Pseudo-OTP achieves a similar security property to plain OTP, but involving indistinguishability:

Definition 5.3.2 (Computational one-time secrecy)

An encryption scheme Σ\Sigma has computational one-time secrecy (OTS) if the following two libraries are indistinguishable:

Lots-realΣ\lib{ots-real}^\Sigma
ots.enc(M)\otsenc(\ptxt):
KΣ.K\key \gets \Sigma.\K
C:=Σ.Enc(K,M)\ctxt := \Sigma.\Enc(\key,\ptxt)
return C\ctxt
\indist
Lots-randΣ\lib{ots-rand}^\Sigma
ots.enc(M)\otsenc(\ptxt):
CΣ.C\ctxt \gets \Sigma.\C
return C\ctxt

If the two libraries are interchangeable, then we say that the scheme has perfect one-time secrecy (precisely the same as definition 2.5.3).

Claim 5.3.3 (Pseudo-OTP has computational one-time-secrecy)

If GG is a secure PRG, then pseudo-OTP (construction 5.3.1) has computational one-time secrecy. In other words,

if \quad
Lprg-real\lib{prg-real}
prg.sample()\prgsamp(\,):
S{0,1}λ\seed \gets \bits^\secpar
return G(S)G(\seed)
\indist
Lprg-rand\lib{prg-rand}
prg.sample()\prgsamp(\,):
Y{0,1}λ+Y \gets \bits^{\secpar+\ell}
return YY
then \quad
Lots-real\lib{ots-real}
ots.enc(M)\otsenc(\ptxt):
// KK\key \gets \K:
K{0,1}λ\key \gets \bits^\secpar
// C:=Enc(K,M)C := \Enc(\key,\ptxt):
Y:=G(K)Y := G(\key)
C:=YM\ctxt := Y \oplus \ptxt
return C\ctxt
\indist
Lots-rand\lib{ots-rand}
ots.enc(M)\otsenc(\ptxt):
// CC\ctxt \gets \C:
C{0,1}λ+\ctxt \gets \bits^{\secpar+\ell}
return C\ctxt

Proof idea: You might expect a security proof for something called pseudo-OTP to closely follow the security proof for plain OTP. We proved claim 2.2.2 by explicitly calculating probabilities. Unfortunately, that same strategy won't work against pseudo-OTP, because the PRG GG is completely unspecified; we simply don't seem to have enough information to reason about exact probabilities.

Instead, we must remember this chapter's motivation: We want to use a value G(K)G(\key) as a OTP key to mask the plaintext. Plain OTP requires its key to be uniform, but the theme of this chapter is that being pseudorandom is the next best option.

This idea is formalized in a proof by introducing an intermediate hybrid library. Lots-real\lib{ots-real}, which generates pseudo-OTP ciphertexts using G(K)G(\key) as a kind of OTP key, is indistinguishable from a library that uses a truly uniform OTP key. This new library generates true OTP ciphertexts, so it is of course indistinguishable from Lots-real\lib{ots-real}, as desired. So instead of adapting the technique used to prove security of OTP, we simply use the security of OTP, as-is, in a single step of our proof.

Proof:

Hybrid Sequence:
The starting point is Lots-real\lib{ots-real}, with the pseudo-OTP algorithms included.
To use the fact that GG is a secure PRG, we can apply a three-hop maneuver to replace “Y:=G(K)Y := G(\key) with “Y{0,1}λ+Y \gets \bits^{\secpar+\ell}.” The result of the three-hop maneuver is identical to Lotp-real\lib{otp-real}: a library that produces true OTP ciphertexts of length λ+\secpar+\ell.
Lotp-real\lib{otp-real} and Lotp-rand\lib{otp-rand} are interchangeable (claim 2.2.2):
Lots-real\lib{ots-real}
ots.enc\otsenc(M\ptxt):
// KK\key \gets \K:
K{0,1}λ\key \gets \bits^\secpar
// C:=Enc(K,M)C := \Enc(\key,\ptxt):
YY
:={}:= {}
G(K)G(\key)
prg.sample()\prgsamp()
{0,1}λ+{}\gets \bits^{\secpar+\ell}
C\ctxt
:=YM{}:= Y \oplus \ptxt
{0,1}λ+{}\gets \bits^{\secpar+\ell}
return C\ctxt
\link
Lprg-realG\lib{prg-real}^G
prg.sample\prgsamp( ):
S{0,1}λ\seed \gets \bits^\secpar
Y:=G(S)Y := G(\seed)
return YY
Lprg-randG\lib{prg-rand}^G
prg.sample\prgsamp( ):
Y{0,1}λ+Y \gets \bits^{\secpar+\ell}
return YY

The final library is identical to Lots-rand\lib{ots-rand} from the statement of the claim. This completes the proof.

5.4. How to extend a PRG's stretch

A PRG's stretch measures how much longer the plaintext can be than the key in pseudo-OTP. A larger stretch means you can encrypt longer plaintexts with a conveniently short key.

In this section, we show how to use a PRG with small stretch to build a PRG with longer stretch. We illustrate only the case of using a PRG with stretch λ\secpar to build a PRG with stretch 2λ2\secpar. Exercise 5.9 explores the more general case.

Definition 5.4.1 (Length-doubling)

A PRG GG is length-doubling if it has stretch λ\secpar. In other words, G:{0,1}λ{0,1}2λG : \bits^\secpar \to \bits^{2\secpar}. When GG is length-doubling, we write AB:=G(S)A\|B := G(\seed) to assign the first half of its output to AA and the second half to BB.

Similarly, GG is length-tripling if it has stretch 2λ2\secpar, and we write ABC:=G(S)A\|B\|C := G(\seed) to assign each third of the output to separate variables.

We can extend a PRG's stretch by invoking it twice in sequence:

Construction 5.4.2 (PRG feedback construction)

Let GG be a length-doubling PRG. Then the following function is length-tripling:

H(S)H(\seed):
AB:=G(S)A \| B := G(\seed)
CD:=G(B)C \| D := G(B)
return ACDA \| C \| D
\quad
Claim 5.4.3 (Security of the PRG feedback construction)

If GG is a secure PRG, then construction 5.4.2 is too. In other words,

if \quad
Lprg-realG\lib{prg-real}^G
prg.sampleG()\prgsamp_G(\,):
S{0,1}λ\seed \gets \bits^\secpar
return G(S)G(\seed)
\indist
Lprg-randG\lib{prg-rand}^G
prg.sampleG()\prgsamp_G(\,):
Y{0,1}2λY \gets \bits^{2\secpar}
return YY
then \quad
Lprg-realH\lib{prg-real}^H
prg.sampleH()\prgsamp_H(\,):
S{0,1}λ\seed \gets \bits^\secpar
// H(S)H(\seed):
AB:=G(S)A \| B := G(\seed)
CD:=G(B)C \| D := G(B)
return ACDA \| C \| D
\indist
Lprg-randH\lib{prg-rand}^H
prg.sampleH()\prgsamp_H(\,):
Y{0,1}3λY \gets \bits^{3\secpar}
return YY

Both pairs of libraries are from the Lprg\lib{prg} family, so I have added subscripts on the subroutine names to disambiguate.

Proof idea: We want to show that HH is a secure PRG. In other words, when inputs to HH are chosen uniformly, its outputs are indistinguishable from uniform. Working backwards from our desired goal, what can we say about the outputs of HH?

Its output consists of three blocks, each of which is the output of some call to GG, a secure PRG. Outputs of a PRG are pseudorandom, so proof complete... right? Don't fall into this tempting trap; things are not so simple! A secure PRG is not a magical device that always produces pseudorandom output in every situation; its outputs are pseudorandom only when its input is chosen uniformly.

Here's another way to think about it: The only way to use the fact that GG is a secure PRG in a proof is to factor out some lines of a library into a separate instance of Lprg-realG\lib{prg-real}^G, so they can be replaced with Lprg-randG\lib{prg-rand}^G. In Lprg-realG\lib{prg-real}^G, the input to GG is sampled uniformly.

HH computes its final two output blocks as CD:=G(B)C \|D := G(B). In order to take advantage of GG's property as a secure PRG, its input BB must be chosen uniformly. Unfortunately, this is not the case here; fortunately, though, BB is pseudorandom, and that's the next best option. It means we can consider an indistinguishable intermediate hybrid in which BB actually is uniform.

Thus, the proof has two main steps:

  • Starting with Lprg-realH\lib{prg-real}^H, apply the PRG security of GG to the first call to GG, which is possible because it involves a uniform input to GG. The result is a new intermediate hybrid in which AA and BB are uniformly sampled.

  • Now that the intermediate hybrid samples BB uniformly, we can apply the PRG security of GG to the remaining call to GG, on input BB.

Proof (details):

Hybrid Sequence:
The starting point is Lprg-realH\lib{prg-real}^H.
We can apply a three-hop maneuver to the first call to GG, replacing “AB:=G(S)A\|B := G(\seed) with “AB{0,1}2λA\|B \gets \bits^{2\secpar}.
Uniformly sampling 2λ2\secpar bits is the same as uniformly (and independently) sampling its two halves.
Now we can apply a three-hop maneuver to the remaining call to GG.
Concatenating λ\secpar uniformly sampled bits with 2λ2\secpar independent, uniformly sampled bits is the same as sampling 3λ3\secpar uniform bits. The result of this change is the Lprg-randH\lib{prg-rand}^H library, which completes the proof.
Lprg-realH\lib{prg-real}^H
prg.sampleH\prgsamp_H( ):
S{0,1}λ\seed \gets \bits^\secpar
// H(S)H(\seed):
AA
B\| B
:={}:= {}
G(S)G(\seed)
prg.sampleG()\prgsamp_G()
{0,1}2λ{}\gets \bits^{2\secpar}
{0,1}λ{}\gets \bits^\secpar
CDC \| D
:={}:= {}
G(B)G(B)
prg.sampleG()\prgsamp_G()
{0,1}2λ{}\gets \bits^{2\secpar}
return
ACDA \| C \| D
YY
\link
Lprg-realG\lib{prg-real}^G
prg.sampleG\prgsamp_G( ):
S{0,1}λ\seed \gets \bits^\secpar
return G(S)G(\seed)
Lprg-randG\lib{prg-rand}^G
prg.sampleG\prgsamp_G( ):
Y{0,1}2λY \gets \bits^{2\secpar}
return YY

5.5. How to attack pseudorandomness

Security is a knife's edge. One small change can make a secure construction catastrophically insecure. In this book we will encounter many examples of this phenomenon, starting with the following small modification to construction 5.4.2:

Claim 5.5.1 (An insecure attempt at extending a PRG's stretch)

The following function HH is not a secure PRG, even if GG is.

H(S)H(\seed):
AB:=G(S)A \| B := G(\seed)
CD:=G(B)C \| D := G(B)
return ABCDA \| \hl{B} \| C \| D
\quad

In other words, the following two libraries are not indistinguishable:

Lprg-realH\lib{prg-real}^H
prg.sample()\prgsamp(\,):
S{0,1}λ\seed \gets \bits^\secpar
// H(S)H(\seed):
AB:=G(S)A\|B := G(\seed)
CD:=G(B)C\|D := G(B)
return ABCDA\|B\|C\|D
≊̸\not\indist
Lprg-randH\lib{prg-rand}^H
prg.sample()\prgsamp(\,):
Y{0,1}4λY \gets \bits^{4\secpar}
return YY

Pay special attention to how this claim is worded. We should be able to attack HH, even when GG is the most secure PRG in the world. It would be futile in that case to try to distinguish outputs of GG from uniform.

Instead, we must attack the erroneous way that HH uses GG. Even the best PRG in the world can guarantee security only when its seed is chosen uniformly and not used for anything else. This is the “proper” way to use a PRG, spelled out explicitly in Lprg-real\lib{prg-real}.

Our HH function violates this “contract” by using BB as the input to GG while also including BB in the output. An adversary who knows BB can also compute G(B)G(B), and will notice that the result is exactly equal to the second half of the output from HH. On the other hand, if A,B,C,A, B, C, and DD are all chosen uniformly, it is unlikely that CDC\|D will have anything to do with the value G(B)G(B). Thus, we have identified a way to distinguish outputs of HH from the uniform distribution.

Know Thine Enemy

If you are attacking a construction HH that uses some secure building block GG, don't try to attack GG directly. Instead, attack that erroneous way that HH uses GG. Look for a mismatch between GG's security definition and how HH uses GG.

We now formalize this attack idea, proving claim 5.5.1:

Proof:

To show that HH is not a secure PRG, we must write a program that can distinguish between the following two libraries:

Lprg-realH\lib{prg-real}^H
prg.sample()\prgsamp(\,):
S{0,1}λ\seed \gets \bits^\secpar
// H(S)H(\seed):
AB:=G(S)A\|B := G(\seed)
CD:=G(B)C\|D := G(B)
return ABCDA\|B\|C\|D
Lprg-randH\lib{prg-rand}^H
prg.sample()\prgsamp(\,):
Y{0,1}4λY \gets \bits^{4\secpar}
return YY

Consider the following adversary:

A\A
ABCD:=prg.sample()A\|B\|C\|D := \prgsamp()
return G(B)==CDG(B) == C\|D

When A\A is linked to Lprg-realH\lib{prg-real}^H, then CDC\|D is indeed computed as CD:=G(B)C\|D := G(B). Hence, A\A always outputs true\mytrue.

On the other hand, when A\A is linked to Lprg-randH\lib{prg-rand}^H, the values BB, CC, and DD are independently and uniformly distributed. Since they are independent, we can imagine BB being sampled first. When BB is fixed, G(B)G(B) is uniquely determined, since GG is deterministic. Then A\A will output true\mytrue only if CDC\|D is chosen to equal G(B)G(B). This event happens with probability 1/22λ1/2^{2\secpar} since CDC\|D is uniformly chosen and 2λ2\secpar bits long.

In summary, Pr[ALprg-realHtrue]=1\PR{ \A \link \lib{prg-real}^H \outputs \mytrue } = 1, whereas Pr[ALprg-randHtrue]=1/22λ\PR{ \A \link \lib{prg-rand}^H \outputs \mytrue } = 1/2^{2\secpar}. The difference in probabilities is nonnegligible, so the attack is successful. HH is not a secure PRG.

Is it “legal” for the adversary/calling program to run the GG algorithm?
Kerckhoffs's principle says that the adversary is allowed to know which algorithms it is attacking. In technical terms, the source code of the adversary is allowed to depend on the source code of the two libraries that it might be linked to, including the description of GG. The only thing the adversary doesn't know is the value of S\seed that is chosen in Lprg-real\lib{prg-real}, but knowing S\seed is not necessary to perform our attack.

If I tried to write a security proof for this insecure construction, where would it break down?
The first few steps in the proof of construction 5.4.2 would also apply to this insecure construction. But we'd be stuck when we get to this step:

\cdots
prg.sampleH()\prgsamp_H(\,):
A{0,1}λA \gets \bits^\secpar
B{0,1}λB \gets \bits^\secpar
CD:=G(B)C \| D := \hl{G(B)}
return ABCDA \| \hl{B}\| C \| D
≢!\overset{\hl{!}}{\not\equiv}
prg.sampleH()\prgsamp_H(\,):
A{0,1}λA \gets \bits^\secpar
CD:=prg.sampleG()C \| D := \prgsamp_G()
return AB?CDA \| \hl{B^?}\| C \| D
\link
Lprg-realG\lib{prg-real}^G
prg.sampleG()\prgsamp_G(\,):
S{0,1}λS \gets \bits^\secpar
return G(S)G(S)

We try to express the call to GG in “CD:=G(B)C\|D := G(B) in terms of the Lprg-realG\lib{prg-real}^G library. We rename the BB variable to the S\seed variable inside Lprg-realG\lib{prg-real}^G. The line “B{0,1}λB \gets \bits^\secpar becomes the line “S{0,1}λ\seed \gets \bits^\secpar in Lprg-realG\lib{prg-real}^G. The value G(B)G(B) becomes the return value G(S)G(\seed) from the prg.sampleG\prgsamp_G subroutine.

But what about the remaining reference to BB in “return ABCDA\|\hl{B}\|C\|D?” There is no way to rewrite this reference in terms of the S\seed variable, which is privately scoped in Lprg-realG\lib{prg-real}^G. The library, as written above, results in a “compiler error.” We get stuck because HH doesn't obey the “contract” of how to use its PRG GG: It requires internal secrets that Lprg-realG\lib{prg-real}^G is unwilling to provide.

Later in the book we will not always write the three-hop maneuver explicitly. Still, this example shows that it's important to mentally confirm that the three-hop maneuver “compiles” correctly, because improper use of cryptographic primitives often shows up as an error of scope in an attempted proof.

Exercises

  1. Describe an exponential-time adversary that can successfully distinguish the two libraries from definition 5.1.2, and calculate its distinguishing advantage.

  2. Suppose G1G_1 and G2G_2 are both secure PRGs with identical input/output lengths. Is it possible to tell whether a victim is generating outputs according to G1G_1 or G2G_2 just by looking at its outputs? Assume that the victim indeed samples seeds uniformly and uses each seed only once.

  3. Let G:{0,1}λ{0,1}λ+G : \bits^\secpar \to \bits^{\secpar+\ell} be a deterministic function, and define the following set:

    AG:={YS{0,1}λ:G(S)=Y}. A_G := \{ Y \mid \exists \seed \in \bits^\secpar : G(\seed) = Y \}.

    Show that if there is a polynomial-time (in λ\secpar) algorithm for determining membership in AGA_G, then GG is not a secure PRG.

    AGA_G is unconditionally in the complexity class NP, for any polynomial-time function GG. If P = NP, then there is a polynomial-time algorithm for membership in AGA_G. In other words, if P = NP, no function GG can be a secure PRG.

  4. What can an adversary learn by observing two pseudo-OTP ciphertexts encrypted using the same key?

  5. Pseudo-OTP (construction 5.3.1) is defined in terms of a function G:{0,1}λ{0,1}λ+G : \bits^\secpar \to \bits^{\secpar+\ell}. We proved that if GG is a secure PRG, then pseudo-OTP has computational one-time secrecy. Prove that the converse is also true: If pseudo-OTP (using some function GG) has computational one-time secrecy, then GG is a secure PRG.

  6. Let GG be a length-doubling PRG. Show that the following encryption scheme does not have computational one-time secrecy, even if GG is a secure PRG:

    K={0,1}λM={0,1}4λC={0,1}4λ\begin{aligned} \K &= \bits^\secpar \\ \M &= \bits^{4\secpar} \\ \C &= \bits^{4\secpar}\end{aligned}
    // each Mi\ptxt_i is exactly λ\secpar bits
    Enc(K,M1M4)\Enc(\key,\ptxt_1 \| \cdots \| \ptxt_4):
    S1S2:=G(K)S_1 \| S_2 := G(\key)
    S3S4:=G(S1)S_3 \| S_4 := G(S_1)
    for i=1i =1 to 44:
    Ci:=SiMi\ctxt_i := S_i \oplus \ptxt_i
    return C1C4\ctxt_1 \| \cdots \| \ctxt_4
    // each Ci\ctxt_i is exactly λ\secpar bits
    Dec(K,C1C4)\Dec(\key,\ctxt_1 \| \cdots \| \ctxt_4):
    S1S2:=G(K)S_1 \| S_2 := G(\key)
    S3S4:=G(S1)S_3 \| S_4 := G(S_1)
    for i=1i =1 to 44:
    Mi:=SiCi\ptxt_i := S_i \oplus \ctxt_i
    return M1M4\ptxt_1 \| \cdots \| \ptxt_4
  7. Prove that if an encryption scheme Σ\Sigma has computational one-time secrecy, then the following two libraries are indistinguishable:

    Lleft\lib{left}
    ots.enc(M)\otsenc(\ptxt):
    KΣ.K\key \gets \Sigma.\K
    C:=Σ.Enc(M)\ctxt := \Sigma.\Enc(\ptxt)
    return C\ctxt
    \indist
    Lright\lib{right}
    ots.enc(M)\otsenc(\ptxt):
    KΣ.K\key \gets \Sigma.\K
    MΣ.M\ptxt' \gets \Sigma.\M
    C:=Σ.Enc(M)\ctxt := \Sigma.\Enc(\hl{\ptxt'})
    return C\ctxt
  8. Suppose Σ1\Sigma_1 and Σ2\Sigma_2 are encryption schemes, where Σ2.KΣ1.M\Sigma_2.\K \subseteq \Sigma_1.\M (i.e., Σ1\Sigma_1 can encrypt keys for Σ2\Sigma_2). Prove that if both Σ1\Sigma_1 and Σ2\Sigma_2 have computational one-time secrecy, then so does the following scheme (from construction 2.6.1):

    K:=Σ1.KM:=Σ2.MC:=Σ1.C×Σ2.C\begin{aligned}\K &:= \Sigma_1.\K \\ \M &:= \Sigma_2.\M \\ \C &:= \Sigma_1.\C \times \Sigma_2.\C \end{aligned}
    Enc(K,M)\Enc(\key,\ptxt):
    KΣ2.K\key' \gets \Sigma_2.\K
    C1:=Σ1.Enc(K,K)\ctxt_1 := \Sigma_1.\Enc(\key,\key')
    C2:=Σ2.Enc(K,M)\ctxt_2 := \Sigma_2.\Enc(\key',\ptxt)
    return (C1,C2)(\ctxt_1,\ctxt_2)
    Dec(K,(C1,C2))\Dec(\key,(\ctxt_1,\ctxt_2)):
    K:=Σ1.Dec(K,C1)\key' := \Sigma_1.\Dec(\key,\ctxt_1)
    M:=Σ2.Dec(K,C2)\ptxt := \Sigma_2.\Dec(\key',\ctxt_2)
    return M\ptxt
  9. In construction 5.4.2 we showed how to transform a PRG with stretch λ\secpar into one with stretch 2λ2\secpar. Show how to extend a PRG with stretch 1 into a PRG with stretch \ell, for any >1\ell > 1. Prove that your construction is secure.

  10. Prove that if GG is a secure length-doubling PRG, then the following algorithm HH is also a secure PRG:

    H(S)H(\seed):
    AB:=G(S)A\|B := G(\seed)
    C:=G(A)C := G(A)
    D:=G(B)D := G(B)
    return CDC \| D
  11. We've been so focused on extending a PRG's stretch, but what about reducing a PRG's stretch? Prove that if GG is a secure length-tripling PRG (i.e., its output is 3λ3\secpar bits), then the following algorithm HH is also a secure PRG:

    H(S)H(\seed):
    ABC:=G(S)A\|B\|C := G(\seed)
    return ABA \| B
  12. h Prove that if GG is a secure PRG, then the function H(S)=G(S)H(\seed) = \overline{G(\seed)} is also a secure PRG. G(S)\overline{G(\seed)} means to take the bitwise complement of G(S)G(\seed) (i.e., flip every bit in the string G(S)G(\seed)).

    X=X1λ\overline{X} = X \oplus \bit1^\secpar.

  13. h Prove that if GG is a secure PRG, then the function H(S)=G(S)H(\seed) = G(\overline{\seed}) is also a secure PRG. S\overline{\seed} means to take the bitwise complement of S\seed (i.e., flip every bit in the string S\seed).

    X=X1λ\overline{X} = X \oplus \bit1^\secpar.

  14. In this exercise, let's allow a PRG to have input length other than exactly λ\secpar bits. The only restriction should be that the PRG's output is longer than its input.

    Let G1G_1 and G2G_2 be length-tripling functions, and define the algorithm

    H(S1S2)=G1(S1)G2(S2). H( \seed_1 \| \seed_2 ) = G_1(\seed_1) \oplus G_2(\seed_2).

    So HH has inputs of length 2λ2\secpar and outputs of length 3λ3\secpar. Show that HH is a secure PRG if either G1G_1 or G2G_2 is secure.

    Your proof should involve two cases: In the first case, assume that G1G_1 is secure, but assume nothing about G2G_2, except that its outputs have the correct length. Then repeat, swapping the roles of G1G_1 and G2G_2.

  15. Continuing the previous exercise, what is wrong with the simpler construction H(S)=G1(S)G2(S)H(\seed) = G_1(\seed) \oplus G_2(\seed)?

  16. In this exercise, let's allow a PRG to have input length other than exactly λ\secpar bits. The only restriction should be that the PRG's output is longer than its input.

    1. Let G:{0,1}λ{0,1}3λG : \bits^\secpar \to \bits^{3\secpar} be a conventional length-tripling PRG. Prove that the following function H:{0,1}2λ{0,1}3λH: \bits^{2\secpar} \to \bits^{3\secpar} is a secure PRG if GG is:

      // S\seed is 2λ2\secpar bits
      H(S)H(\seed):
      // AA = first λ\secpar bits of S\seed
      AB:=SA \| B := \seed
      return G(A)G(A)

      Thus, it is possible for a PRG to be secure despite ignoring half of its seed.

    2. Let G:{0,1}λ{0,1}2λG : \bits^\secpar \to \bits^{2\secpar} be a conventional length-doubling PRG. Prove that the following function H:{0,1}2λ{0,1}3λH: \bits^{2\secpar} \to \bits^{3\secpar} is a secure PRG if GG is:

      // S\seed is 2λ2\secpar bits
      H(S)H(\seed):
      // AA = first λ\secpar bits of S\seed
      AB:=SA \| B := \seed
      return AG(B)A \| G(B)

      Thus, it is possible for a PRG to be secure despite including half of its seed directly in the output.

  17. h Suppose GG is a secure PRG with stretch \ell. Prove that the following function HH is also a secure PRG:

    H(S)H(\seed):
    if S==0λ\seed == \bit0^\secpar:
    return 0λ+\bit0^{\secpar+\ell}
    else:
    return G(S)G(\seed)

    Thus, it is possible for a PRG to be secure despite having a “weak” input.

    Use a bad event.

  18. Show that the following algorithm HH is not a secure PRG, even if GG is:

    H(S)H(\seed):
    A:=G(S)A := G(\seed)
    B:=G(S)B := G(\seed)
    return ABA \| B
  19. Let GG be a length-doubling function. Show that the following algorithm HH is not a secure PRG, even if GG is:

    H(S)H(\seed):
    AB:=G(S)A\|B := G(\seed)
    CD:=G(AB)C\|D := G(A \oplus B)
    return ABCDA \| B \| C \| D
  20. Show that the following algorithm HH is not a secure PRG, even if GG is:

    H(S)H(\seed):
    AB:=G(S)A \| B := G(\seed)
    CD:=G(B)C \| D := G(B)
    return B(AC)(AD)B \big\| (A\oplus C) \big\| (A \oplus D)

    (Contrast with exercise 5.23.)

  21. Let GG be a secure length-doubling PRG. Is the following algorithm HH a secure PRG? Give either a security proof or a formal attack.

    H(S)H(\seed):
    AB:=G(S)A \| B := G(\seed)
    CD:=G(B)C \| D := G(B)
    return (AB)CD(A \oplus B) \big\| C \big\| D
  22. Let GG be a secure length-doubling PRG. Is the following algorithm HH a secure PRG? Give either a security proof or a formal attack.

    H(S)H(\seed):
    AB:=G(S)A \| B := G(\seed)
    CD:=G(AB)C \| D := G(A \oplus B)
    return ACDA \| C \| D
  23. Let GG be a secure length-doubling PRG. Is the following algorithm HH a secure PRG? Give either a security proof or a formal attack.

    H(S)H(\seed):
    AB:=G(S)A \| B := G(\seed)
    CD:=G(B)C \| D := G(B)
    return B(AC)B \big\| (A \oplus C)

    (Contrast with exercise 5.20.)

  24. Let GG be a secure length-doubling PRG. Is the following algorithm HH a secure PRG? Give either a security proof or a formal attack.

    H(S)H(\seed):
    AB:=G(S)A \| B := G(\seed)
    CD:=G(AB)C \| D := G(A \oplus B)
    return (AC)(BC)D(A \oplus C) \big\| (B \oplus C) \big\| D
  25. Let GG be a secure length-doubling PRG. Is the following algorithm HH a secure PRG? Give either a security proof or a formal attack.

    H(S)H(\seed):
    A:=G(S)A := G(\seed)
    B:=G(0λ)B := G(\bit0^\secpar)
    return ABA \oplus B
  26. Suppose GG and GG' are both secure PRGs. Is the function H(S)=G(S)G(S)H(\seed) = G(\seed) \| G'(\seed) necessarily a secure PRG too? Either give a security proof or a counterexample (a way to choose secure PRGs GG and GG' that cause HH to be insecure).

Chapter Notes

The first candidate PRG, provably secure from number-theoretic conjectures, was proposed by Blum and Micali [49]. Concurrently, Yao [220] developed the modern security definition for PRGs based on indistinguishability.

The P vs NP question is the most important unsolved question in computer science. It asks whether two classes of computational problems are equal. P refers to the set of problems that can be solved in (deterministic) polynomial time. NP refers to the set of problems whose solutions can be verified (but perhaps not discovered) in polynomial time. An accessible introduction to P, NP, and computational complexity in general can be found in the textbook of Sipser [208] or Arora and Barak [7].

  1. Previous Chapter4. Modern Computational Cryptography
  2. Next Chapter6. Pseudorandom Functions