-
Notifications
You must be signed in to change notification settings - Fork 96
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
Evaluate whether we can use Secret Store's DKG, and secp256k1 for threshold schemes. #54
Comments
Schnorr threshold signaturesLet Simple signaturesA secret key is an let k = random();
let r = k * g;
let e = hash((r, msg));
let s = k - sk * e;
let sig = (s, e); Note that e == hash((s * g + e * pk, msg)) The value Threshold signaturesDKG creates signature shares sk[0] == interpolate(0, [(1, sk[1]), …, (t + 1, sk[t + 1])]); Similarly, the Using the same DKG, we can create a random Node let e = hash((r[0], msg));
let s[i] = k[i] - sk[i] * e;
let sig[i] = (s[i], e); (The value Interpolation is linear, so given a list s[0] == interpolate(0, s_vec) Again, disclosing any Threshold signatures in a single message round?For the common coin, running a full DKG in each coin flip is prohibitively slow. We still want a single-message-round coin! I was hoping we could e.g. in the setup phase generate some number It certainly isn't for s[j][i] == k[j][i] - sk[i] * e[j]; // for each `j`, so:
2 * s[1][i] - s[0][i] - s[2][i] == sk[i] * (2 * e[1] - e[0] - e[2]);
sk[i] == (2 * s[1][i] - s[0][i] - s[2][i]) / (2 * e[1] - e[0] - e[2]); I suspect something like that also works for |
It doesn't really make sense to use threshold Schnorr signatures for a common coin. In order to make a threshold Schnorr signature, you already need to somehow generate shares of a unique random value. But then you can just reconstruct that random value directly instead of using it in a Schnorr scheme. As for generating a random value more easily: It's not one round, but if you already have |
Thank you! You're right, those But in the end I think "not one round" is too high a price to pay: Our pairing-based single-round common coin won't actually be that much code, and every added message round means more latency in the consensus algorithm in the end. So I'm in favor of taking the approach in #47 instead. |
Oh, here's a nice idea: Use the same BLS-style threshold signature scheme, but instead of testing a share I haven't fully thought it through (will do so tomorrow), but I believe you can also do a similar system for threshold decrypting of ElGamal encryptions without using pairings. This would allow fully removing the pairing-based crypto from the protocol. @amiller you might also be interested in this. |
This kind of approach is very interesting. It would definitely be great to remove the need for pairing crypto. But I am not sure on balance if this tradeoff is worth it anyway, and also, do you think there's a way to get the same optimism option even in just a DDH group? |
Good point. The best idea I can come up with for optimistic verification would be to modify the NIZK, so that rather than the prover generating the sigma protocol challenge in the clear as the hash of its commitments, the verifier precomputes a random challenge Using this modification, rather than getting I think that an RSA library could be used to write a simple implementation of Benaloh's additively homomorphic scheme, so this isn't an awful solution. Still better than using pairings I think, but still maybe a bit more of a pain than one would like. (Note as well though, that if you do the idea mentioned in that linked issue, of verifying normal signatures over the shares, then since verifying each NIZK is not significantly different computationally from verifying a signature, it would be reasonable to avoid the optimism entirely) |
If I understand correctly (using additive pseudo-Rust), the signature share a1[i] = r[i] * g;
a2[i] = r[i] * hash(msg);
f[i] = r[i] + c * sk[i]; for some random The verifier checks that: f[i] * g == a1[i] + c * pk[i] &&
f[i] * hash(msg) == a3[i] + c * sig[i] With the corresponding Lagrange coefficients main_sig = lc[0] * sig[0] + ... + lc[t] + sig[t];
main_a1 = lc[0] * a1[0] + ... + lc[t] + a1[t];
main_a2 = lc[0] * a2[0] + ... + lc[t] + a2[t];
main_f = lc[0] * f[0] + ... + lc[t] + f[t]; Then that would be a valid group signature (including the valid proof), but For |
The default way of doing things would be to have For aggregatable proofs, my idea was to go after the second option: keep |
Actually after more thought the additive homorphism idea was dumb. Encrypting/decrypting the |
Here's a more reasonable way of doing optimism. I'll describe it as a three-round protocol, but the first two steps can be done in advance by pipelining with the previous coin flip messages. It's maybe a bit annoying to implement since it requires pipelining, but it's efficient. To start, everyone sends Using the pipelining, node |
Thanks, you're right, I think I get the additive homorphism idea now! 🎉
😩 By pipelining you mean that the message contains the third step of the current coin flip, the second step of the next one, and the first one of the one after that? I think in Honey Badger the flips aren't really totally ordered: we may need only one or two flips for each instance of ABA (often none at all), but there are several ABA instances in parallel. So if we'd use this method, we'd have a separate coin for each proposer (i.e. for each of the parallel ABA instances), but we'd need to reuse the coin from epoch 41's proposer 5 ABA for epoch 42's proposer 5 ABA to avoid having to restart the two-step initialization. The latter could only start once the former has terminated for everyone, we'd need to keep track of how often the coin was flipped (so the simple |
Good point about needing to keep track of how many coin rounds happened in an epoch. Alternatively you can avoid pipelining on the coins themselves and instead pipeline on the A further alternative is to avoid pipelining entirely and split the coin in two calls: |
Parity's Secret Store implements ECDKG to generate secpk256k1 key shares: It generates a random polynomial
f
of degreet
inZn
(integers modulon
), wheren
is the order of the group secpk256k1 (G
) and distributes the valuef(i)
to nodei > 0
, without any node knowing the polynomial. The valuesf(i) * g
, withg
the base point ofG
, are public.This is used for threshold Schnorr signatures, where ECDKG generates both the nodes' secret keys (once) and the shares for the random nonce
r
(once per signing protocol execution).G
doesn't seem to have a pairing, and DDH is probably infeasible due to its large embedding degree. So our threshold schemes (#38, #40) don't work in it.Questions:
G
?The text was updated successfully, but these errors were encountered: