16
Public-Key Cryptography

Digital Signatures

In chapter 9 we used PRFs for message authentication. If the correct MAC tag F(K,M)F(\key,\ptxt) accompanied a message M\ptxt, this was “proof” that someone who knows the key has vouched for M\ptxt. MACs are symmetric-key primitives: The same key is used both to generate and verify a tag.

This chapter introduces digital signatures, the asymmetric-key equivalent of MACs. A private key is used to produce the authentication tag, and a public key is used to verify it.

16.1. Security definitions for digital signatures

In a digital signature scheme, a user first generates a key pair using a key generation algorithm. Only someone who holds the private key can generate authentication tags, now called signatures, of messages. But anyone who holds the public key can verify that the signature is authentic. Thus, verification must happen differently than for MACs. With a MAC (at least MACs as we have defined them), a tag is verified by simply recomputing the “correct” tag and comparing it to the given one. We cannot expect digital signatures to be verified in the same way, since the person performing verification cannot compute correct signatures on their own. Thus, a signature scheme must specify an additional, explicit verification algorithm.

Definition 16.1.1 (Digital signature scheme)

A digital signature scheme (usually just called a signature scheme) consists of the following algorithms:

  • KeyGen\KeyGen: a randomized algorithm that takes no inputs and outputs a key pair (PK,SK)(\pk,\sk), where PK\pk is a public key and SK\sk is a private key.

  • Sign\Sign: a possibly randomized algorithm that takes a private key SK\sk and message MM\ptxt \in \M as input and returns a signature.

  • Verify\Verify: a deterministic algorithm that takes a public key PK\pk, message M\ptxt, and signature SS as input, and returns a boolean.

If Verify(PK,M,S)=true\Verify(\pk,\ptxt,S)= \mytrue, we say that SS is a valid signature of M\ptxt under PK\pk. A signature scheme is correct if signatures generated by Sign\Sign are always valid. More formally, for all MM\ptxt \in \M, the following program outputs true\mytrue with probability 1:

(PK,SK):=KeyGen()(\pk,\sk) := \KeyGen()
S:=Sign(SK,M)S := \Sign(\sk,\ptxt)
return Verify(PK,M,S)\Verify(\pk,M,S)

Sometimes the public key of a signature scheme is called the verification key and the private key called the signing key.

Security: The intuitive guarantee of a signature scheme is that only the private-key holder can produce valid signatures. Even an adversary who is allowed to see many examples of valid signatures, on messages of its choice, and who knows the public key, cannot produce any new examples of valid signatures.

We formalize security in a similar way to MACs (section 9.4). We imagine an attack scenario in which the adversary can request signatures on chosen messages from the victim. Of course these signatures will always be valid. A forgery is any message-signature pair (M,S)(\ptxt,S) produced by the adversary, which is valid but different than those it received from the victim/library. We say that forgeries should be hard to generate by requiring that the verification algorithm is indistinguishable from an algorithm that simply responds false\myfalse to any (M,S)(\ptxt,S) not generated by the victim. The true verification algorithm differs from this “fake” one only in the case of a forgery, so if they are indistinguishable then it must be hard to produce a forgery.

Definition 16.1.2 (Security for signature schemes)

A digital signature scheme Σ\Sigma is secure if the following two libraries are indistinguishable:

Lsig-realΣ\lib{sig-real}^\Sigma
(PK,SK):=Σ.KeyGen()(\pk,\sk) := \Sigma.\KeyGen()
sig.pk()\sigpk(\,):
return PK\pk
sig.sign(M)\sigsign(\ptxt):
S:=Σ.Sign(SK,M)S := \Sigma.\Sign(\sk,\ptxt)
return SS
sig.ver(M,S)\sigver(\ptxt,S):
return Σ.Verify(PK,M,S)\Sigma.\Verify(\pk,\ptxt,S)
\indist
Lsig-idealΣ\lib{sig-ideal}^\Sigma
(PK,SK):=Σ.KeyGen()(\pk,\sk) := \Sigma.\KeyGen()
sig.pk()\sigpk(\,):
return PK\pk
sig.sign(M)\sigsign(\ptxt):
S:=Σ.Sign(SK,M)S := \Sigma.\Sign(\sk,\ptxt)
S:=S{(M,S)}\mathcal{S} := \mathcal{S} \cup \{ (\ptxt,S) \}
return SS
sig.ver(M,S)\sigver(\ptxt,S):
if (M,S)S(\ptxt,S) \in \mathcal{S}: return true\mytrue
else: return false\myfalse

Another difference with MACs is that we treated MACs and PRFs as synonyms. Thus, every MAC that we have seen has tags that are not only hard to forge but are pseudorandom. But pseudorandom signatures are simply not possible. A valid signature cannot be pseudorandom because it satisfies a very conspicuous property: It causes the Verify\Verify algorithm to output true\mytrue! A uniformly chosen value would rarely have this property (otherwise, one could easily generate forgeries by sampling signatures uniformly).

Because of this distinction, the security definition for signature schemes does not require signatures to look pseudorandom. Both libraries produce and output truly valid signatures; we do not have a “real” library generating valid signatures and a “random” library generating fake, uniformly chosen ones.

16.2. Signatures from RSA

In RSA-based cryptography, only someone who holds the private key can compute ee-th roots. On the other hand, anyone with the public key can verify that XX is an ee-th root of YY by checking Xe=YX^e = Y. These properties seem perfectly matched for digital signatures. Can we make a signature scheme in which signatures are ee-th roots?

16.2.1. Textbook RSA signatures

Textbook RSA is the signature scheme you get by letting the ee-th root of M\ptxt be its signature.

Construction 16.2.1 (Textbook RSA signature scheme)

The textbook RSA digital signature scheme is defined by the following algorithms:

KeyGen=RSA.KeyGen\KeyGen = \RSA.\KeyGen
Sign(SK=(n,d),M)\Sign( \sk=(\nmod,d), \ptxt ):
S:=Md%nS := \ptxt^d \pct \nmod
return SS
Verify(PK=(n,e),M,S)\Verify( \pk=(\nmod,e), \ptxt, S ):
if SenMS^e \equiv_\nmod \ptxt:
return true\mytrue
else: return false\myfalse

Unfortunately, just like the case of encryption, the textbook RSA approach is insecure.

First, textbook RSA signatures are malleable, thanks to their algebraic structure. Given two textbook RSA signatures S1=(M1)dS_1 = (\ptxt_1)^d and S2=(M2)dS_2 = (\ptxt_2)^d, it's not hard to see that S1S2S_1 \cdot S_2 is a valid signature for the message M1M2\ptxt_1 \cdot \ptxt_2. In a secure signature scheme, it should not be possible to guess a valid signature on M1M2\ptxt_1 \cdot \ptxt_2 after seeing valid signatures of M1\ptxt_1 and M2\ptxt_2.

Second, we must be more precise when claiming that “it's hard to compute ee-th roots mod n\nmod.” In fact, it is easy to find a pair (S,M)(S,\ptxt) where SS is the ee-th root of M\ptxt: Simply choose SS first, and then set M=Se%n\ptxt = S^e \pct \nmod. In the context of textbook RSA signatures, this corresponds to an attack in which the adversary chooses the signature first and then computes the message that matches. Even though the attack results in a signature on a message that the adversary can't control, it's something that should not be possible in a secure digital signature scheme.

To be more precise about computing ee-th roots mod n\nmod, we should say that “it's hard to compute ee-th roots mod n\nmod, of values that you didn't choose.” In textbook RSA signatures, the M\ptxt values can be chosen by the adversary, which means they can be chosen with a known ee-th root. To fix textbook RSA signatures, the signer should not compute the ee-th root of M\ptxt directly, but rather the ee-th root of something that nobody can directly control.

16.2.2. RSA-PSS

In the RSA-PSS scheme, the signer computes ee-th roots of a hash of M\ptxt, the idea being that it should be hard to choose M\ptxt that hashes to any favorable value. The signature scheme can be proven secure if the hash function is modeled as a random oracle. The proof is made significantly easier if the signer computes an ee-th root, not of H(M)\ro(\ptxt) but of H(MR)\ro(\ptxt \|R), where RR is chosen uniformly for each signature (and included in the output).

Construction 16.2.2 (RSA-PSS)

Let H\ro be a random oracle whose range is Zn\Z_\nmod. The RSA probabilistic signature scheme (RSA-PSS) is defined by the following algorithms:

KeyGen=RSA.KeyGen\KeyGen = \RSA.\KeyGen
Sign(SK=(n,d),M)\Sign( \sk=(\nmod,d), \ptxt ):
R{0,1}λR \gets \bits^\secpar
S:=H(MR)d%nS := \ro(\ptxt \| R)^d \pct \nmod
return (R,S)(R,S)
Verify(PK=(n,e),M,(R,S))\Verify( \pk=(\nmod,e), \ptxt, (R,S) ):
if SenH(MR)S^e \equiv_\nmod \ro(\ptxt \| R):
return true\mytrue
else: return false\myfalse

One downside to RSA-PSS is that it requires a hash function that acts like a random oracle, with outputs in Zn\Z_\nmod. It's not immediately clear how to instantiate such a hash function in the real world. However, construction 16.2.2 is merely a simplification of the “real” RSA-PSS standard, which uses a more conventional random oracle with outputs in {0,1}λ\bits^\secpar.

16.2.3. Self-reducibility

In the RSA assumption (definition 15.2.5), one RSA key pair is associated with just a single challenge value YY. Finding the ee-th root of this value YY is hard. On the other hand, the security of RSA-PSS relies on the difficulty of finding the ee-th root of any one of many random oracle outputs. Hence, one important step in the proof is to bridge this gap between one target for ee-th roots and many targets.

In this section, we prove that finding the ee-th root of any one of many uniformly chosen targets is hard. This is a general result, not tied to the use of RSA for signatures. The proof uses the following idea: Given any RSA target value YY^*, there is a way to generate many new values YiY_i such that:

  • Each YiY_i is uniformly distributed in Zn\Z^*_\nmod, and

  • Given the ee-th root of any of these YiY_i values, we can easily compute an ee-th root of YY^*.

Thus, from a single target value YY^* we get many target values YiY_i which follow the correct distribution, and whose ee-th roots are exactly as hard to find as YY^*'s. This kind of transformation, from one YY^* to many YiY_i's, is called a random self-reduction, and it is a useful concept throughout cryptography.

Let's now see the idea behind this self-reduction, illustrated for a single YY value. Given a target value YY^*, how can we choose YY such that an ee-th root of YY helps us learn the ee-th root of YY^*?

Claim 16.2.3 (Random self-reduction for RSA)

Suppose Y,Y,ΔZnY^*, Y, \Delta \in \Z^*_\nmod, where YYΔeY \equiv Y^* \cdot \Delta^e. Then given Δ\Delta, and an ee-th root of YY, it is possible to efficiently compute an ee-th root of YY^*. Furthermore, if Δ\Delta is sampled uniformly in Zn\Z^*_\nmod, then the distribution over YY is uniform.

Proof:

If XX is an ee-th root of YY, then X=XΔ1X^* = X \cdot \Delta^{-1} is an ee-th root of YY^*, a fact that can be verified as:

(X)en(XΔ1)enXe(Δe)1nY(Δe)1n(YΔe)(Δe)1nY. (X^*)^e \equiv_\nmod (X \cdot \Delta^{-1})^e \equiv_\nmod X^e (\Delta^e)^{-1} \equiv_\nmod Y (\Delta^e)^{-1} \equiv_\nmod (Y^* \Delta^e) (\Delta^e)^{-1} \equiv_\nmod Y^*.

To see that YY is distributed uniformly, observe that: (1) Δ\Delta is chosen uniformly; (2) raising to the ee-th power is a 1-to-1 function, so Δe\Delta^e is distributed uniformly; (3) Y=YΔeY = Y^* \cdot \Delta^e is a one-time pad ciphertext with Δe\Delta^e acting as key, and multiplication-mod-n\nmod as the algebraic group operation.

We can now prove the multi-target security of the RSA assumption:

Claim 16.2.4 (RSA assumption with many challenges)

If the RSA assumption is true, then the following two libraries are indistinguishable:

Lrsa*-real\lib{rsa*-real}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
rsa.pk()\rsapk^*(\,):
return (n,e)(\nmod,e)
rsa.challenge()\rsachallenge^*(\,):
YZnY \gets \Z_\nmod
Y:=Y{Y}\mathcal{Y} := \mathcal{Y} \cup \{Y\}
return YY
// is XX the ee-th root of any YYY \in \mathcal{Y}?
rsa.check(X)\rsacheck^*(X):
if Xe%nYX^e \pct \nmod \in \mathcal{Y}: return true\mytrue
else: return false\myfalse
\indist
Lrsa*-ideal\lib{rsa*-ideal}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
rsa.pk()\rsapk^*(\,):
return (n,e)(\nmod,e)
rsa.challenge()\rsachallenge^*(\,):
YZnY \gets \Z_\nmod
return YY
// is XX the ee-th root of any YYY \in \mathcal{Y}?
rsa.check(X)\rsacheck^*(X):
return false\myfalse

These libraries are indistinguishable if it is hard for the adversary to find the ee-th root of any of the YY-values generated by the library.

Proof:

Hybrid Sequence:
The starting point for the proof is Lrsa*-real\lib{rsa*-real}.
First, we rewrite the check for membership in Y\mathcal{Y} as a for-loop involving explicit comparisons.
Suppose we initially choose one value YY^* and later define each YYY \in \mathcal{Y} as Y=YΔeY = Y^* \cdot \Delta^e. If each Δ\Delta is uniformly distributed, then the YY's are also uniformly distributed. In rsa.check\rsacheck^*, we can then replace each YY with its equivalent expression YΔeY^* \cdot \Delta^e. Instead of keeping track of a collection of YY-values, it is then enough to keep track of their Δ\Delta values.
Now we can rearrange the equation XenYΔeX^e \equiv_\nmod Y^* \cdot \Delta^e to obtain the equivalent equation (XΔ1)enY(X \Delta^{-1})^e \equiv_\nmod Y^*.
Now the library has a single target value YY^* and repeatedly checks whether a certain expression (XΔ1X \cdot \Delta^{-1}) is its ee-th root. We can therefore apply the RSA assumption, with YY^* playing the role of its single target value. The standard three-hop maneuver is not shown.
As we argued above, each YY value is sampled uniformly. Now that the Δ\Delta values are not needed, we can simply sample the YY values uniformly in a more direct way, as they were previously. After simplifying its code, the result is Lrsa*-ideal\lib{rsa*-ideal}, which completes the proof.
Lrsa*-real\lib{rsa*-real}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
rsa.pk\rsapk^*( ):
return (n,e)(\nmod,e)
rsa.challenge\rsachallenge^*( ):
YY
Zn{}\gets \Z_\nmod
:=YΔe%n{}:= Y^* \cdot \Delta^e \pct \nmod
Zn{}\gets \Z_\nmod
Y:=Y{Y}\mathcal{Y} := \mathcal{Y} \cup \{Y\}
return YY
rsa.check\rsacheck^*(XX):
if
XeX^e
%nY{}\pct \nmod \in \mathcal{Y}: return true\mytrue
n\equiv_\nmod
YY: return true\mytrue
YΔeY^* \cdot \Delta^e: return true\mytrue
(XΔ1)enY(X \cdot \Delta^{-1})^e \equiv_\nmod Y^*: return true\mytrue
false\myfalse: return true\mytrue
else: return false\myfalse

16.2.4. Security proof for RSA-PSS

We now have the tools to prove security of RSA-PSS.

Claim 16.2.5

RSA-PSS (construction 16.2.2) is a secure digital signature scheme in the random oracle model, if the RSA assumption is true.

Proof:

An RSA-PSS signature is the ee-th root of a random oracle output. The intuition behind security is that it is hard to compute the ee-th root of such uniformly sampled values, if you don't know the private RSA exponent dd. We expect to formalize this intuition in the security proof by applying claim 16.2.4. But we cannot do so unless we have a hybrid library that doesn't use dd at all: The libraries in claim 16.2.4 do not provide dd to the calling program. So the main challenge in this proof is finding a different way to implement the sig.sign\sigsign subroutine without using dd.

Our approach takes advantage of the fact that the library can change how random-oracle outputs are generated; this is called programming the random oracle. Normally, the sig.sign\sigsign subroutine would sample H(MR)\ro(M\|R) uniformly from Zn\Z_\nmod. We introduce a hybrid in which the library samples this H(MR)\ro(M\|R) to have a known ee-th root. In other words, when H(MR)\ro(M\|R) is called, the library samples SS, computes X=SeX = S^e, and designates XX to be the output of H(MR)\ro(M\|R). The output distribution of H(MR)\ro(M\|R) does not change; it remains uniform. However, (R,S)(R,S) is a valid RSA-PSS signature of MM, because SS is the ee-th root of H(MR)=X\ro(M\|R) = X. Importantly, this modified library never needs to know the exponent dd.

At this point in the proof, random oracle calls are treated in two distinct ways: If a random oracle call is made inside sig.sign\sigsign, then the library chooses the output in this special way to have a known ee-th root. If a random oracle call is made directly by the adversary, then the library chooses the output uniformly, so we can argue that finding an ee-th root of this value is hard. You may ask what should happen if a random oracle call falls into both cases. Should the output be chosen with a known or unknown ee-th root? Fortunately, we don't need to worry about this case. The first case (in sig.sign\sigsign) involves calls of the form H(MR)\ro(M\|R), where RR has just been sampled uniformly. It is therefore only negligibly likely that the adversary has already directly called H(MR)\ro(M\|R). This is precisely the reason for RR in the construction.

We now proceed with the hybrid proof.

Hybrid Sequence:
The starting point is Lsig-real+ro\lib{sig-real+ro}:
The library can remember signatures produced by sig.sign\sigsign; they don't need to be verified later in sig.ver\sigver.
Inline the call made to H\ro inside sig.sign\sigsign.
Make the if-statement in sig.sign\sigsign unconditional. This changes the library's behavior only in the bad event that H[MR]\rotable[\ptxt\|R] is already defined. However, RR is sampled uniformly each time. If the adversary makes at most qq calls to the library's subroutines, then there are most qq entries in H[]\rotable[\cdot], so at most qq “bad” values of RR that can be chosen. Overall, across at most qq calls to sig.sign\sigsign, the bad event has negligible probability at most q2/2λq^2/2^\secpar.
Instead of uniformly sampling H[MR]\rotable[\ptxt\|R] and setting S:=H[MR]dS := \rotable[\ptxt\|R]^d, we can uniformly sample SS and set H[MR]:=Se\rotable[\ptxt\|R] := S^e. The two methods induce the same joint distribution over (S,H[MR])(S, \rotable[\ptxt\|R]).
When sig.ver\sigver checks whether Y=SeY = S^e, it always uses a YY that was chosen uniformly in H\ro, not chosen with a known ee-th root in sig.sign\sigsign (the if-statement in sig.ver\sigver catches these cases). If we let Y\mathcal{Y} denote the set of all H\ro-outputs, then the condition Y=SeY = S^e implies SeYS^e \in \mathcal{Y}. Hence, it has no effect on the library to add the additional check SeYS^e \in \mathcal{Y} in sig.ver\sigver.
The library no longer uses the private RSA exponent dd; it maintains a set Y\mathcal{Y} of uniformly sampled values; it later checks whether the adversary has provided an ee-th root of any of these values. Hence, we can apply claim 16.2.4:
After removing the now-unreachable if-statement, and reversing several earlier changes, the result is Lsig-fake+ro\lib{sig-fake+ro}. This completes the proof.
Lsig-real+ro\lib{sig-real+ro}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
sig.pk\sigpk( ):
return
(n,e)(\nmod,e)
rsa.pk()\rsapk^*()
(n,e)(\nmod,e)
sig.sign\sigsign(M\ptxt):
// Sign(SK,M)\Sign(\sk,\ptxt):
R{0,1}λR \gets \bits^\secpar
S:=S := {}
H(MR)d%n\ro(\ptxt\|R)^d \pct \nmod
H[MR]d%n\rotable[\ptxt\|R]^d \pct \nmod
return (R,S)(R,S)
sig.ver\sigver(M,(R,S)\ptxt,(R,S)):
// Verify(PK,M,(R,S))\Verify(\pk,\ptxt,(R,S)):
Y:=H(MR)Y := \ro(\ptxt\|R)
return
Y==Se%nY == S^e \pct \nmod
false\myfalse
H\ro(AA):
if H[A]\rotable[A] undefined:
H[A]\rotable[A]
Zn{}\gets \Z_\nmod
:=rsa.challenge(){}:= \rsachallenge^*()
Zn{}\gets \Z_\nmod
return H[A]\rotable[A]
\link
Lrsa*-real\lib{rsa*-real}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
rsa.pk\rsapk^*( ):
return (n,e)(\nmod,e)
rsa.challenge\rsachallenge^*( ):
YZnY \gets \Z_\nmod
Y:=Y{Y}\mathcal{Y} := \mathcal{Y} \cup \{Y\}
return YY
rsa.check\rsacheck^*(XX):
if Xe%nYX^e \pct \nmod \in \mathcal{Y}: return true\mytrue
else: return false\myfalse
Lrsa*-ideal\lib{rsa*-ideal}
(n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
rsa.pk\rsapk^*( ):
return (n,e)(\nmod,e)
rsa.challenge\rsachallenge^*( ):
YZnY \gets \Z_\nmod
return YY
rsa.check\rsacheck^*(XX):
return false\myfalse

A note on programming: Programming the random oracle is a powerful proof technique, and one of the main features of the random oracle that critics disparage. Indeed, imagine trying to carry out the steps of our security proof where H\ro is a public, plain-model hash function like SHA-3. You will get stuck when the proof reaches a hybrid that tries to “choose” SHA3(MR)\textsf{SHA3}(\ptxt\|R) to have a known ee-th root. Of course, the library cannot do this, because SHA3(MR)\textsf{SHA3}(\ptxt\|R) simply is whatever it is, and the library cannot pretend it to be something else.

16.2.5. A rant

If you want to make a cryptographer genuinely angry, casually mention that signing is just encrypting with the private key, or that verifying a signature is just decrypting with the public key.

The document is then encrypted with the user's private key.

— US News & World Report, “What Is a Digital Signature?”

To validate a digital signature, the recipient ... decrypts the digital signature using the sender's PUBLIC key...

Public key encrypts, private key decrypts (encrypting); Private key encrypts, public key decrypts (signing)

— highly rated answers to Stack Overflow question, “How does a public key verify a signature?”

You can create a one-way hash of the data and then use your private key to encrypt the hash. The encrypted hash, along with other information like the hashing algorithm, is known as a digital signature.

— IBM z/TPF documentation

Why do people say these things?
RSA-based cryptography, for both encryption and signatures, involves exponentiation to the ee power and to the dd power:

exponentiate with ee exponentiate with dd
RSA-KEM: encryption decryption
RSA signatures: verification signing

In a nontechnical context, we might want to avoid talking about the scary concept of exponentiation and instead euphemistically refer to it as “encryption/decryption with a key.” In that case it would make sense to describe signing as “encryption with the private key” This correctly emphasizes the fact that encryption and signature verification use public information, while decryption and signing require private information.

So what's wrong with saying these things?
First, it's annoyingly imprecise to call everything “encryption” and “decryption.” Digital signatures and public-key encryption are completely different primitives, targeting completely different security goals; they deserve different terminology. If an operation requires the private key of a public-private keypair, please don't call it encryption.

Second, it's wrong to suggest a fundamental duality between signature schemes and encryption schemes (“to construct a signature scheme, just reverse the keys in a public-key encryption scheme!”). The fact that RSA encryption, decryption, signing, verification all use similar exponentiation steps is mostly a fluke. There is no fundamental reason to expect a signing algorithm to resemble any kind of encryption operation. Aside from RSA, I can't think of any other signature scheme with this curious property. In general, you cannot easily convert an arbitrary PKE scheme into a digital signature scheme, nor vice versa.

16.2.6. Looking Ahead

RSA-based signatures have great historical significance, and their security proof demonstrates important new provable security techniques. However, RSA signatures are expensive and large, because RSA requires huge moduli. One might wonder whether, as in the case of key agreement, it is possible to achieve something better by using elliptic curve cryptography, where the underlying values are significantly smaller than RSA group elements. Later in section 19.4 we discuss an alternative approach for signatures—called Schnorr signatures—that can be based on elliptic curves and therefore lead to much smaller signatures. For most applications, Schnorr signatures (and closely related constructions) are a better choice than RSA signatures.

16.3. Common signature idioms

16.3.1. Hash-then-sign

In RSA-PSS, the signer starts by computing a hash of the message being signed. It is important to the security proof that the hash function is a random oracle. But the idea of hashing before signing is a standard general principle. In practice, one can always sign a hash of a long message rather than the message itself.

Signing a hash authenticates that the signer vouches for that hash. And if the hash function is collision-resistant, there can be only one known message that produces that hash, so the signature of its hash authenticates that (unique) message. Both the signer and verifier must be able to evaluate this hash function. Thus, one should use a standard collision-resistant hash function with public salt, and not a UHF.

We can formalize the security of signing a hash, with the following construction:

Construction 16.3.1 (Hash-then-sign)

Let Σ\Sigma be a signature scheme with Σ.M={0,1}n\Sigma.\M = \bits^n, and let HH be a salted hash function with output length nn. The hash-then-sign construction is defined by the following:

M={0,1}\M = \bits^*
KeyGen()\KeyGen(\,):
(PK,SK)Σ.KeyGen(\pk,\sk) \gets \Sigma.\KeyGen
T{0,1}λT \gets \bits^\secpar
PK:=(PK,T)\pk' := (\pk,T)
SK:=(SK,T)\sk' := (\sk,T)
return (PK,SK)(\pk',\sk')
Sign((SK,T),M)\Sign\bigl((\sk,T),\ptxt\bigr):
X:=H(T,M)X := H(T,\ptxt)
S:=Σ.Sign(SK,X)S := \Sigma.\Sign(\sk,X)
return SS
Verify((PK,T),M,S)\Verify\bigl( (\pk,T), \ptxt, S\bigr):
X:=H(T,M)X := H(T,\ptxt)
return Σ.Verify(PK,X,S)\Sigma.\Verify(\pk,X,S)

We use variable TT to denote the hash function's salt, since SS is used to represent signatures.

Claim 16.3.2 (Security of hash-then-sign)

If Σ\Sigma is a secure signature scheme and HH is collision-resistant, then hash-then-sign is a secure signature scheme.

Proof:

Hybrid Sequence:
The starting point is Lsig-real\lib{sig-real}.
First, apply the security of signature scheme Σ\Sigma. The standard three-hop maneuver is not shown.
Rewrite the check (X,S)S(X,S) \in \mathcal{S} explicitly in terms of equality tests. This will make it easier to apply the collision resistance of HH later.
Instead of storing H(T,M)H(T,\ptxt) in S\mathcal{S}, we can store M\ptxt in S\mathcal{S} and recompute its hash H(T,M)H(T,\ptxt) later when it is needed.
Now that sig.ver\sigver is implemented in terms of hash comparisons, we can apply the collision resistance of HH (definition 10.1.1). The standard three-hop maneuver is not shown.
The for-loop is just an explicit implementation of the check (M,S)S(\ptxt,S) \in \mathcal{S}. Rewriting in this way results in Lsig-fake\lib{sig-fake}.
Lsig-real\lib{sig-real}
(PK,SK):=Σ.KeyGen()(\pk',\sk) := \Sigma.\KeyGen()
T{0,1}λT \gets \bits^\secpar
PK:=(PK,T)\pk := (\pk,T)
sig.pk\sigpk( ):
return PK\pk
sig.sign\sigsign(M\ptxt):
// Sign((SK,T),M)\Sign\bigl( (\sk,T), \ptxt \bigr):
X:=H(T,M)X := H(T,\ptxt)
S:=Σ.Sign(SK,X)S := \Sigma.\Sign(\sk,X)
return SS
sig.ver\sigver(M,S\ptxt,S):
// Verify((PK,T),M,S)\Verify\bigl( (\pk,T), \ptxt,S \bigr):
X:=H(T,M)X := H(T,\ptxt)
return Σ.Verify(PK,X,S)\Sigma.\Verify(\pk',X,S)

16.3.2. Certificates and chains

When Alice wants to connect to joyofcryptography.com, how does her browser ensure that she is talking to the real joyofcryptography.com and not some impostor website that advocates for ECB mode? Cryptography does not directly involve things like website domain names; instead, it involves public keys and private keys. Users need a way to bridge the gap between cryptographic public keys and human-understandable identities, like domain names. On the internet, this gap is bridged by certificates, a common application of digital signatures. Certificates help answer the question, what is the correct public key for this particular domain name? Later in chapter 18 we discuss how to actually use a public key to cryptographically authenticate a website connection.

There are billions of websites, so web browsers cannot simply ship with a database that maps every domain name to a public keys. Instead, browsers delegate the responsibility to a small number of certificate authorities (CA). The job of a CA is to issue certificates, which are essentially digital signatures on messages of the form “a28f1eb9... is a valid public key for joyofcryptography.com.”

Certificates are issued in the following process:

  • A website operator contacts a CA and presents a public key PK\pk. The operator proves that (1) it controls a domain name, usually by adding a special string to its DNS record or to a publicly accessible webpage, and (2) that it controls the public key, usually by signing a challenge message sampled uniformly by the CA.

  • If the CA is satisfied, it will generate a certificate signed under its (the CA's) public key.

This process is frequently automated, and some larger website hosting companies are also CAs themselves, making the process easier.

Later, when a browser connects to the website:

  • The webserver presents its public key PK\pk, and its certificate.

  • The browser verifies that the certificate lists PK\pk and the expected domain name, and that it is signed by a known CA. Each browser ships with a small collection of known CA public keys; at the time of writing, my browser recognizes 74 CAs.

  • Assuming all of these checks pass, the browser attempts to authenticate the server as the holder of the private key corresponding to PK\pk. Authentication happens using the techniques described in chapter 18.

Signature/Certificate Chains: A certificate is just a signature vouching for someone else's public key. That someone else could be a website, but it could also be another CA. In practice, root CAs sign the public keys of other CAs, called intermediate CAs, who then sign public keys of websites. This arrangement helps relieve load on the root CAs.

For example, the certificate for joyofcryptography.com is signed by Cloudflare's CA, whose CA certificate is signed by Baltimore CyberTrust, a root CA whose public key is in your browser's trust store. When your browser connects to joyofcryptography.com, the server presents its public key along with this certificate chain. Your browser validates the entire chain from root to website.

Trusting CAs: Any certificate authority that your browser trusts can issue a certificate for any domain name. Thus, CAs have the power to completely and silently impersonate any website on the internet. The decision to include a CA in a browser's trusted list is therefore not taken lightly, and geopolitical forces are often at play. (The EU recently proposed controversial legislation that would force browsers to trust CAs operated by EU governments.)

A rogue CA who issues improper certificates can have a disastrous impact on the internet. While rogue certificates cannot be completely eliminated, modern web browsers include some features to detect them. For example, a website operator can instruct browsers to accept certificates only from specific CAs, using a special DNS record called certificate authority authorization (CAA). In a project called certificate transparency, CAs are required to publicly announce all certificates they issue; some browsers periodically check certificates they have received against this public list. A domain name owner can also check the list for unexpected certificates for their domain. If a website presents a certificate that is not in this public list, the offending CA's reputation can be damaged.

Exercises

  1. Let Σ\Sigma be a digital signature scheme, and define the new scheme Σ\Sigma' as follows:

    Σ.KeyGen=Σ.KeyGen\Sigma'.\KeyGen = \Sigma.\KeyGen
    Σ.Sign(SK,M)\Sigma'.\Sign(\sk,\ptxt):
    S:=Σ.Sign(SK,M)S := \Sigma.\Sign(\sk,\ptxt)
    return SMS \| M
    Σ.Verify(PK,M,S)\Sigma'.\Verify(\pk,M,S):
    parse SM:=SS' \| M' := S
    if MMM' \ne M: return false\myfalse (\star)
    return Σ.Verify(PK,M,S)\Sigma.\Verify(\pk,M,S')
    1. Prove that Σ\Sigma' is secure, if Σ\Sigma is. This example shows that digital signatures do not need to hide the message, since signatures in Σ\Sigma' include the message in the clear.

    2. Show that if the line marked \star is removed, then the resulting scheme is not secure.

  2. Let Σ\Sigma be a digital signature scheme, and define the new scheme Σ\Sigma' as follows:

    Σ.KeyGen=Σ.KeyGenΣ.M=Σ.M={0,1}n\begin{aligned} \Sigma'.\KeyGen &= \Sigma.\KeyGen \\ \Sigma'.\M &= \Sigma.\M = \bits^n \end{aligned}
    Σ.Sign(SK,M)\Sigma'.\Sign(\sk,\ptxt):
    V{0,1}nV \gets \bits^n
    S1:=Σ.Sign(SK,V)S_1 := \Sigma.\Sign(\sk,V)
    S2:=Σ.Sign(SK,VM)S_2 := \Sigma.\Sign(\sk,V \oplus \ptxt)
    return (V,S1,S2)(V,S_1,S_2)
    Σ.Verify(PK,M,(V,S1,S2))\Sigma'.\Verify\bigl(\pk,\ptxt,(V,S_1,S_2)\bigr):
    return Σ.Verify(PK,V,S1)\Sigma.\Verify(\pk,V,S_1) and Σ.Verify(PK,VM,S2)\Sigma.\Verify(\pk,V\oplus \ptxt,S_2)

    Show that Σ\Sigma' is not a secure digital signature scheme.

  3. In this exercise, H\ro is a random oracle with input and output length λ\secpar. We use the following shorthand notation:

    H(i)(X)=H(H(Hi times(X)). \ro^{(i)}(X) = \underbrace{\ro(\ro(\cdots\ro}_{i \text{ times}}(X)\cdots).

    Consider the following signature scheme:

    M={0,,127}\begin{aligned} \M &= \{0, \ldots, 127\} \end{aligned}
    KeyGen()\KeyGen(\,):
    SK1{0,1}λ\sk_1 \gets \bits^\secpar
    SK2{0,1}λ\sk_2 \gets \bits^\secpar
    PK1:=H(127)(SK1)\pk_1 := \ro^{(127)}(\sk_1)
    PK2:=H(127)(SK2)\pk_2 := \ro^{(127)}(\sk_2)
    return ((PK1,PK2),(SK1,SK2))\bigl( (\pk_1,\pk_2), (\sk_1,\sk_2) \bigr)
    Sign((SK1,SK2),M)\Sign\bigl( (\sk_1,\sk_2), \ptxt \bigr):
    // M{0,,127}\ptxt \in \{0, \ldots, 127\}
    S1:=H(M)(SK1)S_1 := \ro^{(\ptxt)}(\sk_1)
    S2:=H(127M)(SK2)S_2 := \ro^{(127-\ptxt)}(\sk_2)
    return (S1,S2)(S_1, S_2)
    Verify((PK1,PK2),M,(S1,S2))\Verify\bigl( (\pk_1, \pk_2), \ptxt, (S_1, S_2) \bigr):
    X1:=H(127M)(S1)X_1 := \ro^{(127-\ptxt)}(S_1)
    X2:=H(M)(S2)X_2 := \ro^{(\ptxt)}(S_2)
    return [X1==PK1[X_1 == \pk_1 and X2==PK2]X_2 == \pk_2]
    1. Show that the scheme satisfies correctness.

    2. \star Consider a variant of the security definition for digital signatures, in which the adversary can receive only one signature (e.g., sig.sign\sigsign returns an error if called more than once). Prove that the scheme is secure with respect to this modified definition.

    3. Show that the scheme is not secure with respect to the standard definition for digital signatures.

  4. In section 15.3 we proved that RSA-KEM is a secure one-message KEM. Then we used the general result that a secure one-message KEM is a secure many-message KEM. But the latter proof involves a sequence of qq hybrids, where qq is the number of ciphertexts encrypted by the adversary. Each hybrid adds a negligible loss to the proof's concrete security. Overall, these two proofs show that breaking security of RSA-KEM is at most qq times easier than breaking the RSA assumption.

    Give a direct proof that RSA-KEM is a secure many-message KEM (in the random oracle model), where the sequence of hybrids applies the RSA assumption only once. Thus, in terms of concrete security, breaking security of RSA-KEM is no easier than breaking the RSA assumption.

  5. Show a random self-reduction for the discrete logarithm problem. Let G\G be a cyclic group with order nn and generator gg.

    Given any XGX^* \in \G, show how to generate a new value XGX \in \G such that:

    • XX is uniformly distributed in G\G.

    • Given the discrete logarithm of XX, there is an efficient way to compute the discrete logarithm of XX^*.

  6. h This exercise develops a random self-reduction for the DDH problem. Let G\G be a cyclic group with order nn and generator gg. Consider the following algorithm:

    SelfReduce(A,B,C)\textsf{SelfReduce}(A^*,B^*,C^*):
    rZnr \gets \Z_\nmod
    sZns \gets \Z_\nmod
    tZnt \gets \Z_\nmod
    A:=(A)tgrA := (A^*)^t \cdot g^r
    B:=BgsB := B^* \cdot g^s
    C:=(A)st(B)r(C)tgrsC := (A^*)^{st} (B^*)^r (C^*)^t \cdot g^{rs}
    return (A,B,C)(A,B,C)

    We will say that (A,B,C)(A,B,C) are a Diffie-Hellman triple if A=gaA = g^a, B=gbB= g^b, and C=gabC=g^{ab}. The DDH assumption says that it is hard to distinguish the uniform distribution over Diffie-Hellman triples from the uniform distribution over all triples in G3\G^3.

    1. Show that if (A,B,C)(A^*,B^*,C^*) is a Diffie-Hellman triple, then the output of SelfReduce(A,B,C)\textsf{SelfReduce}(A^*,B^*,C^*) is uniformly distributed over Diffie-Hellman triples. Make no assumptions about the distribution on (A,B,C)(A^*, B^*, C^*). The output of SelfReduce\textsf{SelfReduce} is induced by its random choices, not a distribution over its inputs.

    2. Show that if (A,B,C)(A^*,B^*,C^*) is not a Diffie-Hellman triple, then the output of SelfReduce(A,B,C)\textsf{SelfReduce}(A^*,B^*,C^*) is uniformly distributed over G3\G^3.

    3. The DDH assumption (definition 13.2.3) generates only a single triple in its lifetime. Prove that if the DDH assumption is true, then the following two libraries (which generate many independent triples) are indistinguishable:

      Lddh-real*G\lib{ddh-real*}^\G
      ddh.get()\subname{ddh.get}^*(\,):
      aZna \gets \Z_\nmod
      bZnb \gets \Z_\nmod
      return (ga,gb,gab)(g^a, g^b, g^{ab})
      \indist
      Lddh-rand*\lib{ddh-rand*}
      ddh.get()\subname{ddh.get}^*(\,):
      aZna \gets \Z_\nmod
      bZnb \gets \Z_\nmod
      cZnc \gets \Z_\nmod
      return (ga,gb,gc)(g^a, g^b, g^c)

      Your proof should invoke the standard DDH assumption only once!

    For part (a), reason about all cyclic group elements in terms of their discrete logs. For part (b), a non-Diffie-Hellman triple has the form (ga,gb,gab+d)(g^a, g^b, g^{ab+d}) where d0d\ne 0.

  7. Below is a variant of RSA-PSS which does not use a random oracle. Assume that the RSA modulus has kk bits, message M\ptxt has kλk - \secpar bits, and MR\ptxt \| R is interpreted as a kk-bit integer in the usual way.

    KeyGen=RSA.KeyGen\KeyGen = \RSA.\KeyGen
    Sign(SK=(n,d),M)\Sign( \sk=(\nmod,d), \ptxt ):
    R{0,1}λR \gets \bits^\secpar
    S:=(MR)d%nS := (\ptxt \| R)^d \pct \nmod
    return (R,S)(R,S)
    Verify(PK=(n,e),M,(R,S))\Verify( \pk=(\nmod,e), \ptxt, (R,S) ):
    if Sen(MR)S^e \equiv_\nmod (\ptxt \| R):
    return true\mytrue
    else: return false\myfalse

    Show that the scheme is not secure.

  8. h Exponentiation mod n\nmod can be sped up using the CRT method (section 15.4), if the factorization of n\nmod is known. In RSA-PSS signatures, it is the signer who knows this factorization. Using the CRT optimization, the signer will compute H(MR)d\ro(M\|R)^d mod p\pmod, then mod q\qmod, and finally reconstruct the result SS mod pq\pmod\qmod.

    Suppose a victim has signed a known message MM in this way, resulting in signature (R,S)(R,S). However, their CPU experienced a glitch while computing H(MR)d\ro(M\|R)^d mod p\pmod, resulting in an incorrect result. The CPU correctly computed H(MR)d\ro(M\|R)^d mod q\qmod and the CRT reconstruction (on the wrong values). As a result, the final result (R,S)(R,S) does not verify as a valid signature.

    Show how an adversary who knows MM, (R,S)(R,S), and the public key can factor n\nmod.

    SS satisfies:

    Se̸pH(MR);SeqH(MR).\begin{aligned} S^e \not\equiv_\pmod \ro(M\|R); \\ S^e \equiv_\qmod \ro(M\|R).\end{aligned}
  9. \star Usually it is not advisable to use the same key for different purposes. Despite that, it is safe to use RSA-KEM and RSA-PSS with the same RSA keypair; prove that the following two libraries are indistinguishable. RSA-KEM requires a random oracle with output {0,1}λ\bits^\secpar, while RSA-PSS requires one with output Zn\Z_\nmod. The following libraries implement two independent random oracles, with different ranges.

    (n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
    pk()\subname{pk}(\,):
    return (n,e)(\nmod,e)
    enc()\subname{enc}(\,):
    // Encaps(PK)\Encaps(\pk):
    RZnR \gets \Z_\nmod
    C:=Re%n\ctxt := R^e \pct \nmod
    M:=H2(R)\ptxt := \ro_2(R)
    return (C,M)(\ctxt, \ptxt)
    dec(C)\subname{dec}(\ctxt):
    // Decaps(SK,C)\Decaps(\sk, \ctxt):
    return H2(Cd%n)\ro_2(\ctxt^d \pct \nmod)
    sign(M)\subname{sign}(\ptxt):
    // Sign(SK,M)\Sign(\sk,\ptxt):
    R{0,1}λR \gets \bits^\secpar
    S:=H1(MR)d%nS := \ro_1(\ptxt\|R)^d \pct \nmod
    return (R,S)(R,S)
    ver(M,(R,S))\subname{ver}(\ptxt,(R,S)):
    // Verify(PK,M,(R,S))\Verify(\pk,\ptxt, (R,S)):
    Y:=H1(MR)Y := \ro_1(\ptxt\|R)
    return Y==Se%nY == S^e \pct \nmod
    H1(A)\ro_1(A):
    if H1[A]\rotable_1[A] undefined:
    H1[A]Zn\rotable_1[A] \gets \Z_\nmod
    return H1[A]\rotable_1[A]
    H2(A)\ro_2(A):
    if H2[A]\rotable_2[A] undefined:
    H2[A]{0,1}λ\rotable_2[A] \gets \bits^\secpar
    return H2[A]\rotable_2[A]
    \indist
    (n,e,d):=RSA.KeyGen()(\nmod,e,d) := \RSA.\KeyGen()
    pk()\subname{pk}(\,):
    return (n,e)(\nmod,e)
    enc()\subname{enc}(\,):
    CZn\ctxt \gets \Z_\nmod
    M{0,1}λ\ptxt \gets \bits^\secpar
    D[C]:=M\mathcal{D}[\ctxt] := \ptxt
    return (C,M)(\ctxt, \ptxt)
    dec(C)\subname{dec}(\ctxt):
    if D[C]\mathcal{D}[\ctxt] defined: return D[C]\mathcal{D}[\ctxt]
    // Decaps(SK,C)\Decaps(\sk, \ctxt):
    return H2(Cd%n)\ro_2(\ctxt^d \pct \nmod)
    sign(M)\subname{sign}(\ptxt):
    // Sign(SK,M)\Sign(\sk,\ptxt):
    R{0,1}λR \gets \bits^\secpar
    S:=H1(MR)d%nS := \ro_1(\ptxt\|R)^d \pct \nmod
    S:=S{(M,R,S)}\mathcal{S} := \mathcal{S} \cup \{ (\ptxt,R,S) \}
    return (R,S)(R,S)
    ver(M,(R,S))\subname{ver}(\ptxt,(R,S)):
    if (M,R,S)S(\ptxt,R,S) \in \mathcal{S}: return true\mytrue
    return false\myfalse
    H1(A)\ro_1(A):
    if H1[A]\rotable_1[A] undefined:
    H1[A]Zn\rotable_1[A] \gets \Z_\nmod
    return H1[A]\rotable_1[A]
    H2(A)\ro_2(A):
    if H2[A]\rotable_2[A] undefined:
    H2[A]{0,1}λ\rotable_2[A] \gets \bits^\secpar
    return H2[A]\rotable_2[A]
  10. Prove that if HH is a secure (salted) CRHF and Σ\Sigma is a secure signature scheme, then the following scheme is also a secure signature scheme:

    KeyGen()\KeyGen(\,):
    (PK,SK):=Σ.KeyGen()(\pk,\sk) := \Sigma.\KeyGen()
    T{0,1}λT \gets \bits^\secpar
    V:=H(T,PK)V := H(T,\pk)
    PK:=(V,T)\pk' := (V,T)
    SK:=(SK,PK,T)\sk' := (\sk,\pk,T)
    return (PK,SK)(\pk',\sk')
    Sign((SK,PK,T),M)\Sign\bigl((\sk,\pk,T),\ptxt\bigr):
    S:=Σ.Sign(SK,M)S := \Sigma.\Sign(\sk,\ptxt)
    return (S,PK)(S,\pk)
    Verify((V,T),M,(S,PK))\Verify\bigl( (V,T), \ptxt, (S,\pk) \bigr):
    return V==H(T,PK)V == H(T,\pk) and Σ.Verify(PK,M,S)\Sigma.\Verify(\pk,\ptxt,S)

    So if a signature scheme has very large public keys, they can be shrunk at the expense of making signatures longer.

  11. Suppose Σpke\Sigma_{\text{pke}} is a PKE scheme and Σsig\Sigma_{\text{sig}} is a signature scheme, and consider the following new PKE scheme:

    KeyGen=Σpke.KeyGen\KeyGen = \Sigma_{\text{pke}}.\KeyGen
    Enc(PK,M)\Enc(\pk,\ptxt):
    C:=Σpke.Enc(PK,M)\ctxt := \Sigma_{\text{pke}}.\Enc(\pk,\ptxt)
    (PK,SK):=Σsig.KeyGen()(\pk',\sk') := \Sigma_{\text{sig}}.\KeyGen()
    S:=Σ.Sign(SK,C)S := \Sigma.\Sign(\sk', \ctxt)
    return (C,PK,S)(\ctxt, \pk', S)
    Dec(SK,(C,PK,S))\Dec\bigl(\sk,(\ctxt,\pk',S)\bigr):
    if Σsig.Verify(PK,C,S)\Sigma_{\text{sig}}.\Verify(\pk', \ctxt, S):
    return Σpke.Dec(SK,C)\Sigma_{\text{pke}}.\Dec(\sk,\ctxt)
    else: return err\myerr

    Show that this scheme is not CCA-secure, even if Σpke\Sigma_{\text{pke}} is CPA-secure and Σsig\Sigma_{\text{sig}} is a secure digital signature scheme.

  12. This exercise explores whether we can convert a CPA-secure PKE into a CCA-secure one, by incorporating signatures similar to how MACs promote CPA security to CCA security for SKE.

    1. Let Σcpa\Sigma_{\text{cpa}} be a CPA-secure PKE with Σcpa.M={0,1}n\Sigma_{\text{cpa}}.\M = \bits^n. Prove that the following scheme is correct and is also CPA-secure:

      KeyGen=Σcpa.KeyGenM=Σcpa.M={0,1}nC=Σcpa.C×{0,1}n×{0,1}n\begin{aligned} \KeyGen &= \Sigma_{\text{cpa}}.\KeyGen \\ \M &= \Sigma_{\text{cpa}}.\M = \bits^n \\ \C &= \Sigma_{\text{cpa}}.\C \times \bits^n \times \bits^n \end{aligned}
      Enc(PK,M)\Enc(\pk,\ptxt):
      C:=Σcpa.Enc(PK,M)\ctxt := \Sigma_{\text{cpa}}.\Enc(\pk,\ptxt)
      return (C,1n,0n)(\ctxt, \bit1^n, \bit0^n)
      Dec(SK,(C,R,S))\Dec\bigl(\sk,(\ctxt,R,S)\bigr):
      M:=Σcpa.Dec(SK,C)\ptxt := \Sigma_{\text{cpa}}.\Dec(\sk,\ctxt)
      // &\& denotes bitwise-and
      return (M&R)S(\ptxt \mathbin{\&} R) \oplus S
    2. Now consider the following natural approach to authenticate ciphertexts using a signature: Encrypt the plaintext along with a verification key, and then sign the resulting ciphertext. More formally, let Σpke\Sigma_{\text{pke}} be a PKE scheme and Σsig\Sigma_{\text{sig}} be a signature scheme, and define the following PKE:

      KeyGen=Σpke.KeyGen\KeyGen = \Sigma_{\text{pke}}.\KeyGen
      Enc(PK,M)\Enc(\pk,\ptxt):
      (PK,SK):=Σsig.KeyGen()(\pk',\sk') := \Sigma_{\text{sig}}.\KeyGen()
      C:=Σpke.Enc(PK,MPK)\ctxt := \Sigma_{\text{pke}}.\Enc(\pk,\ptxt \| \hl{\pk'})
      S:=Σ.Sign(SK,C)S := \Sigma.\Sign(\sk', \ctxt)
      return (C,S)(\ctxt, S)
      Dec(SK,(C,PK,S))\Dec\bigl(\sk,(\ctxt,\pk',S)\bigr):
      MPK:=Σpke.Dec(SK,C)\ptxt \| \pk' := \Sigma_{\text{pke}}.\Dec(\sk,\ctxt)
      if Σsig.Verify(PK,C,S)\Sigma_{\text{sig}}.\Verify(\pk', \ctxt, S):
      return M\ptxt
      else: return err\myerr

      Show that the resulting scheme is not CCA-secure, when Σpke\Sigma_{\text{pke}} is the CPA-secure scheme from part (a), and Σsig\Sigma_{\text{sig}} is a secure digital signature scheme. Thus, this recipe does not suffice to upgrade an arbitrary CPA-secure PKE into a CCA-secure.

  13. Let Σ\Sigma be a signature scheme and define the new scheme Σ\Sigma^* below, which produces a signature chain:

    KeyGen=Σ.KeyGen\KeyGen = \Sigma.\KeyGen
    Sign(SK,M)\Sign(\sk,\ptxt):
    (PK,SK):=Σ.KeyGen()(\pk',\sk') := \Sigma.\KeyGen()
    S1:=Σ.Sign(SK,PK)S_1 := \Sigma.\Sign(\sk, \hl{\pk'})
    S2:=Σ.Sign(SK,M)S_2 := \Sigma.\Sign(\hl{\sk'}, \ptxt)
    return (PK,S1,S2)(\pk', S_1, S_2)
    Verify(PK,M,(PK,S1,S2))\Verify\bigl(\pk,\ptxt,(\pk',S_1,S_2)\bigr):
    if Σ.Verify(PK,PK,S1)\Sigma.\Verify(\pk, \pk', S_1)
    and Σ.Verify(PK,M,S2)\Sigma.\Verify(\pk',\ptxt,S_2):
    return true\mytrue
    else: return false\myfalse

    Prove that Σ\Sigma^* is a secure digital signature scheme, if Σ\Sigma is.

Chapter Notes

Diffie and Hellman were the first to conceive of digital signatures [83]. The standard modern security definition for signatures is due to Goldwasser, Micali, and Rivest [116].

The signature scheme in exercise 16.3 is based on the Winternitz signature scheme, attributed to Robert Winternitz by Merkle [160].

Construction 16.2.2 is a simplified variant of the PSS construction proposed by Bellare and Rogaway [28]. The “real” PSS construction uses a hash function with range {0,1}λ\bits^\secpar, rather than Zn\Z_\nmod as in construction 16.2.2, and then cleverly encodes the randomness RR into the bits of the Zn\Z_\nmod-element itself, thus saving on the additional cost of transmitting RR as part of the signature. PSS itself is a variant of full-domain hash (FDH) signature scheme, which is essentially construction 16.2.2 without the signing randomness RR. FDH is also secure, although its security proof is more involved, and provides worse concrete security; see Coron [72,73].

  1. Previous Chapter15. RSA
  2. Next Chapter17. Encrypted Messaging and Ratcheting