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:
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).
To better illustrate our goal with PVPKE, lets consider a threshold Schnorr signature scheme (TSS). In TSS any subset of -out-of- signers can produce a valid signature. In the simplest case -out-of- 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.
In order for the protocol to be correct peers need to know which secret shares exactly (ie. the set ) 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 to decide which peer to trust in a dispute between and where complains that is bad and tries to prove otherwise. With PVPKE we can implement DKG as follows.
An obvious drawback is added complexity to generate and verify proofs and increased size of broadcasted messages.
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:
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).
Let be receivers' public keys, then lifted ElGamal multi-user encryption is defined by the following two equations.
and have all the nice additively homomorphic properties allowing to use them in Bulletproofs.
only works for with small . For any , we split it into chunks .
This effectively increases 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 (ie. the owner of the private key is the actual receiver):
It's possible to use proof with as one-way homomorphic map. Formally the proof means that the dealer knows , but semantically it means the receiver's public key was used to encrypt . It's possible to aggregate the final proof to account for receivers and chunks.
Chunking is the proof that the receiver can bruteforce DLog :
We'll use a modified proof with as ElGamal commitment. Formally this proof does also prove knowledge of . We need to make sure that it's safe to use public key and as CRS in ElGamal commitment.
We want to use our PVPKE scheme to construct a PVSS scheme. Let's recall Feldman's VSS:
In a PVSS scheme scalars to be encrypted are secret shares satisfying certain verification equation . Thus we have to add a corresponding proof.
Sharing is the proof that encrypted share is correct, ie. :
Again, we use proof of knowledge with as one-way homomorphic map. Formally it means the knowledge of and equality of discrete logs. Semantically it means image of encrypted value is .
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 to be more consistent with the Bulletproofs paper and avoid clash of names):
where .
Here the following notation will be used:
Step 1.
The prover chooses nonces , such that can be rewritten as a system of scalar equations:
where .
The prover chooses a random and publishes commitment .
Step 2.
The prover receives from the verifier challenge and aggregates the previous system into the following one with scalar equations:
Step 3.
The prover receives from the verifier challenge and further aggregates the system into scalar equation:
The same equation can be rewritten in inner-product form:
or in a folded form with only 1 inner product (the goal is to get inner product of and ):
Step 4.
In order to use inner-product argument (IPA) and make proof zero-knowledge prover needs to blind and .
The prover chooses random nonces , a random , publishes commitment .
Step 5.
The prover receives from the verifier challenge and constructs blindings:
Note: and are polynomials in over
Equation ( evaluated at ) is equivalent (with high probability) to the initial system and the statement that is small.
Now, the prover can prove that with IPA instead.
Step 6.
, serve as blindings for . The prover commits to with ElGamal commitment () using random :
so that the following holds:
We can use the equation above and the equations from the PVSS statement to deduce the form of the piece of proof , the form of point and necessary verification equations.
More concretely, we use the following equations:
,
Thus we get:
The prover publishes commitments for and as part of proof.
Step 7.
The verifier verifies:
Step 8.
The prover chooses random , published commitment .
Step 9.
The prover receives challenge from the verifier and publishes commitment .
Step 10.
The prover receives challenge from the verifier. The prover publishes proof:
Step 11.
The verifier verifies:
Step 12.
In order to be able to use IPA, the prover computes the following commitment:
Let's denote , we can rewrite expression for as follows:
The prover publishes as part of proof (so that can be reconstructed by the verifier). The prover constructs and publishes IPA.
Step 13.
The verifier reconstructs commitment and verifies IPA.