Simulating Bulletproofs Under Adaptive Corruptions

·25 min read
Zero-Knowledge ProofsBulletproofsAdaptive SecuritySecure ErasuresPedersen Commitments
Abstract

In this post, we show how to reconstruct the state of a honest prover given a simulated Bulletproof and a valid witness of the proof’s statement. Protocols that use Bulletproofs therefore can use our technique to handle adaptive corruptions and no longer need to additionally assume secure erasures.

A zero-knowledge proof [GMR85] allows a prover to convince a verifier that a public statement x\stmt of an NP-relation is true without revealing the corresponding witness w\wit. For example, x\stmt may be a public key x=gw\stmt=g^\wit, where gg generates a group of prime order pp and w\wit is the secret key. A zero-knowledge proof could then convince the verifier that the prover knows the secret key, without revealing any information besides the already known public key x\stmt. In this post we are particularly interested in non-interactive zero-knowledge proofs, or NIZK [BFM88], which allow the prover to generate such a proof π\pi without interacting with the verifier.

In cryptography, we formalize the promise that a proof ‘‘reveals no additional information’’ through simulation. We say a proof is zero-knowledge if an efficient algorithm (called a simulator) that only knows a statement x\stmt but does not know the witness w\wit can produce valid proofs that no efficient verifier can distinguish from an honest proof. Whatever the verifier learns from an honest proof, it could then also have learned from a simulated proof, which carries no information about the witness to begin with.

At first glance, this definition seems paradoxical, since if a simulator can produce valid proofs without knowing the witness, why should a proof convince a verifier? The answer to this question is called a trapdoor, a piece of secret information that the simulator in a security proof knows and lets it simulate proofs. At the same time, no real prover has access to the trapdoor, so proofs from a real prover are sound (can only be computed when knowing a valid witness). For Fiat–Shamir-based proofs [FS86], which are the subject of this post, the simulator’s trapdoor is the power to program the random oracle [BR93], which is of course not possible in real instantiations.

This simulation property is useful when proving the security of a larger protocol, where NIZKs are used as a building block. Throughout the security proof of such a higher-level protocol, the reduction can first use the NIZK’s simulator to generate proofs without knowing a valid witness, and then embed a challenge element in the NIZK’s statement. With our example NIZK of secret-key knowledge, this would allow the reduction to embed a discrete-logarithm (DLog) challenge element into the public key while still producing accepting proofs of knowledge of the secret key. If the adversary breaks the modified protocol, the reduction uses this break to compute the discrete logarithm of the embedded element. Since replacing honest proofs with simulated ones results in an indistinguishable view for the adversary, any adversary that breaks the real protocol can also be used to break the modified protocol, which in turn allows solving DLog. Because DLog is assumed to be hard, no such adversary can exist.

A timeline of three experiments. The honest execution, then simulated NIZK proofs, then an embedded challenge.
Experiments in the security proof. Consecutive experiments are computationally indistinguishable.

This proof technique is standard in cryptographic literature and yields secure higher-level protocols under static corruptions, where the adversary chooses which parties to corrupt before the protocol starts. Under static corruptions, the reduction must only simulate the remaining honest parties. Additionally, these honest parties stay uncorrupted throughout the execution and the reduction never has to reveal the internal state behind their simulated proofs. For this part of the security argument, producing indistinguishable proofs is sufficient.

However, static corruptions are not a very realistic corruption model, as in practice adversaries typically do not announce prior to a protocol start which parties they eventually will corrupt. Therefore, as a more realistic corruption model, cryptographers use adaptive corruptions [CGJKR99], where the adversary can choose parties to corrupt during the execution of a protocol, based on the protocol messages it has already seen. If the adversary decides to corrupt such a party, then the reduction has to provide all secret information in the state of this party (including all the randomness used so far). The gap between static and adaptive corruptions might seem small at first sight, but adaptive corruptions have a big impact on the way we can do security proofs. For example, an adversary could wait until all honest parties have published a NIZK, and then decide to corrupt a random party afterwards.

While this might not necessarily help the adversary to break the protocol, it can give it the power to complicate our proof. For example, if we want to use the proof strategy discussed above, we cannot simply replace all honest proofs by simulated ones, since the reduction has to reveal the randomness behind a simulated proof as soon as its prover is corrupted. The adversary can check that this randomness is consistent with the public transcript by running the honest prover again. A simulated proof, however, was produced without the witness, and the random choices of the simulator need not be valid coins for the honest prover. Even if the witness becomes available upon corruption, the proof is already fixed and cannot be replaced. Thus, indistinguishability of the proof alone no longer suffices.

The timeline of the three experiments, with the adversary corrupting the prover after the NIZK proofs are simulated.
Experiments under adaptive corruption. The corruption asks for the state behind a proof that was simulated without a witness.

There are three ways around this problem. First, the reduction can guess in advance which parties the adversary will corrupt. It then computes the proofs of these parties honestly (it knows their witnesses, since it embeds the challenge only in the statements of the others) and simulates the remaining proofs. If the guess turns out to be wrong, the reduction aborts. For a single corruption among nn parties, this costs a factor of nn in the success probability of the reduction, which is still polynomial. Threshold protocols, however, allow the adversary to corrupt up to tt of the nn parties, and if it corrupts tt of them at random, a guess of this set is correct only with probability 1/(nt)1/\binom{n}{t}. For n=100n=100 and t=50t=50, the reduction thus loses a factor larger than 2962^{96}, which makes the security bound meaningless.

Second, honest parties can use secure erasures [CGJKR99] and delete the randomness of a proof directly after sending it. A later corruption then no longer reveals this randomness. This, however, is an additional assumption on how honest parties are implemented.

Third, the reduction can simulate all proofs anyway and, once the witness becomes available upon corruption, try to reconstruct randomness that makes the honest prover output exactly the proof it already published. For this post we can simply assume that the reduction obtains a valid witness for the statement of a corrupted party, since upon corruption the reduction must hand over the witness as part of the party’s state anyway.

Reconstructing the prover’s state#

Because we do not want to additionally assume secure erasures, and also cannot efficiently guess which parties the adversary will corrupt, we take the third way. This means that we want to reconstruct randomness for a simulated proof given a valid witness.

If a reduction is able to reconstruct the prover’s state behind a simulated proof, this fixes the gap in the sketched adaptive security proof of the higher-level protocol. Throughout the security proof of the higher-level protocol, the reduction can again first use the NIZK’s simulator to generate proofs without knowing a valid witness, and then embed a challenge element in the NIZK’s statement. When the adversary corrupts a party, the reduction obtains this party’s witness, uses it to reconstruct the randomness behind every proof the party has published, and returns this randomness as part of the party’s internal state.

A simulator first publishes a proof without a witness, then reconstructs consistent randomness after a valid witness becomes available upon corruption.
The proof is fixed before the witness is known. The reconstructed randomness reproduces it with the later witness.

We formalize this property as honest prover state reconstruction, following Groth, Ostrovsky and Sahai [GOS06].

Definition 1 (Honest prover state reconstruction).

Let Π=(Prove,Verify)\Pi=(\mathrm{Prove},\mathrm{Verify}) be a NIZK for a relation R\mathcal R in the random oracle model, where Prove\mathrm{Prove} takes its randomness rr as an explicit input and every public parameter is derived from the random oracle HH. Then Π\Pi has honest prover state reconstruction if there are efficient algorithms Sim\mathrm{Sim} and Rec\mathrm{Rec} with a shared state st\mathrm{st} such that for every efficient adversary A\mathcal A

Pr[AH,Oreal=1]Pr[ASim,Osim=1], \Pr\bigl[\mathcal A^{H,\,\mathcal O_{\mathrm{real}}}=1\bigr] \approx \Pr\bigl[\mathcal A^{\mathrm{Sim},\,\mathcal O_{\mathrm{sim}}}=1\bigr],

where HH is a random function in the first experiment and Sim\mathrm{Sim} answers the adversary’s random-oracle queries in the second. Both oracles take a pair (x,w)(\stmt,\wit), return \bot if (x,w)R(\stmt,\wit)\notin\mathcal R, and otherwise answer as follows.

  • Oreal(x,w)\mathcal O_{\mathrm{real}}(\stmt,\wit) samples rr, computes πProveH(x,w;r)\pi\gets\mathrm{Prove}^{H}(\stmt,\wit;r), and returns (π,r)(\pi,r).
  • Osim(x,w)\mathcal O_{\mathrm{sim}}(\stmt,\wit) lets Sim\mathrm{Sim} compute a proof π\pi on input x\stmt, programming its random oracle as needed, then computes rRec(st,x,w)r\gets\mathrm{Rec}(\mathrm{st},\stmt,\wit), and returns (π,r)(\pi,r).

Note that in the simulated experiment the witness reaches only Rec\mathrm{Rec}, after Sim\mathrm{Sim} has already fixed the proof, which is what happens in our sketched security proof upon a corruption. In addition, besides reproducing the proof, the reconstructed randomness must also be distributed like honest coins, to ensure that the adversary’s view with reconstructed randomness is indistinguishable from a real view.
For Fiat–Shamir proofs, the adversary re-runs the prover against the same random oracle, so the randomness has to reproduce the proof under the answers the simulator programmed. Additionally, we allow the reconstruction algorithm to use the simulator’s retained state, which includes every random-oracle answer the simulator chose, and ask it to reconstruct randomness only for proofs that this simulator produced.

State reconstruction for Schnorr proofs#

The goal of this post is to show that Bulletproofs have honest prover state reconstruction. As a warm-up example, we first recall how to reconstruct the prover’s state for Schnorr proofs [Sch91], again for a Schnorr proof of knowledge of the secret key w\wit for a public key x=gw\stmt=g^\wit. Recall that to compute such a Schnorr proof, the prover samples a random element r$Zpr\sample\ZZ_p, sends A=grA=g^r, and answers the challenge c=H(x,A)c=H(\stmt,A) with z=r+cwz=r+c\wit. To simulate such a proof, the simulator samples (c,z)$Zp2(c,z) \sample \ZZ_p^2 uniformly and sets A=gzxcA=g^z\stmt^{-c}, which satisfies the verification equation gz=Axcg^z=A\stmt^c. It then programs the random oracle to return cc on input (x,A)(\stmt,A), provided that this input has not already been queried.

Theorem 1 (Schnorr proofs have honest prover state reconstruction).

Schnorr’s proof of knowledge of a discrete logarithm has honest prover state reconstruction in the sense of Definition 1.

Proof (Reconstructing the Schnorr prover's randomness).

We construct an algorithm Rec\mathrm{Rec} that, given the simulator’s state (c,z)(c,z) and the witness w\wit, computes

r=zcw(modp). r=z-c\wit\pmod p.

Since x=gw\stmt=g^\wit, this gives gr=gzxc=Ag^r=g^z\stmt^{-c}=A, and the honest prover’s response is r+cw=zr+c\wit=z, so re-running the prover on rr against the programmed oracle reproduces π\pi. In the real experiment rr is uniform and the challenge c=H(x,A)c=H(\stmt,A) is uniform and independent of it. In the simulated experiment cc and zz are uniform and independent, and for fixed cc and w\wit subtracting cwc\wit is a bijection, so cc and rr are uniform and independent as well. Both experiments therefore give the same joint distribution of π\pi and rr, unless Sim\mathrm{Sim} has to program a point (x,A)(\stmt,A) that is already defined. Let the adversary make qHq_H random-oracle queries and qPq_P proof queries. Since AA is uniform in a group of order pp, a single proof hits an already defined point with probability at most (qH+qP)/p(q_H+q_P)/p, and a union bound over the qPq_P proofs shows that the two experiments differ by at most qP(qH+qP)/pq_P(q_H+q_P)/p, which is negligible in the security parameter.

Our argument naturally generalizes to other Schnorr-type proofs whose responses are linear in the witness, such as proofs of equality of discrete logarithms or of knowledge of a Pedersen opening, where the reconstruction algorithm subtracts the challenge times the witness from each response.

For Schnorr proofs, randomness reconstruction is possible, so they can be simulated in adaptive protocols without assuming secure erasures upon corruption. However, a Schnorr proof sends one response per secret value, so the proof size grows linearly with the witness. To make protocols that use NIZKs for large witnesses more efficient, one can use Bulletproofs [BBB+18] instead of Schnorr proofs. In contrast to Schnorr, Bulletproofs grow only logarithmically in the witness size, but similar to Schnorr, need no trusted setup and rely only on the discrete-logarithm assumption.

Pedersen commitments#

Before we turn to Bulletproofs, we need one more building block, namely Pedersen commitments [Ped91]. Intuitively, a commitment scheme works like a sealed envelope. In the commit phase, a committer puts a value mm into the envelope and hands it to a receiver, who cannot look inside. In the opening phase, the committer reveals mm, and the receiver checks that this is indeed the value in the envelope, so the committer cannot change its mind in between. Proof systems use commitments to let the prover fix a value before it sees the verifier’s challenge, without revealing the value already.

To compute a Pedersen commitment to a single value, we need a second generator hh of our group. To commit to mZpm\in\ZZ_p, the committer samples a random ρ$Zp\rho\sample\ZZ_p and sends C=gmhρC=g^mh^\rho. To open the commitment, it reveals mm and ρ\rho, and the receiver checks that C=gmhρC=g^mh^\rho.

A commitment should satisfy two properties. First, it should be hiding, which means that CC reveals no information about mm. For Pedersen commitments, this holds since for every pair of values mmm \neq m' and every ρ\rho, there is exactly one ρ\rho' with gmhρ=gmhρg^mh^\rho=g^{m'}h^{\rho'}. Every commitment could thus equally well contain any other value, and since ρ\rho is uniformly random, CC has the same distribution no matter which value it contains. Second, it should be binding, which means that the committer cannot open CC to a different value later. If it could, it would know two openings (m,ρ)(m,\rho) and (m,ρ)(m',\rho') with mmm\neq m' and gmhρ=gmhρg^mh^\rho=g^{m'}h^{\rho'}, from which it could compute the discrete logarithm loghg=(ρρ)/(mm)\log_h g=(\rho'-\rho)/(m-m'). Pedersen commitments are thus binding as long as the discrete-logarithm assumption between gg and hh holds.

On the other hand, Pedersen commitments are equivocable. This means that anyone who knows ν=loghg\nu=\log_h g can compute the randomness ρ=ρ+ν(mm)\rho'=\rho+\nu(m-m') from the hiding property, and thus open a commitment C=gmhρC=g^mh^\rho to any other value mm'. We call ν\nu the trapdoor of the commitment. Just like the simulator’s trapdoor for proofs, this trapdoor will become important later. Another interesting property of Pedersen commitments is that they allow us to commit to whole vectors mZpn\mathbf m\in\ZZ_p^n at once in a single group element. This works by using one generator per entry via C=hρigimiC=h^\rho\prod_ig_i^{m_i}. Such a vector commitment is binding as long as nobody knows a discrete-logarithm relation between the generators, and anyone who knows the discrete logarithms of all generators to the base hh can again open it to any vector. To make sure that only a security reduction, but no real protocol participant knows such a relation, one typically derives all generators through the random oracle by hashing public labels [BBB+18].

Bulletproofs#

At their core, Bulletproofs use an inner-product argument (IPA), which proves that two committed vectors have a given inner product. More formally, for generators g=(g1,,gn)\mathbf g=(g_1,\ldots,g_n), h=(h1,,hn)\mathbf h=(h_1,\ldots,h_n) and uu, and writing ga=igiai\mathbf g^{\mathbf a}=\prod_i g_i^{a_i}, the prover of an IPA shows that it knows vectors a,bZpn\mathbf a,\mathbf b\in\ZZ_p^n with P=gahbua,bP=\mathbf g^{\mathbf a}\mathbf h^{\mathbf b}u^{\langle\mathbf a,\mathbf b\rangle} for a public group element PP. Inner-product arguments are a powerful tool for NIZKs, because many statements are inner products. Evaluating a committed polynomial with coefficient vector a\mathbf a at a point zz, for instance, is the inner product a,(1,z,,zn1)\langle\mathbf a,(1,z,\ldots,z^{n-1})\rangle, and the constraints of an arithmetic circuit can be checked all at once through a random linear combination that collapses them into a single inner product [BCC+16].

To prove an inner product without sending 2n2n field elements, Bulletproofs use the split-and-fold technique of [BCC+16, BBB+18]. It splits both vectors into halves a1,a2\mathbf a_1,\mathbf a_2 and b1,b2\mathbf b_1,\mathbf b_2 and, for a challenge xx, folds them into a=xa1+x1a2\mathbf a'=x\mathbf a_1+x^{-1}\mathbf a_2 and b=x1b1+xb2\mathbf b'=x^{-1}\mathbf b_1+x\mathbf b_2 of half the length, whose inner product is a,b=a,b+x2a1,b2+x2a2,b1\langle\mathbf a',\mathbf b'\rangle=\langle\mathbf a,\mathbf b\rangle+x^2\langle\mathbf a_1,\mathbf b_2\rangle+x^{-2}\langle\mathbf a_2,\mathbf b_1\rangle. The folded vectors thus satisfy the same relation once the two cross terms a1,b2\langle\mathbf a_1,\mathbf b_2\rangle and a2,b1\langle\mathbf a_2,\mathbf b_1\rangle are accounted for. To account for these cross terms, the prover computes the two group elements L=g2a1h1b2ua1,b2L=\mathbf g_2^{\mathbf a_1}\mathbf h_1^{\mathbf b_2}u^{\langle\mathbf a_1,\mathbf b_2\rangle} and R=g1a2h2b1ua2,b1R=\mathbf g_1^{\mathbf a_2}\mathbf h_2^{\mathbf b_1}u^{\langle\mathbf a_2,\mathbf b_1\rangle}.

Given the two group elements LL and RR, both parties can fold the generators to half the length and set P=Lx2PRx2P'=L^{x^2}PR^{x^{-2}}, whose extra factors add exactly the two cross terms. Because Fiat–Shamir derives xx only after LL and RR are fixed, the prover cannot choose them to hide a wrong inner product. The result PP' is again an instance of the same relation, but of half the length. To proceed, the prover applies this step recursively, until after log2n\log_2 n rounds each vector is a single scalar. With this technique, the proof consists of 2log2n2\log_2 n group elements and two scalars. Apart from a\mathbf a and b\mathbf b this prover uses no randomness.

One round of split and fold. The challenge x combines the two halves of each vector into a vector of half the length, while the cross terms L and R pair each half of one vector with the opposite half of the other and turn P into the statement for the halved vectors. After log2 n rounds two scalars remain.
Split and fold in the inner-product argument. The verifier folds the generators and the statement itself, so each round adds only two group elements to the proof.

The protocol we described so far is not zero-knowledge, since PP and the final scalars are functions of the vectors. To make it zero-knowledge, Bulletproofs+ [CHJ+22] use the hiding property of Pedersen commitments and add a random power of hh to every group element. (Bulletproofs+ actually prove weighted inner products, but for this post we set all weights to 11.) First, the statement itself becomes a hiding commitment P=gahbua,bhαP=\mathbf g^{\mathbf a}\mathbf h^{\mathbf b}u^{\langle\mathbf a,\mathbf b\rangle}h^{\alpha} with a random blinding exponent α\alpha. Then, in every round, the prover samples two fresh exponents dL,dR$Zpd_L,d_R\sample\ZZ_p and sends the blinded cross terms

L=g2a1h1b2ua1,b2hdL,R=g1a2h2b1ua2,b1hdR. L=\mathbf g_2^{\mathbf a_1}\mathbf h_1^{\mathbf b_2}u^{\langle\mathbf a_1,\mathbf b_2\rangle}h^{d_L},\qquad R=\mathbf g_1^{\mathbf a_2}\mathbf h_2^{\mathbf b_1}u^{\langle\mathbf a_2,\mathbf b_1\rangle}h^{d_R}.

Since hdLh^{d_L} and hdRh^{d_R} are uniformly random, LL and RR now reveal no information about the witness vectors. Folding works as before, but the prover additionally keeps track of the blinding exponent of the folded commitment P=Lx2PRx2P'=L^{x^2}PR^{x^{-2}}, which is α=α+x2dL+x2dR\alpha'=\alpha+x^2d_L+x^{-2}d_R.

In the last round, in which the prover would send the scalars aa and bb in the clear, it now proves that it knows aa, bb and α\alpha with a Schnorr-like step. It samples r,s,δ,η$Zpr,s,\delta,\eta\sample\ZZ_p, sends the two commitments

A=grhsurb+sahδ,B=urshη A=g_\ast^{r}h_\ast^{s}u^{rb+sa}h^{\delta},\qquad B=u^{rs}h^{\eta}

for the folded generators gg_\ast and hh_\ast, and answers the challenge ee with

r=r+ae,s=s+be,δ=η+δe+αe2. r'=r+ae,\qquad s'=s+be,\qquad \delta'=\eta+\delta e+\alpha e^2.

Just like in a Schnorr proof, the random rr and ss hide aa and bb in the responses. The verifier then checks that Pe2AeB=grehseurshδP^{e^2}A^eB=g_\ast^{r'e}h_\ast^{s'e}u^{r's'}h^{\delta'}, where AA and BB provide the cross terms rb+sarb+sa and rsrs that show up in ursu^{r's'}.

Put together, the Bulletproof inner-product argument for vectors of length nn consists of the blinded cross terms of all k=log2nk=\log_2 n rounds and the messages of the final Schnorr-like step,

π=(L1,R1,,Lk,Rk,A,B,r,s,δ). \pi=(L_1,R_1,\ldots,L_k,R_k,A,B,r',s',\delta').

With Fiat–Shamir, the challenge xjx_j of round jj and the last challenge ee are hashes of PP and all previous messages, so the verifier can recompute them from π\pi and fold the generators and PP itself.

With these changes, we get a zero-knowledge argument that the prover knows a\mathbf a, b\mathbf b and α\alpha with P=gahbua,bhαP=\mathbf g^{\mathbf a}\mathbf h^{\mathbf b}u^{\langle\mathbf a,\mathbf b\rangle}h^{\alpha}. Compared to the plain argument, it costs only two more group elements and one more scalar. The original Bulletproofs [BBB+18] make the argument zero-knowledge in a different way, by running it on randomly masked vectors. In this post we focus on the approach of Bulletproofs+, and come back to the original one in Corollary 1.

Simulating Bulletproofs#

To simulate Bulletproofs without knowing a valid witness, the simulator can follow a strategy similar to the one for Schnorr proofs. In the rounds of the argument, the simulator samples every LL and RR as a uniformly random group element. These are distributed exactly like the blinded cross terms of an honest prover. The round challenges come from the random oracle as usual. For the last step, the simulator samples the responses r,s,δr',s',\delta' and the challenge ee uniformly, together with a random group element BB, and then computes AA such that the verification equation holds. Finally, similar to the Schnorr simulation, the simulator programs the random oracle to return ee on the transcript ending with AA and BB, provided that this input has not already been queried.

Let us now try to reconstruct the prover’s randomness for such a simulated proof, once we know the witness a\mathbf a, b\mathbf b and α\alpha. We do this in the opposite order in which the simulator computed the proof. For the last step, we can apply the Schnorr trick from above, computing r=raer=r'-ae and s=sbes=s'-be. For the blinding exponents, however, we run into a problem. Since the simulator sampled LL as a random group element, we need a dLd_L for which the honest prover would have sent the same LL, namely

hdL=Lg2a1h1b2ua1,b2. h^{d_L}=L\,\mathbf g_2^{-\mathbf a_1}\mathbf h_1^{-\mathbf b_2}u^{-\langle\mathbf a_1,\mathbf b_2\rangle}.

The same holds for dRd_R in every round and for η\eta in BB. Finding such a dLd_L means computing a discrete logarithm. However, it can also be found with the trapdoor of the Pedersen commitments involved, which consists of the discrete logarithms of all generators to the base hh.

Our simulator can obtain this trapdoor because the generators come from the random oracle. In the simulated experiment of Definition 1, the simulator answers all random-oracle queries itself, so it also decides what the generators are. It answers the query for hh honestly, but every other generator query with hθh^{\theta} for a fresh uniform exponent θ\theta. Since hθh^\theta is again a uniformly random group element, the adversary cannot notice this change. This way, the simulator knows scalars κ,λ,ν,ω\boldsymbol\kappa,\boldsymbol\lambda,\nu,\omega with

gi=hκi,hi=hλi,g=hν,u=hω, g_i=h^{\kappa_i},\qquad h_i=h^{\lambda_i},\qquad g=h^{\nu},\qquad u=h^{\omega},

which we call the generator trapdoor. Once the simulator knows the generator trapdoor, it also knows the discrete logarithms of all folded generators, since folding only raises the generators to known powers of the challenges and multiplies them. For example, loghgi=x1κi+xκi+n/2\log_h g'_i=x^{-1}\kappa_i+x\,\kappa_{i+n/2}. In the same way, it samples every LL, RR and BB as a power of hh and remembers the exponents, which we denote by θL\theta_L, θR\theta_R and θB\theta_B. Note that this needs no additional assumption, since the simulator already programs the random oracle for the Fiat–Shamir challenges.

With the generator trapdoor, every commitment of the form C=hρgmhmumC=h^{\rho}\mathbf g^{\mathbf m}\mathbf h^{\mathbf m'}u^{m''} is simply a power of hh,

C=hρ+κ,m+λ,m+ωm. C=h^{\,\rho+\langle\boldsymbol\kappa,\mathbf m\rangle+\langle\boldsymbol\lambda,\mathbf m'\rangle+\omega\,m''}.

So if the simulator sampled CC itself as a power of hh, it can open CC to any messages by setting

ρ=loghCκ,mλ,mωm. \rho=\log_h C-\langle\boldsymbol\kappa,\mathbf m\rangle-\langle\boldsymbol\lambda,\mathbf m'\rangle-\omega\,m''.

Opening a commitment thus costs only one subtraction, just like reconstructing the Schnorr prover’s randomness in Theorem 1.

Warning

If a security proof relies on the generator trapdoor, it can no longer rely on the binding property of the Pedersen commitments, since the reduction can equivocate the commitments.
If the surrounding protocol needs binding, its security proof therefore has to establish binding before it switches to the generator trapdoor. This adds two experiments to the sequence from the introduction, which sit between the honest execution and the experiment with simulated NIZK proofs.

In the first experiment, the random oracle still answers the generator queries honestly, but the experiment aborts as soon as the adversary opens a commitment to two different values. This experiment differs from the honest execution only if the abort happens, and an adversary that causes it reveals a discrete-logarithm relation between the honest generators, so the abort happens only with negligible probability under DLog.

In the second experiment, the random oracle answers the generator queries with powers of hh whose exponents the reduction knows. This switch does not change the distribution of the generators, so the adversary cannot distinguish the second experiment from the first. From now on, the reduction no longer needs binding, since every binding break already leads to an abort. Extraction from adversarial Bulletproofs [GOP+22, DG23] is unaffected, because the adversary never learns the trapdoor.

State reconstruction for Bulletproofs#

With the generator trapdoor and the exponents θL\theta_L, θR\theta_R and θB\theta_B, the reconstruction algorithm can now compute all blinding exponents, which gives our main result.

Theorem 2 (Bulletproofs have honest prover state reconstruction).

The zero-knowledge inner-product argument of Bulletproofs+ [CHJ+22] with weight 11, made non-interactive with Fiat–Shamir and with generators derived from the random oracle, has honest prover state reconstruction in the sense of Definition 1.

For every random value of the honest prover, the simulated proof contains a value that this randomness has to reproduce. The table lists these pairs, in the order in which the reconstruction algorithm computes them.

Randomness of the honest proverSimulated value it has to reproduceHow the reconstruction algorithm computes it
dLd_L and dRd_R in every roundL=hθLL=h^{\theta_L} and R=hθRR=h^{\theta_R}open LL and RR with the generator trapdoor
rr and ssrr' and ss'solve r=r+aer'=r+ae and s=s+bes'=s+be
η\etaB=hθBB=h^{\theta_B}open BB with the generator trapdoor
δ\deltaδ\delta'solve δ=η+δe+αe2\delta'=\eta+\delta e+\alpha e^2

The last message AA needs no row of its own, because once all other values agree, the verification equation leaves only one choice for AA. The honest prover uses 2k+42k+4 random values for the k=log2nk=\log_2 n rounds, and the simulator samples exactly as many values, one for each random value of the honest prover.

Proof (Reconstructing the prover's randomness).

We construct an algorithm Rec\mathrm{Rec} that, given the simulator’s state and a valid witness (a,b,α)(\mathbf a,\mathbf b,\alpha), computes the randomness of the honest prover in the order of the table. In each round, it knows the discrete logarithms of the current generators and sets

dL=θLκ2,a1λ1,b2ωa1,b2 d_L=\theta_L-\langle\boldsymbol\kappa_2,\mathbf a_1\rangle-\langle\boldsymbol\lambda_1,\mathbf b_2\rangle-\omega\langle\mathbf a_1,\mathbf b_2\rangle

and dRd_R in the same way, where κ2\boldsymbol\kappa_2 and λ1\boldsymbol\lambda_1 contain the discrete logarithms of g2\mathbf g_2 and h1\mathbf h_1. With these exponents, the honest prover sends the same LL and RR as the simulator, and Rec\mathrm{Rec} folds a\mathbf a, b\mathbf b and α\alpha as the honest prover does. For the folded aa, bb and α\alpha, it then sets

r=rae,s=sbe,η=θBωrs,δ=e1(δηαe2), r=r'-ae,\qquad s=s'-be,\qquad \eta=\theta_B-\omega rs,\qquad \delta=e^{-1}(\delta'-\eta-\alpha e^2),

so that the honest prover sends the same BB and the same responses. It remains to show that the honest prover also computes the same AA, which the simulator derived from the verification equation. Since the witness is valid, it opens PP, and since folding preserves this, the folded witness opens the folded PP. The honest AA therefore satisfies the verification equation, in which every other value agrees with the simulation, so it equals the simulated AA. Re-running the prover on the reconstructed coins thus reproduces the whole proof.

The generators are uniformly random in both experiments. In the real experiment, the coins dL,dR,r,s,δ,ηd_L,d_R,r,s,\delta,\eta are uniform, and the last challenge is uniform and independent of them. In the simulated experiment, the exponents θL,θR,θB\theta_L,\theta_R,\theta_B and the responses r,s,δr',s',\delta' are uniform and independent of the last challenge. For fixed challenges and witness, each step of Rec\mathrm{Rec} subtracts a value that the witness and the previous steps determine, and possibly multiplies by e1e^{-1}, so the reconstruction is a bijection and the reconstructed coins are uniform as well. Both experiments therefore give the same joint distribution of proof and coins, unless Sim\mathrm{Sim} has to program a point that is already defined. As for Schnorr proofs, the simulator programs only one point per proof, and this point contains the uniformly random BB. A union bound over the qPq_P proofs bounds this probability by qP(qH+qP)/pq_P(q_H+q_P)/p, as in the proof of Theorem 1.

Remark 1 (Other weights).

Bulletproofs+ prove the weighted inner product iaibiyi\sum_i a_ib_iy^i for a weight yZpy\in\ZZ_p^*. Theorem 2 carries over to every such weight. The weight only adds known powers of yy to some exponents of the cross terms, the folding and the final step. The reconstruction algorithm therefore subtracts slightly different known values, and every step remains a bijection.

Corollary 1 (Range proofs and arithmetic circuits).

The range proofs of Bulletproofs+ [CHJ+22] and of Bulletproofs [BBB+18], as well as the arithmetic-circuit protocol of Bulletproofs, made non-interactive with Fiat–Shamir and with generators derived from the random oracle, have honest prover state reconstruction in the sense of Definition 1.

Proof.

The range proof of Bulletproofs+ shows that a Pedersen commitment V=gvhγV=g^vh^\gamma contains a value v[0,2n)v\in[0,2^n). Its prover first commits to the bits aL\mathbf a_L of vv and to aR=aL1n\mathbf a_R=\mathbf a_L-\mathbf 1^n as A=gaLhaRhαA=\mathbf g^{\mathbf a_L}\mathbf h^{\mathbf a_R}h^{\alpha}. After two challenges yy and zz, it runs the argument of Theorem 2 with weight yy on a statement that both parties compute from AA and VV. Our simulator samples AA as a power of hh, so Rec\mathrm{Rec} obtains α\alpha with the generator trapdoor and then proceeds as in the proof of Theorem 2, which covers weight yy by Remark 1. The simulator now programs a second point per proof for (y,z)(y,z), which changes the bound to 2qP(qH+2qP)/p2q_P(q_H+2q_P)/p.

The range proof and the circuit protocol of Bulletproofs run the plain argument on masked vectors. The same argument applies to these. In the range proof, the prover commits to vectors a,bZpn\mathbf a,\mathbf b\in\ZZ_p^n derived from the witness in a commitment AA, and to random masks sL,sR$Zpn\mathbf s_L,\mathbf s_R\sample\ZZ_p^n in a commitment SS. The inner product of the masked vectors a+XsL\mathbf a+X\mathbf s_L and b+XsR\mathbf b+X\mathbf s_R is a polynomial t(X)=t0+t1X+t2X2t(X)=t_0+t_1X+t_2X^2, where t0t_0 depends only on the witness (up to public terms that encode the range). The prover commits to t1t_1 and t2t_2 in T1T_1 and T2T_2, and after a challenge xx, it runs the plain argument on =a+xsL\boldsymbol\ell=\mathbf a+x\mathbf s_L and r=b+xsR\boldsymbol r=\mathbf b+x\mathbf s_R, whose inner product is t(x)t(x). Every commitment hides its content behind a random blinding exponent, so the prover also sends two blinding responses. The response μ\mu combines the blinding exponents of AA and SS in the same way as \boldsymbol\ell and r\boldsymbol r combine the vectors and the masks, and τx\tau_x combines those of VV, T1T_1 and T2T_2 in the same way as t(x)t(x) combines the coefficients. With these responses, the verifier checks in two verification equations that \boldsymbol\ell and r\boldsymbol r match AA and SS, and that t(x)t(x) matches VV, T1T_1 and T2T_2. The circuit protocol works in the same way, with more commitments and a polynomial of degree six. Our simulator samples \boldsymbol\ell, r\boldsymbol r, μ\mu and τx\tau_x uniformly and every commitment as a power of hh, except for SS and T1T_1, which it derives from the two verification equations. With the witness, Rec\mathrm{Rec} opens the sampled commitments with the generator trapdoor and solves the responses for the masks and the remaining blinding exponents, as for Schnorr proofs. The honest SS and T1T_1 then satisfy the verification equations and hence equal the simulated ones, where for T1T_1 we again need that the witness is valid. The plain inner-product argument needs no reconstruction, since its prover samples no randomness, so the same masked vectors lead to the same transcript. All equations that Rec\mathrm{Rec} solves are linear with nonzero coefficients, so the reconstructed coins are uniform, and the bound is again 2qP(qH+2qP)/p2q_P(q_H+2q_P)/p.

Conclusion#

Simulating NIZK proofs is a standard step in security proofs, but it becomes much harder once the adversary can corrupt parties adaptively. Upon a corruption, the reduction has to reveal the randomness behind every proof of the corrupted party, including the proofs that it simulated without a witness. Since guessing the corrupted parties in advance is too costly in general, the reduction either relies on secure erasures or has to reconstruct randomness that is consistent with the simulated proofs. For Schnorr proofs, this reconstruction was already established and takes a single subtraction, but for Bulletproofs it was left as an open problem [BLSW24].

In this post, we showed that Bulletproofs have honest prover state reconstruction, both the zero-knowledge argument of Bulletproofs+ [CHJ+22] and the range proof and circuit protocol of the original Bulletproofs [BBB+18]. The key observation is that every group element of a Bulletproof is a Pedersen commitment. A simulator that programs the generators through the random oracle knows their discrete logarithms and can therefore open each of these commitments to the witness it learns upon corruption. Protocols that simulate Bulletproofs in their security proof therefore no longer need to assume secure erasures for the randomness of these proofs.

References

[GMR85]
Shafi Goldwasser, Silvio Micali, Charles Rackoff
STOC 1985
[BFM88]
Manuel Blum, Paul Feldman, Silvio Micali
STOC 1988
[BR93]
Mihir Bellare, Phillip Rogaway
ACM CCS 1993
[BBB+18]
Benedikt Bünz, Jonathan Bootle, Dan Boneh, Andrew Poelstra, Pieter Wuille, Greg Maxwell
IEEE Symposium on Security and Privacy 2018
[GOS06]
Jens Groth, Rafail Ostrovsky, Amit Sahai
EUROCRYPT 2006
[CHJ+22]
Heewon Chung, Kyoohyung Han, Chanyang Ju, Myungsun Kim, Jae Hong Seo
IEEE Access 2022
[BLSW24]
Renas Bacho, Julian Loss, Gilad Stern, Benedikt Wagner
ASIACRYPT 2024
[Ped91]
Torben Pryds Pedersen
CRYPTO 1991
[Sch91]
Claus-Peter Schnorr
Journal of Cryptology 1991
[FS86]
Amos Fiat, Adi Shamir
CRYPTO 1986
[BCC+16]
Jonathan Bootle, Andrea Cerulli, Pyrros Chaidos, Jens Groth, Christophe Petit
EUROCRYPT 2016
[CGJKR99]
Ran Canetti, Rosario Gennaro, Stanisław Jarecki, Hugo Krawczyk, Tal Rabin
CRYPTO 1999
[DG23]
Quang Dao, Paul Grubbs
EUROCRYPT 2023
[GOP+22]
Chaya Ganesh, Claudio Orlandi, Mahak Pancholi, Akira Takahashi, Daniel Tschudi
EUROCRYPT 2022