Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sound rangeproofs #1

Open
wants to merge 6 commits into
base: secp256k1-mw
Choose a base branch
from
Open

Conversation

apoelstra
Copy link
Owner

Implements a design by Oleg Andreev to create sound rangeproofs with identical size and format to the original Elements ones (though of course, neither will validate as the other).

@oleganza
Copy link

oleganza commented Apr 24, 2017

(moved from BlockstreamResearch#4 (comment))

Note that this multi-generator trick works only for a single-asset blockchain, but if you need to balance values per-asset, and assets are themselves blinded, then you cannot commit to a shared blinding factor as a second part of the commitment.

So this:

V = v*H  +f*G
F = f*J (shared among all digits)

won't work if H = A + b*G. You'd actually need:

Asset commitment (H,B):
  H = A + b*G
  B = b*J

Value commitment (V,F):
  V = v*H + f*G
  F = v*B + f*J

Now, balancing Vs and Fs will guarantee that v_i*A_j balance per asset (there is an extra requirement for As being random and v being of relatively short range, like < 64 bits). But having value encoded in the F commitment makes it non-reusable for individual digits.

Quantum computers are %@#$!@#^@.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 24, 2017

Oleg, if I have H = A + bG then a rangeproof with asset generator H is just as good as one with asset generator A.... which is good, because the latter would require I expose the secret A!

Since the soundness changes affect only the rangeproof, and the total balancing equation is independent of this, I don't see why it should matter at all if I have multiple assets.

Note that each rangeproof only works on a single asset; you can't have multiple asset types in a single output.

@oleganza
Copy link

oleganza commented Apr 24, 2017

Hmm...

Lets say you commit to f alone in F, and we assume the asset commitment is soundly proven to be within a proper set (so since very issuance random asset ids are not created out of thin air).

Asset commitment (H,B):
  H = A + b*G
  B = b*J

Value commitment (V,F):
  V = v*H + f*G
  F = f*J

Therefore, V = v*A + (v*b + f)*G. Balancing Fs and Vs would means that these things balance:

v*(a + b)*G   // A = a*G, where dlog `a` is PQ-known 

Since b (unlike v) is a scalar with unrestricted range, it is easy for you to find b' so that a' + b' == a + b and morph the commitment to a different asset a'. Due to soundness of the asset range proofs (surjection proofs), you'd need to have a little bit of a' on the input, but then in the output you can assign v to a'.

So the attack looks like this:

  1. Create asset A that you control.
  2. Break ECDLP to extract a from A.
  3. Choose asset A' that you do not control.
  4. Break ECDLP to extract a' from A'.
  5. Issue v units of A.
  6. Acquire at least one unit of A'.
  7. Create a tx with v*A and 1*A' on the inputs.
  8. Compute b' = a - a' + b.
  9. Create output with v*A' and blind A' with factor b'.
  10. Create output with 1*A and blind A with factor b.
  11. Now you swapped 1000000 units of dummy asset (A) and 1 unit of USD (A') for 1000000 USD and 1 dummy asset.

I'd be glad to be proven wrong to regain that 20% in space savings.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 24, 2017

Dammit. I see. It is simpler in the small-assets case where A, A' exist in a fixed list rather than having been issued and potentially reblinded many times.

Consider your asset commitment (H, B), and suppose I have v of these. I can create a transaction with one input and one output, both equal as El Gamal commitments, but the asset commitment on the output is changed to (H, B'). Here

H = vA + b*G [= vA' + (va - va' + b)*G]
B = b*J
B' = (va - va' + b)*J

A real attacker would also change H by just adding some extra blinding factor, but this illustrates the point.

Basically, the soundness of the surjection proof cannot stop a DLP attacker from recharacterizing asset commitments like this. (It does require they create a transaction to do it since they can't change the proofs' meaning after the fact. And in the presence of issuance I think you're right that you need to have inputs of both asset types, though the values are not important.)

The way that asset commitments are defined, as repeatedly-reblinded NUMS points plus a blinding factor, seems to make this inherent, no matter how your surjection proof is structured....do you think you can do better without the optimized sound rangeproof?

@oleganza
Copy link

oleganza commented Apr 24, 2017

If I'm not mistaken, the following approach is PQ-sound:

Asset ID point:
  AssetID = Hash(issuance_script)
  A = HashToPoint(AssetID)

Asset commitment (H,B):
  H = A + b*G
  B = b*J

Value commitment (V,F):
  V = v*H + f*G
  F = v*B + f*J

Value rangeproof proves that f is the same in V,F for some value v.

Balancing Vs and Fs ensures that v*A components must balance:

  V = v*A + (v*b + f)*G   -> balance
  F = (v*b + f)*J         -> balance
  => 
  v*A -> balance too

Then, I assume that ECDLP is broken for A1=a1*G, A2=a2*G.

Now, the only way to morph assets is to:

  1. either find a v1,v2 pair so that v1*a1 == v2*a2,
  2. or find a a2 for a given pair v1,v2 so that v1*a1 == v2*a2.

In both cases the space of v1/v2 mod L is restricted since values are at most 64-bit integers. And to get a valid a2, you need to go through NUMS process of hashing to a point - because you need to satisfy a chain of asset rangeproofs and these require clear preimages for the hashes in the issuance transaction (that's the case for both a cleartext issuance and a confidential ringsig-based issuance).

In other words, restricted ranges of v1, v2 make it computationally hard (even for QC) to satisfy that equation.

The challenge I have is to have a good upper bound on v1/v2 mod L where v1 and v2 are N-bit (e.g. 64-bit) integers, L is a large prime (≈2^252 or ≈2^256). Naïvely it looks like it's not more than 2^2N, which is good, but not great. I hope it's noticeably smaller than that.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 24, 2017

Ah, yeah, I think this is correct -- and I see that we lose the space savings because when you decompose V into digits you have to analogously decompose F. Frustrating.

Edit: Have you thought about doing a normal rangeproof for V and then separately proving that V and F have the same v, f? Or alternately doing a normal rangeproof of V - F? I suspect there is some simple reason these ideas don't work, but they would let us retain the space savings on the rangeproof..

Here "normal rangeproof" means the thing in this PR. Note that with the latter idea we'd need to decompose J into several NUMS generators just like we did with G.

@oleganza
Copy link

oleganza commented Apr 24, 2017

Have you thought about doing a normal rangeproof [...]?

Yes, I explored additional proofs "transferring" f from F1 = v*B + f*J1 to F2 = f*J2, but to make it sound it seems you need a separate commitment to v w/o extra blinding factors which makes it subject to bruteforce cracking (since it is not random and in short range). Or, you'd have to make a ring-proof of v which defeats the whole point of transfer in the first place.

@oleganza
Copy link

oleganza commented Apr 24, 2017

Offtopic for this PR, but what'd be your take on this problem?:

The challenge I have is to have a good upper bound on v1/v2 mod L where v1 and v2 are N-bit (e.g. 64-bit) integers, L is a large prime (≈2^252 or ≈2^256). Naïvely it looks like it's not more than 2^2N, which is good, but not great. I hope it's noticeably smaller than that.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 24, 2017

I thought about it briefly. I think it's roughly 2^2N, smaller but not a lot smaller.

Consider starting with all 2^2N pairs (v1, v2). For one quarter of possible v1/v2, you can multiply both numerator and denominator by 2 to get a redundant element that can be removed, so subtract 1/4 from the total. Similarly for 1/9 of the remainder you can multiply both top and bottom by 3, and so on for all the primes up to 2^N. This will give an underestimate because you can't actually remove "1/4 of the total", but only the floor of that number.

So the total underestimate is (2^2N)(1 - 1/4)(1 - 1/9)(1 - 1/25)...(1 - 1/p^2) where p is the largest prime less than 2^N.

I ran through this calculation in sage (using floating-point approximations) for N = 10, 15, 20 and in those cases I did not even shave an entire bit off of 2^2N.

@oleganza
Copy link

oleganza commented Apr 24, 2017

That was helpful! Could it be that other parts of 2^2N space are colliding mod L and we need to prune some pairs there too?

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 24, 2017

Unfortunately no, because the integers mod L are a field there can be no other collisions.

Btw I just completed a check for 2^32. Again not even a bit of reduction. In all cases it seems like the space is reduced by a factor of roughly 1.645, I think only the first few primes really matter to the calculation.

@oleganza
Copy link

That's the same factor I get in my simulation as well for low ranges and precise modulo arithmetic. Nice.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 25, 2017

I spent a while last night thinking about your solution. It's really clever, I guess the core of the technique is to force vb + f to balance along with va + vb + f and then va has to balance as well. I continue to think that there's a more efficient way to accomplish this than to construct F = vB + fJ and prove via simultaneous rangeproof that this has the same opening as V = vH + fG, but I haven't found one.

I'm worried now about your claim that the only way to break this is to find v1*a1 = v2*a2. I think this can be broken more generally by finding some set of v's and a's with v1*a1 + v2*a2 + ... + vn*an with each v value in [-2^N, 2^N]. (Negative numbers mean the asset has to appear as an input and positive ones mean they have to appear as an output, in an illegally transmuting transaction.) This is a transmutation equation from a combination of some set of assets into another combination. Say a1 is a valuable asset and all the rest are arbitrary issuances from an attacker.

I think with Wagner's algorithm an attacker should be able to produce the remaining a2 through an such that this equation can be satisfied, even though they are uncontrollably random.

Edit: "small assets", with a fixed list of asset types that can't be grinded, is not vulnerable to this because there are only a couple a values and Wagner's algo requires the attacker be able to produce many of them at will. So for Mimblewimble this is ok, but for issued assets it's not :(

@oleganza
Copy link

I hope you'd need an order of 2^N inputs and outputs (or, alternatively, 2^N transactions) to make that transmutation.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 25, 2017

Nope, you produce some large but doable number of a values (something like 2^30 or 2^40 if I remember right), find a subset of them which give you a simple sum like this (which will consist of a dozen or two values, if I remember right), and create a transaction with that subset.

Unfortunately I'm not aware of a simple writeup of this. The original paper is http://link.springer.com/chapter/10.1007/3-540-45708-9_19 but it takes a bit of work to translate it from xor into an ordinary sum of a values that adds to 0 (though Wagner says how to do this), and to get concrete performance numbers out of it...and then I'd guess that you can do even better than the paper if you're allowed to multiple the a's by arbitrary values in [-2^N, 2^N].

@oleganza
Copy link

oleganza commented Apr 25, 2017

Dammit. Will the Ed448 Goldilocks curve be of help here with its 448-bit order?

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 25, 2017

I believe increasing the curve size will make Wagner's algorithm slower, but not exponentially slower. I'd be really really hesitant to rely on this, especially in the face of a quantum computer. (I don't know if anyone has studied quantum speedups of Wagner's algo.)

I also don't like the idea of using the performance of Wagner as a measure of security, the fact that Wagner's algorithm exists at all was a surprise to me and without some proven computational lower bound, I don't like the idea of using any sum of independent adversarially-choosable random numbers in cryptography. Who knows what other algorithms might exist.

@oleganza
Copy link

Maybe you can increase the collision space by having M asset ID representations to which the same value is committed. And maybe that M could be proportional to number of inputs/outputs. So for short transactions where you don't have a lot of space for shenanigans, you have lower overhead.

@oleganza
Copy link

oleganza commented Apr 25, 2017

Lets say, asset A is represented with A1,A2 random points. Then, you can commit to v*a1 and v*a2 and make sure they individually balance. Now you have ≈512 random bits VS 64 bits of v.

Even better, what if we have the whole value encoded as v1*A1 + v2*A2 where v1 is the first bit, v2 is the second bit. Now you have 256-bit randomness against 1-bit value for each commitment. By encoding 64 bits with 64 A_i random multipliers we now have to work in space of size 2^(256*64) (2^16384) where we only have 2^64 allowed combinations. Will this make Wagner's algorithm prohibitively expensive?

Edit: this poses another problem, though: how do we implement homomorphic addition of commitments and handle overflow of 1+1=>2.

@oleganza
Copy link

Just a note: producing 2^30 a values means breaking ECDLP not once, but 2^30 times.

@apoelstra
Copy link
Owner Author

Heh, yes, that is pretty important as a practical consideration.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 27, 2017

Let's ignore the Wagner problem for now. It needs further study, but can be prevented by having a fixed list of assets at least. For issuance it might be sufficient to just require a spend of a utxo, and to take entropy not only from that utxo's txid:vout pair but also from the hash of the block in which it appeared...then an attacker can't precompute asset IDs, they'd actually have to put 2^30 outputs on the blockchain and see which ones were worth issuing assets out of.

So. To get your security model, how about this? As you described, we have a blind asset tag (H, B) describing an asset A. Suppose we have a surjection proof showing H = A + bG and B = bJ and this rangeproof (i.e. the one in the PR) which shows V = vH + rG. We want to show F = vB + rJ which by your argument gets us soundness, at least up to Wagner's attack.

As discussed I don't want to do a simultaneous rangeproof because this requires adding complexity to the rangeproof, pregenerating a split of J, and providing digits of F. (And personally, I'd have to change my PR, which is hard to do since I'm not convinced yet that I have to :))

Here's an alterate scheme. Prover thinks up a random scalar s. They then provide sV and sF and prove both ss are the same. They provide srG and srJ and prove both srs are the same. From here the verifier can compute svH = sV - srG and svB = sF - srJ and the prover shows both svs are the same. Total cost: four points, sV, sF, srG, srJ plus three proofs (totalling four scalars, since they can share a challenge). So about 8*32 bytes.

Verification of the extra proofs costs the same as doing six signature verifications.

I'll need some more work to show this is actually zero-knowledge in v, but I think it is.

@oleganza
Copy link

For issuance it might be sufficient to just require a spend of a utxo, and to take entropy not only from that utxo's txid:vout pair but also from the hash of the block in which it appeared...then an attacker can't precompute asset IDs, they'd actually have to put 2^30 outputs on the blockchain and see which ones were worth issuing assets out of.

That's an interesting mitigation, thank you. Sadly, it's not cryptographically robust, but it's pretty reasonable in practice. My concern is how much it would stifle the existing patterns involving asset issuance. Will have to investigate that further.

Three-move transfer

Sounds good. I've tried something very similar, but was having trouble with soundness without a direct X = v*Y commitment that ruins secrecy of v. Will have to spend more time analyzing this transfer, especially this part: svH = sV - srG, svB = sF - srJ. Because it's not proven that sr is actually s*r, but could be some other scalar. That may allow some malleability of v inside the commitment... I hope it'd work though. Bandwidth savings would be worth it.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 27, 2017

It's worth analyzing to see if it's necessary, but we can prove sr by proving rJ as part of the rangeproof and then proving srJ shares the same discrete log with respect to it as sV and sF. This requires zero additional space and one more signature verfication's worth of time.

Edit: Yeah, I think it's necessary. Good catch.

@oleganza
Copy link

Additional dlog proof within a rangeproof cannot be fiatshamirred under the rug due to soundness requirement, so it will require extra 2N scalar mults for N-bit number. Which is +33% CPU cost to 4N that you'd have already in a sound rangeproof with 2-point digits.

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 28, 2017

I'm saying that rJ is the other part of the el-gamal commitment, so proving this is already part of the 4N. Note that I just say "the rangeproof proves that V = vH + rG" above, so modify that to "the rangeproof proves that V = vH + rG has the same r as rJ".

@apoelstra
Copy link
Owner Author

apoelstra commented Apr 28, 2017

Updated commit to allow normal Boneh-sound borromean sigs with different r values on each ring. Not used in this PR, but will be in a later one related to surjection proofs.

Specifically, I want the surjection proofs to be sound, but also support 2^4 denominations using this scheme of amiller's.

@oleganza
Copy link

oleganza commented May 1, 2017

Oh, nice link to the Andrew Miller's exponent optimization. I've considered that too, but was also looking into a more generic solution that allows encoding a number with an arbitrary combination of constant-multiplication (with a variable base or variable exponent across the ring) and with proofs of multiplication of two commitments (sort of "blinded DDH proof"). I haven't got much time to extensively study that approach, maybe you did? My worry is that complicated ad-hoc encoding while saving space allows for a more efficient adversarial analysis and makes it harder to estimate privacy guarantees.

@apoelstra
Copy link
Owner Author

Well, today there is an explicit exponent in the rangeproofs (I'm not sure how often it is used), so hiding the exponent is definitely an improvement on that. It's also an improvement on the "denominations" scheme I had been thinking about, where basically there is a small fixed list of possible exponents people can use.

You can do a blinded DDH proof, I think my 3-step change-of-bases proof above for mapping V to F is pretty-much all you need.

In general I agree with your worry about ad-hoc encodings. But the exponent provides a huge space savings for common (round) amounts, so it's hard to take this tradeoff all the way to the "full privacy" direction, which would pretty-much require 52-bit rangeproofs everywhere.

@apoelstra
Copy link
Owner Author

I think I'm going to call the 3-step proof an "asset transfer proof" because it's a fairly general thing that lets you prove that two commitments have the same amount, while showing that you're changing the asset commitment. This may be important in the future for cross-chain pegs where asset IDs differ.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants