Try   HackMD

Publicly verifiable multi-user public key encryption

Introduction

Public key encryption (PKE) is a standard tool used in many protocols with two parties sender and receiver. Sender uses receiver's public key to encrypt a secret message and receiver uses her private key to decrypt it. In modern (decentralized) protocols there's a third party verifier. Verifier acts as an arbiter, she verifies that both parties (sender and receiver) follow the protocol correctly. When there's a need for privacy a PKE scheme does not offer the verifier to do her job to get access to the encrypted message privacy property must be sacrificed.

To overcome this issue there's publicly verifiable public key encryption (PVPKE). In such a scheme the sender encrypts a message and proves certain useful properties about it such that the verifier can verify the proof (ie. that the properties do actually hold for the encrypted message without decrypting it) and the receiver can decrypt the message as usual.

Some useful properties about encrypted text might include the following:

  • proof of decryptability, ie. that the receiver can indeed decrypt the message (and not claim that she can't, without revealing her private decryption key);
  • proof of correct encryption, ie. that the sender has encrypted a valid message (and not some garbage).

Depending on the underlying platform (message space, key space) and provable properties there can be many approaches. In a general case encryption algorithm is represented as a circuit, then a proof system is used to construct a (non-interactive) proof for that circuit.

In this post we present an extension to multi-receiver ElGamal PKE extended with Bulletproofs-based proof of correct encryption and decryptability that can be used to construct a publicly verifiable secret sharing (PVSS) scheme and non-interactive threshold signature scheme (NITSS).

TSS case study

To better illustrate our goal with PVPKE, lets consider a threshold Schnorr signature scheme (TSS). In TSS any subset of

t-out-of-
n
signers can produce a valid signature. In the simplest case
t
-out-of-
n
property is achieved with a secret sharing scheme (SSS). In a distributed multi-party protocol it's done with distributed key generation (DKG). In TSS a DKG protocol is used to generate keys and nonce during signing round. A DKG is usually constructed as multiple VSS sessions where each signer gets to act as a secret dealer. The pseudocode for a DKG protocol is presented below.

  1. Commitmentsi,SharesiVSS.ShareRandom()
  2. broadcast
    Commitmentsi
  3. Good{}
  4. for each
    j
    :
    4.1. receive
    Commitmentsj
    from
    Peerj

    4.2. send
    Eji=PKE.Encrypt[PKj](Sharei(j))
    to
    Peerj

    4.3. receive
    Eij
    from
    Peerj

    4.4.
    Sharej(i)PKE.Decrypt[ski](Eij)

    4.5. if
    VSS.Verify(Commitmentj,Sharej(i))
    then
    GoodGood{j}

    4.6. else handle bad dealer
    Peerj
  5. FinalShareijGoodSharej(i)
  6. return
    FinalSharei

In order for the protocol to be correct peers need to know which secret shares exactly (ie. the set

Good) contribute to the final value (signing key, nonce, final signature). It's trivial if we consider that all peers are honest, ie. they won't try to disrupt the execution of the protocol, or forge a signature. This is not the case in real world and we have to account for that.

First, we need to assume asynchronous networking model. In it an adversary can block (but not reorder) some messages. That means that we have to communicate with all peers at once (and not sequentially as presented in the pseudocode). Next, the broadcast primitive must be reliable (ie. all honest nodes must receive the same commitments which is not true with an incorrect trivial "send-to-all" implementation of broadcast). Next, an adversary shall not be able to break a secure channel between peers (implemented with PKE in the pseudocode). Lastly, there should be a proper "handle bad dealer" procedure.

We shall focus on the last issue. Without PVPKE many DKG protocols do special "complaint-and-verify" rounds. In simple terms, the idea is for

Peerk to decide which peer to trust in a dispute between
Peeri
and
Peerj
where
Peeri
complains that
Peerj
is bad and
Peerj
tries to prove otherwise. With PVPKE we can implement DKG as follows.

  1. Commitmentsi,SharesiPVSS.ShareRandom()
  2. EncryptedSharesi,ProofsiPVPKE.ProveEncrypt[PK](Sharesi)
  3. broadcast
    Commitmentsi,EncryptedSharesi,Proofsi
  4. Good{}
  5. for each
    j
    :
    5.1. receive
    Commitmentsj,EncryptedSharesj,Proofsj
    from
    Peerj

    5.2. if
    PVSS.Verify[PKj](Commitmentsj,EncryptedSharesj,Proofsj)
    then
    GoodGood{j}

    5.3.
    Sharej(i)PVPKE.Decrypt[ski](EncryptedSharesij)
  6. FinalShareijGoodSharej(i)
  7. return
    FinalSharei

An obvious drawback is added complexity to generate and verify proofs and increased size of broadcasted messages.

Overview

There is a number of well-known PKE/KEM systems such as ElGamal encryption, DHIES, Paillier, Kurosawa-Desmedt, Cramer-Shoup, RSA. The usual approach to PVPKE is to extend a PKE system with a non-interactive zero-knowledge proof (NIZKP), for example publicly verifiable ElGamal and RSA encryption, Paillier-based PVSS, Paillier-based IND-CCA secure PVPKE, pairing-based PVPKE, non-interactive DKG. These constructions target different properties such as semantic or IND-CCA2 security, homomorphic property, threshold compatibility, forward secrecy, pairing or RSA friendliness.

Among others we require the following properties:

  1. assumed hardness of DL/DH problems or their variant;
  2. semantic encryption "in scalar";
  3. proofs of decryptability and correct encryption;
  4. multi-user encryption;
  5. aggregation and batch verification of proofs.

The first requirement means compatibility with Ed25519/X25519; no pairings, RSA, composite/unknown order groups are allowed. The second and third requirements enable a simple application in PVSS, DKG, and TSS constructions; we do not need a stronger IND-CCA2 security. The last two requirements make implementations efficient.

The obvious candidate for a suitable PKE is ElGamal encryption. It satisfies requirements 1 and 4. In order to be able to decrypt a scalar we need to be able to compute a discrete logarithm. It's only possible for small scalars, hence we need to split a secret scalar to be encrypted into sufficiently small chunks.

For decryptability proof we need to prove that the owner of the private key corresponding to the encryption public key is able to decrypt an encrypted small chunk. This is done with a preimage proof (ElGamal encryption is additively homomorphic) and range proof (that the secret scalar chunk is sufficiently small). Proof of correct encryption is also a preimage proof (but for a combined scalar, not individual chunks).

Preimage proofs are easily doable with Schnorr sigma protocol generalized by Maurer. Range proofs are much more difficult. To do that we use Bulletproofs a succinct proof system in DL setting. If we use a straightforward approach we wouldn't fulfill requirement 5. Fortunately, Bulletproofs range proof can be modified to support ElGamal commitments (instead of Pedersen commitments which is used initially), extended statement for chunking proofs, and efficient aggregation (due to use of multi-user ElGamal encryption).

PVPKE & PVSS

Let

X=xG be receivers' public keys, then lifted ElGamal multi-user encryption is defined by the following two equations.

C,R=EncX(s,r)=sH+rX,rG
sj=Decxj(Cj,R)=DLH(CjxjR)

Enc and
Dec
have all the nice additively homomorphic properties allowing to use them in Bulletproofs.

DLH(sjH) only works for
sj[0..2b)
with small
b
. For any
sjZq
,
sj=l=0m12blsj,l
we split it into
m
chunks
sj,l[0..2b)
.

Cl,Rl=EncX(sl,rl)=slH+rlX,rlG
sj,l=Decxj(Cj,l,Rl)=DLH(Cj,lxjRl)

This effectively increases

m times the cipher text size.

In order to turn it into PVPKE we need to add some nice proofs.

Decryptability is the proof that the receiver can decrypt

sH=CxR (ie. the owner of the private key
x
is the actual receiver):

Decryptability{(C,R;s,r):C,R=EncX(s,r)}

It's possible to use

Preimage proof with
EncX(s,r)
as one-way homomorphic map. Formally the proof means that the dealer knows
s,r
, but semantically it means the receiver's public key
X
was used to encrypt
s
. It's possible to aggregate the final proof to account for
n
receivers and
m
chunks.

Chunking is the proof that the receiver can bruteforce DLog

s=DLH(sH):

Chunking{(C;s,r):C=sH+rXs[0..2b)}

We'll use a modified

RangeProof proof with
C,R
as ElGamal commitment. Formally this proof does also prove knowledge of
s,r
. We need to make sure that it's safe to use public key
X
and
H
as CRS in ElGamal commitment.

We want to use our PVPKE scheme to construct a PVSS scheme. Let's recall Feldman's VSS:

  1. The dealer generates random polynomial
    f(x)=k=0t1xkfk
    such that
    s=f0=f(0)
    is the dealer's secret.
  2. Next, the dealer publishes commitment
    Fk=fkH
    to
    f(x)
    .
    F0
    is the dealer's public key and
    F(x)=k=0t1xkFk
    is commitment polynomial.
  3. Next, the dealer computes shares
    sj=f(j)
    and securely delivers them to each receiver.
  4. Receivers can use Feldman's verification equation
    sjH=?F(j)
    to verify their shares.
  5. The shared secret can be recovered via interpolation polynomial
    f^(x)=jJljJ(x)sj
    where
    ljJ(x)=iJ,ijxiji
    is Lagrange polynomial. Then the recovered secret is
    s^=f^(0)
    .

In a PVSS scheme scalars to be encrypted are secret shares satisfying certain verification equation

sjH=F(j). Thus we have to add a corresponding proof.

Sharing is the proof that encrypted share is correct, ie.

sjH=F(j):

Sharing{(Fk,Cj,l,Rl,Xj;rl):l2blCj,lF(j)=l2blrlXjRl=rlG}

Again, we use

Preimage proof of knowledge with
gXj(rl)=(l2blrlXj,rlG)
as one-way homomorphic map. Formally it means the knowledge of
r
and equality of discrete logs. Semantically it means image of encrypted value is
F(j)
.

Bulletproofs improved

Here we will specify in more detail Bulletproofs-based interactive protocol to support PVSS proofs. It can then be made non-interactive with Fiat-Shamir transform.

First, let's combine all the desired statements into one (secret share chunk here is

vj,l to be more consistent with the Bulletproofs paper and avoid clash of names):

PVSS{(Fk,Cj,l,Rl,Xj;vj,l,rl):Cj,l,Rl=EncXj(vj,l,rl)vj,l[0..2b)l2blCj,lF(j)=l2blrlXj},

where

k=0..t1,j=1..n,l=1..m.

Here the following notation will be used:

  • cn=(ci)i=0n1Zqn
    ;
  • xa=(xai)i=0n1
    ;
  • a,b=i=0n1aibi
    ;
  • ab=(aibi)i=0n1
    ;
  • x×b=i=0n1(xib)
    ;
  • vj=l=0m12blvj,l
    ,
    v=j(vj,l)l
    ;
  • VCommit(a,b,c)=a,G+b,H+cK
    .

Step 1.

The prover chooses nonces

aL,
aR
such that
vj,l[0..2b)
can be rewritten as a system of
nm+2bnm
scalar equations:

aL,j,l,2b=vj,l,j,laL=aR+1bnmaLaR=0bnm,

where

aL=j=0n1(l=0m1aL,j,l).

The prover chooses a random

α and publishes commitment
A=VCommit(aL,aR,α)
.

Step 2.

The prover receives from the verifier challenge

y and aggregates the previous system into the following one with
nm+2
scalar equations:

aL,j,l,2b=vj,l,j,laLaR1bnm,ybnm=0aL,ybnmaR=0.

Step 3.

The prover receives from the verifier challenge

z and further aggregates the system into
1
scalar equation:

z2j=1nl=0m1z(j1)m+laL,j,l,2b++zaLaR1bnm,ybnm++aL,ybnmaR==z2j=1nl=0m1z(j1)m+lvj,l.

The same equation can be rewritten in inner-product form:

z2aL,znm×2b+zaL,ybnm+aL,ybnmaRzybnm,aR=z2znm,v+zybnm,1bnm,

or in a folded form with only 1 inner product (the goal is to get inner product of

aL and
aR
):

aLz1bnm,z2znm×2b+ybnm(aR+z1bnm)==z2znm,v+(zz2)ybnm,1bnmz31bnm,znm×2b==z2znm,v+δ(y,z).

Step 4.

In order to use inner-product argument (IPA) and make proof zero-knowledge prover needs to blind

aL and
aR
.

The prover chooses random nonces

sL,sR, a random
ρ
, publishes commitment
S=VCommit(sL,sR,ρ)
.

Step 5.

The prover receives from the verifier challenge

x and constructs blindings:

l=aLz1bnm+xsL
r=z2znm×2b+ybnm(aR+z1bnm+xsR)

Note:

l and
r
are polynomials in
x
over
Zqbnm

t=l,r=t0+xt1+x2t2

Equation

t0=z2znm,v+δ(y,z) (
t(x)
evaluated at
x=0
) is equivalent (with high probability) to the initial system and the statement that
vj,l
is small.

Now, the prover can prove that

t=z2znm,v+δ(y,z)+xt1+x2t2 with IPA instead.

Step 6.

t1,
t2
serve as blindings for
t0
. The prover commits to
t1,t2
with ElGamal commitment (
CommitX(s,r)=sG+rX,rG
) using random
τ1,τ2
:

Ti,Qi=CommitX(ti,τi),fori=1,2,

so that the following holds:

tG+τxX=z2znm,C+δ(y,z)G+xT1+x2T2.

We can use the equation above and the equations from the PVSS statement to deduce the form of the piece of proof

τx, the form of point
X
and necessary verification equations.

More concretely, we use the following equations:

Cj,l=vj,lG+rlXj,
Rl=rlG

znm,C=j=1nz(j1)ml=0m1zl(vj,lG+rlXj)

j=1nz(j1)ml=0m1zlrlXj=(l=0m1zlrl)(j=1nz(j1)mXj)

Thus we get:

X=j=1nz(j1)mXj

τx=z2l=0m1zlrl+xτ1+x2τ2

The prover publishes commitments

Ti,Qi for
i=1,2
and
τx
as part of proof.

Step 7.

The verifier verifies:

tG+τxX=?z2znm,C+δ(y,z)G+xT1+x2T2

τxG=?z2zm,R+xQ1+x2Q2

Step 8.

The prover chooses random

η, published commitment
N=ηG
.

Step 9.

The prover receives challenge

u from the verifier and publishes commitment
M=ηj=1nujXj
.

Step 10.

The prover receives challenge

w from the verifier. The prover publishes proof:
s=η+wl2blrl

Step 11.

The verifier verifies:

s(G+j=1nujXj)=?N+M++w(l2blRl+j=1nuj(l2blCj,lF(j))

Step 12.

In order to be able to use IPA, the prover computes the following commitment:

P=IPACommit(l,r)==(aL,G+ybnmaR,H+αK)++x(sL,G+ybnmsR,H+ρK)(α+xρ)Kz1bnm,G+z2znm×2b+zybnm,H

Let's denote

H=ybnmH, we can rewrite expression for
P
as follows:

P=A+xSμKzG+γ(y,z),H

The prover publishes

μ=α+xρ as part of proof (so that
P
can be reconstructed by the verifier). The prover constructs and publishes IPA.

Step 13.

The verifier reconstructs commitment

P and verifies IPA.