
Zero Knowledge Proofs: An illustrated primer - sohkamyung
http://blog.cryptographyengineering.com/2014/11/zero-knowledge-proofs-illustrated-primer.html
======
nullc
One of the things that I've been frustrated by existing ZKP primers while
educating new Bitcoin engineers on the tools in this space is that they don't
form any intuition as to how the you can prove something other than some very
narrow (usually seemingly toy-like) problem.

Even if the problem is NP-complete, the transformation from something you'd
actually like to to be able to prove to graph colouring or SAT or cycles, is
not obvious.

So, I described a novel ZKP for boolean circuits as a teaching tool:

[https://people.xiph.org/~greg/simple_verifyable_execution.tx...](https://people.xiph.org/~greg/simple_verifyable_execution.txt)

It's explicitly not very efficient (since I eschewed all tools from asymmetric
cryptography which could have been used to make it efficient), and it may well
be not very secure (it's not peer reviewed), but the people I've shown it to
have found it to be pretty useful in terms of expanding their perspective and
giving them some intuitive confidence that a zero-knowledge proof of the
output of an arbitrary program on secret inputs is possible.

Some people here may find it interesting for the same reasons.

------
mijoharas
Can someone help clarify a point about the zero-knowledge part for me?

As far as I can tell calculation is performed (which I would argue is
equivalent to knowledge being created) in the process of first checking the
value and then rewinding the program to a previous state. Consider the
following program (pseudocode):

    
    
        start: int value = rand(10) //take a random number between one and 10
        if (value == 2) {return "success"} //here we are checking if our "answer" is correct
        else {goto: start} //rewinding time and trying again
    
    

I would argue that this program calculates the number two, and is functionally
equivalent to checking a value and is identical to the scheme outlined in this
article. Isn't a calculation a creation of information?

If the program was changed so that the if block had (value == 2 `times` 2) I
would argue that the program had calculated 2 times 2 (albeit in a stupid way)
and thus information had been created.

Can someone point out the flaws in my reasoning? (Obviously there are some,
I'm just being too obtuse to see them at the moment)

(EDITS: code syntax and unable to use asterisk as times in the comment so put
`times` in instead, hope it's clear

EDIT #2: just realised I said "information is created" which is obviously
incorrect as information is conserved. I still think calculation is being
performed. I would argue it is the same as performing a random search on the
search space. so the information is provided when we check the value

EDIT #3: expanding upon the previous point, assuming we control the time
(which we model as the scientist going back in time in the given example)
surely in the Verifiers timeline it seems that there is no computation
occuring, but in the scientists timeline (assuming the scientist must go back
in time and set pick a new set of random colorings) computation is occuring
and thus we break our tenet. )

~~~
sysk
> and is identical to the scheme outlined in this article

Would you care to elaborate?

In your example, the Verifier (line 2) already has a solution to the problem
(the number 2). Therefore the Solver (line 1) can't possibly give more
information about the _solution_.

In the article's example (graph colouring), the Verifier doesn't know the
solution to the problem and just verifies a small part of the solution
provided by the Solver (2 vertex each time). The Solver doesn't leak any
information about its solution at each iteration since the colours are
randomised each time.

> I still think calculation is being performed

Yes, but this is the whole point of ZKPs. It's called Zero Knowledge, not Zero
Computation.

> I would argue it is the same as performing a random search on the search
> space

I agree but the fatal flaw in your reasoning is that the Verifier already
knows the solution and therefore doesn't learn "new" information. The Solver
is just wasting CPU cycles.

Disclaimer: I just read the article and have no prior knowledge of ZKPs. This
is just my basic understanding.

------
GotAnyMegadeth
In his example Google could colour each vertex a completely different colour.
That way when you revealed any random two it would always look like that had
done it correctly. I suppose to get round this you have Google tell you which
three colours they are using in advance.

~~~
VLM
This is a good time to point out that the solution to GOOG rainbow color
cheating isn't to reveal 4 instead of 2 and make sure only 3 colors are seen,
because then GOOG wouldn't have to get paid because you'd end up with a long
enough list of known pairs to not need their services, because each trial run
would leak exactly one pair (assuming a trial didn't indicate GOOG cheating,
obviously). This is also why GOOG has to shuffle between each and every
sample.

Its interesting to think about acceptable losses in zero knowledge... If the
GOOG had the computing power to solve a problem 1000x bigger than you can
solve, they can leak down to only maybe 10x and it'll still economically make
sense for you to play fair and pay them.

Another fun mental exercise is to analyze the info leakage rate and truth
belief rate of allowing GOOG to falsify 1%, 1/3, 1/2 of all colors.

~~~
thaumasiotes
Actually, it's not necessary to build a list of known pairs that you
eventually link into a solution; if a challenge reveals at least three
vertices you can identify each vertex unambiguously one by one. (That's
because there are only three colors, so as long as you include the same two
vertices v1, v2 in every challenge, you can classify every vertex into [color
of v1], [color of v2], or [color 3] as soon as you see it.) A list of pairs
only becomes necessary when there are more than three colors allowed.

------
gavinpc
Related, from two months ago

[https://news.ycombinator.com/item?id=8349721](https://news.ycombinator.com/item?id=8349721)

------
cialowicz
In the example, the vertices colors for a graph edge are requested, but how
can one trust that those colors aren't being generated on-the-fly?
Effectively, how can I trust that the "warehouse" isn't cheating me?

~~~
eemax
The OP glosses over this a bit, but it's mentioned in the footnotes: the
"hats" represent a commitment scheme, which is a way for the prover commit to
a specific color assignment, before revealing what that assignment actually
is.

When the verifying party chooses the two vertices he wants to see, the prover
can reveal only those two, and the verifier actually has two things to check:

1) the colors revealed are actually two different colors (otherwise the
purported solution obviously isn't correct)

2) the colors revealed are consistent with the prover's overall commitment.
(in other words, that the prover didn't change his answer "on-the-fly")

------
nly
> In the next post I'll talk about some of those ...[snip]... I'll also talk
> about why I dislike SRP so much.

I'm going to guess this is going to be:

* Rocky development process (~6 versions, removing attack vectors with each release). This however isn't exclusive to SRP: EKE flavours have also suffered from problems[0]

* Outdated constructs (e.g. the RFC for TLS-SRP still recommends using salted SHA1 for password hashing, so realistically still relies upon strong database security. Fortunately, this is under client control regardless of what the document actually says)

* Lack of a formal security proof (although it's generalised and dealt with in quite a few papers alongside other protocols).

* Perhaps the lack of an EC formation, although I believe you can build one with a few modifications. (Yongge Wang drafted one in 2001[5] that looks to me, as an amateur, to be sound. The critical modification is no more crazy than the freaky ECDSA construct we rely upon today, afaict, simply because more elegant Schnorr constructs were covered by patents)

I'm not sure why Matt considers the protocol to be complex[1] or crazy[2]. It
seems to be a pretty straightforward DH protocol, with a couple of interesting
parameters: a commitment by each party to the password verifier, each closing
off a different attack (one where a client could otherwise auth knowing just
the verifier but not the password, and the other to prevent an impersonating
server from gleaning enough to do an offline dictionary attack) There are a
lot of subtleties in all off the PAKEy protocols I've read about, not just
SRP, one good example can be had here[3], which talks about the intricacies of
picking commitment constructs.

Atm I agree with Bram Cohens sentiment on this one[4]. If not SRP, then
_something_. I'm looking forward to Matts thoughts in the follow-up. Perhaps
he has a more modern starting point in mind[6]

I'd like to see the prevalence of full-on PGP-esque signing and HSMs in every
device, but we can't continue to do nothing with passwords. The two uses of
password authentication that everyday people rely on the most: password
authentication on the web, and WPA2-PSK, are both _terrible_ compared to the
PAKEs we already have. Worse, the lack of better things is spawning absolute
garbage like third-party login.

I like SRP. While I'm not as familiar with more current IETF RFCs, like
Dragonfly[7] and Pwd[8], I believe from cursory looks that they fail to fall
in to the "augmented" PAKE category, which means if a server is compromised
the infiltrator can use the knowledge they've gained from the database
immediately, and without any further work.

[0] [http://www.jablon.org/jab97.pdf](http://www.jablon.org/jab97.pdf)

[1]
[https://twitter.com/matthew_d_green/status/28874317682562252...](https://twitter.com/matthew_d_green/status/288743176825622529)

[2]
[https://twitter.com/matthew_d_green/status/28874165135724544...](https://twitter.com/matthew_d_green/status/288741651357245440)

[3]
[http://coitweb.uncc.edu/~yonwang/papers/TCSsrp5.pdf](http://coitweb.uncc.edu/~yonwang/papers/TCSsrp5.pdf)

[4]
[https://twitter.com/bramcohen/status/330423520062476288](https://twitter.com/bramcohen/status/330423520062476288)

[5]
[http://grouper.ieee.org/groups/1363/passwdPK/submissions/p13...](http://grouper.ieee.org/groups/1363/passwdPK/submissions/p1363ecsrp.pdf)

[6]
[https://twitter.com/matthew_d_green/status/34483169358632140...](https://twitter.com/matthew_d_green/status/344831693586321409)

[7] [https://datatracker.ietf.org/doc/draft-irtf-cfrg-
dragonfly/?...](https://datatracker.ietf.org/doc/draft-irtf-cfrg-
dragonfly/?include_text=1)

[8] [https://tools.ietf.org/html/draft-harkins-tls-
pwd-03](https://tools.ietf.org/html/draft-harkins-tls-pwd-03)

~~~
nullc
> using salted SHA1 for password hashing

Anything else would be better there.

But right now there is a huge multiplicity of trendy password strengthening
functions (see also: [https://password-hashing.net/](https://password-
hashing.net/)). I'd worry that doing something better than sha1 might still
not be great because of a lack of clarity of choices there.

E.g. Some of the most popular (e.g. scrypt) are potentially ill-advised for
some fairly overt reasons, like data-dependent timing that potentially leaks
information about your password (in what should other wise be a ZKP thats
potentially pretty bad!), or potentially problematic in subtle ways. (E.g. is
memory hardness really desirable? the cost analysis ignore operating costs.
But for compute bound silicon on 28nm built in quantity, power costs more than
die area after only a couple months of operation. Requiring lots of upfront
costs in gate area means that attackers can amortize their costs over many
attacks. Meanwhile, most of the user's computer is siting idle and not
contributing to expanding the amount of work an attacker must do.

> * Perhaps the lack of an EC formation,

Yea, well ... SRP sends a fair amount of data and isn't terribly fast for
reasonably secure parameters. If someone is unconvinced about the value of
this crypto-security-whatever having them send kilobytes of data over the
regular password they were going to send may be the straw the breaks the
camels back.

Also, if your cryptographic stack is otherwise all ECC having to have a
separate bignum implementation for SRP wouldn't be very welcome. But OTOH, the
latest in trend curve design uses curves with non-prime order, and at least
some of the PAKE schemes I've seen lose their ZK property when there is a
cofactor. Bleh.

~~~
nly
> Anything else would be better there.

Yeah, I can't fathom how that spec got drafted with SHA1. I guess as network
guys they just didn't care too much about verifier storage, which is insane,
because it's clearly the weakest point of any password based scheme where
boxes are, in all practicality, going to be off-the-shelf hardware sat on the
open Internet. I think the other proposals like Dragonfly and TLS-PWD repeat
this mistake also except, not being "augmented", they're even worse.

> right now there is a huge multiplicity of trendy password strengthening
> functions

How's that going? Is there anything amongst the PHC candidates looking like
it'll 'win'? It's gone very silent.

> Some of the most popular (e.g. scrypt) are potentially ill-advised for some
> fairly overt reasons, like data-dependent timing that potentially leaks
> information about your password

Afaict this probably isn't _too_ much of a problem for a client-server PAKE?
The password is only hashed on the client/users, probably somewhat noisy and
unique, machine. You're already talking about pretty sophisticated and
targeted attack that's hard to pull off on a repeated basis. I know that's not
a "sound" crypto argument, but you can't easily make a user enter their
password 10,000 times for example. The server will probably need to apply a
regular hash the password _verifier_ for commitment purposes, but it's
typically mixed in with session nonces, and already hardened, so couldn't be
any worse than a db dump from SQL injection even if successful. I personally
don't see a hole that doesn't exist with current server-side hashing
practices. Thoughts?

> some of the PAKE schemes I've seen lose their ZK property when there is a
> cofactor

Hmm, interesting. Any information on this?

~~~
nullc
> Yeah, I can't fathom how that spec got drafted with SHA1.

I'm not sure, PBKDF2 existed then... though computationally expensive KDFs for
passwords have become more popular over time. And grinding the server for SRP
isn't totally cheap.

> How's that going? Is there anything amongst the PHC candidates looking like
> it'll 'win'? It's gone very silent.

Been pretty silent from what I've seen but the schedule gave a fair amount of
time for review... though I'm not sure how much review various proposals are
getting, since this is a domain with basically infinite shed-painting
potential (as my own comments here go!), makes it almost feel pointless to
review.

> Afaict this probably isn't too much of a problem for a client-server PAKE?

I'm not sure. It would be an unfortunate result if you sought out to make it
more secure, and maybe its less secure. (E.g. server database never leaks, but
lots of opportunities for timing attacks show up)

> The password is only hashed on the client/users, probably somewhat noisy and
> unique, machine. You're already talking about pretty sophisticated and
> targeted attack that's hard to pull off on a repeated basis. I know that's
> not a "sound" crypto argument, but you can't easily make a user enter their
> password 10,000 times for example.

10,000 probably isn't needed though, since extracting a few bits may let you
reasonably grind out the rest against the server only; if you make pessimal
(read: reasonable) assumptions about how much entropy users actually have in
their passwords.

Consider an attack where the attacker code is running in the background (say
in another browser tab/nacl) performing cache timing while the user logs it.
It's a sophisticated attack, but it could potentially extract quite a few
bits. It may be a somewhat complex attack, but a simple conventional hash
PKKDF2 would be invulnerable to it.

Yea, I don't see any concern on the server. Server's commitment shouldn't be
using an intentionally expensive hash, and normal cryptographic hashes in wide
use are constant time.

> Hmm, interesting. Any information on this?

Will look when awake. But the result was something like checking which
subgroup a point was in leaking log2(cofactor) bits about the secret. The
normal way of avoiding this by multiplying all your values by the cofactor
isn't readily available when you're doing some ugly trick of constructing
points with no known discrete log from a hash.

~~~
nly
> the result was something like checking which subgroup a point was in leaking
> log2(cofactor) bits about the secret. The normal way of avoiding this by
> multiplying all your values by the cofactor isn't readily available when
> you're doing some ugly trick of constructing points with no known discrete
> log from a hash.

Ah, a partition attack. Could you fix this with more ugly by just iterating
the hashing/munging process until your commitment was in a predetermined
subgroup? I'm not at all familiar with EC subgroup theory, but the EC-SRP
scheme proposed already does some deterministic munging to select the
y-coordinate. Of course, even if you can do this, you're open to another
timing side-channel.

~~~
pbsd
I don't see what the problem is, exactly. If you have a secure hash function
taking some string into a point of elliptic curve E, multiplying said point by
the cofactor is also a secure hash function into the relevant subgroup of E.
See §6.1 of [1].

[1] [https://eprint.iacr.org/2009/340](https://eprint.iacr.org/2009/340)

~~~
nly
Neat. It's also pointed out in Icarts paper[0] that the naive 'try and
increment' algorithm, which I believe is utilised in Yongge Wangs draft EC-SRP
proposal I linked up above, is vulnerable to timing attacks. Oops

Interestingly, both Dragonfly and TLS-SRP describe a 'Hunting and Pecking'
algorithm to paper over this problem. Perhaps Icarts solution would be more
elegant

[0]
[https://www.iacr.org/archive/crypto2009/56770300/56770300.pd...](https://www.iacr.org/archive/crypto2009/56770300/56770300.pdf)

~~~
pbsd
Hunting-and-pecking is essentially the same algorithm as try-and-increment,
where instead of incrementing an x-coordinate on failure one picks another x
(pseudo-)randomly. Therefore both are susceptible to the same kind of timing
attacks. Dragonfly went to some pains to try to make the process side-channel-
free, but it looks ugly as sin, and it's still unclear whether it is actually
secure (cf [1]).

[1] [https://www.ietf.org/mail-
archive/web/cfrg/current/msg03537....](https://www.ietf.org/mail-
archive/web/cfrg/current/msg03537.html)

~~~
nly
Thanks for that. The tone of Dan Harkins reply is fun. There's clearly a lot
of ego in crypto ;) Not sure I see the point in balanced PAKE myself. If you
turn weak passwords in to preshared keys then why not just use strong
preshared keys to begin with and trust in the bits? Worrying about parameter
binding to the verifier seems irrelevant to EC as well.

~~~
pbsd
I'm probably not the best person to argue in favor of one flavor or another of
PAKE, but balanced schemes give you forward security whereas a naive
preshared-key scheme does not.

------
thaumasiotes
I don't quite follow this description:

> Ultimately what we get is the following theorem. If there exists any
> Verifier computer program that successfully extracts information by
> interactively running this protocol with some Prover, then we can simply use
> the rewinding trick on that program to commit to a random solution, then
> 'trick' the Verifier by rewinding its execution whenever we can't answer its
> challenge correctly. The same logic holds as we gave above: if such a
> Verifier succeeds in extracting information after running the real protocol,
> then it should be able to extract the same amount of information from the
> simulated, rewinding-based protocol. But since there's no information going
> into the simulated protocol, there's no information to extract. Thus the
> information the Verifier can extract must always be zero.

This seems to identify a way of showing that some protocol is zero-knowledge.
But, as I read the paragraph, the requirements aren't strict enough.

Imagine a closely-related protocol, where I get to challenge two edges at once
and the four (or three, I guess) incident vertices are revealed. Obviously, I
can successfully extract the full 3-coloring through repeated runs of this
protocol (revealing four vertices when there are only three legal colors means
I can identify which vertices are the same color as which other vertices;
given a bounded number of challenges, I can get them all). Also obviously, you
can use a time machine to pass any particular challenge in this protocol
almost as easily as you can use one to pass the less leaky one-edge
challenges.

But I don't see what's making the difference, or how the "theorem" helps me
distinguish the protocols. The OP identifies three properties that a zero-
knowledge protocol must have: 1, if the prover has a solution, I become
confident that it's real; 2, if the prover doesn't have a solution, I become
confident that they don't; and 3, zero-knowledgeness.

So, if I'm an honest verifier with no memory (except for previous challenge
pass/fail results), the two-edge challenge protocol has the first two
properties, just like the one-edge protocol: I'll quickly gain confidence that
a genuine solution is real, and I'll quickly discover that a sham solution is
false. If there's a time machine involved, I'll quickly become convinced that
the prover has a solution even though they don't, because it's easy to fake
three or four vertices being properly colored.

If I'm a nefarious verifier with a memory, I can use the extra information
that leaks from the two-edge protocol to recover the full solution if one is
given, and I can also use it to eventually discover that a nefarious prover is
using a time machine to lie to me (when my own illicit copy of the graph-
coloring hits a contradiction). The two-edge protocol doesn't fail the
completeness or soundness tests. So it must fail the zero-knowledgeness test.
How can I tell that? Does the paragraph I quoted indicate _how_ the two-edge
protocol fails zero-knowledgeness?

~~~
sysk
I agree, the quoted paragraph is not clear. It seems to me that the Verifier
could not be tricked even using the rewinding trick if it was allowed to use
its memory (internal copy of the graph-coloring).

~~~
thaumasiotes
Well, in the protocol described in the OP, the verifier can't build an
internal copy of the graph-coloring, because knowing that two adjacent
vertices in the graph are two different colors doesn't help anything; that
much is required of any solution. In the protocol I describe, the verifier can
do that, because revealing more than two vertices simultaneously leaks
information that isn't necessarily true of all possible solutions (at least,
it can; if three vertices which connect in a triangle turn out to be three
different colors, you haven't learned anything because any valid solution will
have that property).

The problem I'm having is that I agree that the one-edge protocol is zero-
knowledge (and that a verifier could be tricked indefinitely by a prover with
a time machine), and obviously the two-edge protocol isn't zero-knowledge
(and, in probably-related-but-I'm-not-sure news), a verifier using the two-
edge protocol _cannot_ be tricked indefinitely by a time machine). I can tell
that, but I tell it by looking within my soul and thinking "yes, there is no
information leak when one edge is revealed, but there is a leak when two edges
are revealed". That's not a reliable method; I'd like to know how to prove
that information does not leak through a protocol, and I don't see that
anywhere in the OP.

~~~
matthewdgreen
Roughly speaking, the question here is: can you simulate a multi-edge
protocol. That is, can you achieve the following properties using rewinding:

1\. The 'fake Prover' simulating the protocol has no knowledge of an actual
graph coloring. 2\. From the Verifier's PoV, the distribution of the simulated
(rewinding-based & fake) protocol transcript is identical to that of a real
protocol run where the Prover really does a solution. 3\. The simulation still
requires only time polynomial in the problem instance (when you include all
the rewinding trips).

I think if you follow this through you'll find that simulating a multi-edge
protocol that 'looks like' a real transcript is highly challenging.

The reason for condition (3) is to rule out an obvious hack wherein the
simulation takes so long that the 'fake Prover' can simply find solve the
problem (e.g., by finding a graph coloring in an exponential number of time
steps).

~~~
thaumasiotes
As I see it, if the transcript consists of a record like the following:

    
    
        Trial 1: PASS
        Trial 2: PASS
        Trial 3: PASS
        Trial 4: PASS
    

etc. etc, then simulating a two-edge protocol is, while more time-consuming
than simulating a one-edge protocol, still pretty easy. If the record looks
like

    
    
        Trial 1: PASS (v1 red -- v2 green, v3 green -- v4 blue)
        Trial 2: PASS (v1 blue -- v2 red, v7 blue -- v9 red)
        Trial 3: PASS (v1 green -- v2 red, v7 green -- v4 red)
    

then after Trial 3 you can tell that the prover is cheating. The fake trials
seem to achieve your properties (1) and (3). I guess they violate #2? What is
the "distribution" of a simulated transcript?

