This is based on Josh’s document, Wikipedia articles, and a few other articles.
I’ve tried to structure this document so that in can be read all the way through like a story. You can also skip to the last section which says everything you need to check for an election, and it should reference the relevent parts of the document, so you can hop around there like a tree.
Our goal is to use cryptography to allow any voter to check that their vote was accurately included in the final tally, without them having to trust the people running the election. This doesn’t encompass everything we would want to be able to guarantee about an election. For example, this doesn’t ensure that the people running the election didn’t create a bunch of well-formed but fake ballots.
One simple way to do that is to publish everone’s votes. We don’t want to do that, because it is a violation of people’s privacy, and because it allows for voter manipulation schemes. For example, someone can pay you to vote a certain way. Even if votes aren’t associated with particular voters, ballots in the US include enough unimportant races to allow people to encode unique identifiers in the selections of those unimportant races. Therefore we want to keep ballots private.
One good way to do this is homomorphic encryption. A homomorphism is
mapping between structures that preserves their structures, so
homomorphic encryption allows us to perform operations on the
encrypted messages that correspond to operations on the cleartext. For
example, if we say that
Using homomorphic encryption, here are the steps in the process of casting a vote:
- The voter submits their selections to a machine, which encrypts it and records it.
- The encrypted votes are gathered.
- The encrypted votes are tallied.
- The encrypted tally is decrypted.
Each of those 4 steps can be independently verified to have been completed without tampering.
ElGamal encryption is based on the difficulty of the discrete log
problem: take some group
For ElGamal encryption, we work in the multiplicative group of
integers modulo
We also need a generator
What does it mean to encrypt something with ElGamal or Exponential ElGamal encryption, and why does the above homomorphic property hold?
Now we have an asymmetric encryption scheme. First we have to generate some a keypair: TODO is it p-1?
- Choose some random element
$s ∈ G$ ; this will be your private key. - Let
$h = g^s$ . This will be your public key. Since the discrete log problem is hard, no one can figure out your private key from your public key, which is good. - Publish your public key
$h$ far and wide.
Suppose your friend wants to send you a secret message
- Choose some random element
$r ∈ G$ . You can think of this as a one-time private key. - Let
$k = g^r$ . You can think of this as your one-time public key. - Publish
$(k, m ⋅ h^r)$ . I’ll refer to the first element of the pair as the one-time public key, the second element as the ciphertext, and the whole pair as the encrypted message.This works well, because $h^r = grs$ acts as a shared secret between you and your friend, because $$ grs = h^r = k^s $$ You can know it by knowing your public key
$h = g^s$ and the one-time private key$r$ , like your friend does, or by knowing the one-time public key$k = g^r$ and your private key$s$ , as you do.If you know that shared secret $grs$, you can divide the ciphertext by it to produce the cleartext \(m\)!
But what about that nice homomorphic property? To get that, we make one small tweak: instead of forming the ciphertext as $m ⋅ grs$ where $grs$ is that shared secret, we use $g^m ⋅ grs$. Then we can multiply our encrypted messages, and by the magic of exponentiation identities, the homomorphic property falls out!
\begin{aligned}
& Er_1(m_1) ⋅ Er_2(m_2)
={}& (gr_1, gm_1 hr_1) ⋅ (gr_2, gm_2 hr_2) \
={}& (gr_1 ⋅ gr_2, gm_1 hr_1 ⋅ gm_2 hr_2) \
={}& (gr_1 + r_2, gm_1 + m_2 hr_1 + r_2) \
={}& Er_1 + r_2(m_1 + m_2)
\end{aligned}
In the above, we’ve shown the randomly generated one-time pritevate keys
as subscripts on the encryption function
When I publish a public key, I may want to convince somebody that I actually possess the seret key associated with that public key. One way to do this is to show them the secret key, but that kind of defeats the point. Instead, we can use a Zero-Knowledge Proof to convince them without showing them the private key.
In this case, we use a Schnorr Proof. You can think of it as an interactionb between a prover (the guy with the private key) and a verifier (the guy who wants to know the prover has the private key).
- The prover generates a random exponent
$0 < r < p - 1$ . This is kind of like another one-time private key for the purposes of the proof. The prover commits to that one-time private key by publishing the one-time public key$k = g^r$ . - The verifier gives the prover a random challenge
$c$ such that$0 < c < p - 1$ . - The prover responds to the challenge with
$u = r + cs \bmod p - 1$ , where$s$ is the secret key they’re trying to show that they know. - The verifier accepts if
$g^u = k ⋅ h^c$
This works basically by forcing the prover to synthesize a new private
key that incorporates
We can convert this from an interactive zero-knowledge proof to a
non-interactive zero-knowledge proof. Intuitively, all we need from
them is the challenge
- The prover generates a random exponent
$0 < r < p - 1$ . publishing the one-time public key$k = g^r$ . - The verifier gives the prover a random challenge
$c$ such that$0 < c < p - 1$ . - The prover responds to the challenge with
$u = r + cs \bmod p - 1$ , where$s$ is the secret key they’re trying to show that they know. - The verifier accepts if
$g^u = k ⋅ h^c$
We will encode the selections for a given contest as bit-vectors so that homomorphically tallying the encrypted selections produces an encrypted tally for each option in the contest.
We also want to be able to check that each ballot is well-formed
without decrypting it. That means that each selection is a one or a
zero, and that the number of selected options for each contest is no
more than the limit
The basis for both of these is a Chaum-Pedersen proof, which is used to show that a given ElGamal message is actually an encryption of zero.
For a Chaum-Pedersen Proof, we have some ElGamal encrypted message
We can do this basically by extending the Schnorr protocol to the ciphertext (the second part of the message) as well as the one-time public key, because the Schnorr protocol will only work on the ciphertext if it is zero. That might not make sense right now, but it will when you see it:
- Like in the Schnorr Proof, the prover will generate a random
exponent
$t$ . They committ to this randomness by publishing not only$g^t$ as they would in a Schnorr proof, but also$h^t$ . You can think of this also as an encryption of zero, because were we encrypting zero using$t$ as the one-time private key, we would publish$(g^t, g^0 ⋅ h^t)$ . So, we publish the pair$(α, β) = (g^t, h^t)$ . - The verifier gives us a random challenge
$c$ . - We response with
$u = t + cr$ like we would if this were a Schnorr proof for posession of$r$ . - The verifier accepts if
$g^u = α ⋅ a^c$ , like they would for a Schnorr proof, but they also check that$h^u = β ⋅ b^c$ .
The reason this works is that the ciphertexts } \beta \cdot b^c \\
h^{t + cr} &\overset{?}{
} (gm_2 ⋅ h^t) ⋅ (gm_1 ⋅ h^t)^c
ht + cr &\overset{?}{=} gm_1 + c m_2 ⋅ ht + cr \
\end{aligned}
The $m$s get in the way! It only works if both $m$s are zero. That’s
why we encrypt one zero message in the commitment, and the other
message is the message we are trying to show encrypts zero.
We can use a Chaum-Pedersen proof to show that two messages
Suppose
the first message uses one-time private key
&= (gr_1 - r_2, gm-m ⋅ cr_1 - r_2) \
&= (gr_1 - r_2, cr_1 - r_2)
\end{aligned}
Now we can produce a Chaum-Pedersen proof that the resulting message
is encodes zero.
So all together, given a public key
- Choose a random exponent
$t$ as the one-use private key. Publish$(α, β) = (g^t, h^t)$ . - Get a random challenge
$c$ (from a verifier or a hash function). - Respond with
$u = t + cr$ . - Verifier accepts if
$g^u = α ⋅ \left(\frac{a_1}{a_2}\right)^c$ and if$h^u = β ⋅ \left(\frac{b_2}{b_1}\right)^c$ .As an optimization, the verifier can avoid modular division by multiplying through the denominator, and check instead
$a_2^c ⋅ g^u = α ⋅ a_1^c$ and$b_2^c ⋅ h^u = β ⋅ b_2^c$ .
We want to show that each selection is an encryption of a one or and encryption of a zero. The trick that we’ll use is we’ll start with an actual proof that the selection is a one or a zero, depending on its value. Then we’ll fake a proof that it’s the value that it’s not in a way that a verifier can’t figure out which one is fake.
In general, we’re going to assume that we have an ElGamal message
We need to have an encrypted ElGamal message for $m\text{real}$ and
$m\text{fake}$ in order to create a Chaum-Pedersen proof, but the
verifier already knows the values of both. So we can make our lives a
lot easier and use
The basic idea is that if we fix a fake challenge
$c\text{fake}$ and fake response $u\text{fake}$ in advance, then
we can construct a fake commitment $(α\text{fake},
β\text{fake})$ to satisfy the equations:
\begin{aligned}
gu_{\text{fake}} = α\text{fake} ⋅
\left(\frac{a}{a\text{fake}}\right)c_{\text{fake}}
&\implies
α\text{fake}
= gu_{\text{fake}} ⋅ \left(\frac{a\text{fake}}{a}\right)c_{\text{fake}}
= \frac{gu_{\text{fake}}}{ac_{\text{fake}}}
hu_{\text{fake}} = β\text{fake} ⋅
\left(\frac{b}{b\text{fake}}\right)c_{\text{fake}}
&\implies
β\text{fake}
= hu_{\text{fake}} ⋅ \left(\frac{b\text{fake}}{b}\right)c_{\text{fake}}
= hu_{\text{fake}} ⋅ \left(\frac{gm_{\text{fake}}}{b}\right)c_{\text{fake}}
\end{aligned}
- Choose a random exponent
$t$ and publish $(α\text{real}, β\text{real}) = (g^t, h^t)$. - Choose a random challenge $c\text{fake}$ and response $u\text{fake}$. Publish $(α\text{fake}, β\text{fake}) = \left( \frac{gu_{\text{fake}}}{ac_{\text{fake}}}, hu_{\text{fake}} ⋅ \left(\frac{gm_{\text{fake}}}{b}\right)c_{\text{fake}} \right)$.
- Generate a challenge
$c$ by hashing relevant parameters in addition to$a$ ,$b$ , $α\text{real}$, $β\text{real}$, $α\text{fake}$, and $β\text{fake}$. - Get the challenge for the real proof $c\text{real} = c - c\text{fake} \bmod p - 1$.
- Complete the real proof as usual, by publishing $u\text{real} =
t + c\text{real} r$, where
$r$ is the one-use private key used to encode the message$(a, b)$ . - The verifier can check both the proofs as usual. In addition they can calculate $c = c\text{real} + c\text{fake}$ and check that it was calculated honestly using the hash function.
We can also use Chaum-Pedersen proofs to show that the process of decryption has been carried out correctly.
When we tally up all the votes, we end up with an ElGamal message
We would like to verify that the \(M_i\)s have been computed correctly
without revealing the \(s_i\)s. If we squint, $M_i = As_i$ is an
encryption of zero where
Luckily, as long as we’re consistent about flipping everything, we can
still use our Chaum-Pedersen proofs to prove that $M_i = As_i$ is
correcty by showing that
So our procedure is pretty much a usual Chaum-Pedersen proof, where
the message
- Generate a random exponent
$t$ , and commit to it by publishing$(α, β) = (g^t, A^t)$ . Remember,$A$ is playing the role of permanent public key even though it’s actually a big one-time public key. - Get a random challenge
$c$ . - Respond with
$u = t + c s_i$ . - The verifier accepts if (just like usual) if
$g^u = α ⋅ a^c = α ⋅ h_i^c$ and$A_u = β ⋅ b^c = β ⋅ M_i^c$ , and also the hash checks out.
[fn:1] Google “Swiss post voting attack” or ask Joey