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

Updates for CGGMP'24 #170

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft

Updates for CGGMP'24 #170

wants to merge 21 commits into from

Conversation

fjarri
Copy link
Member

@fjarri fjarri commented Dec 17, 2024

Fixes #157
Fixes #43
Fixes #91
Fixes #5 (in progress)

  • Updated paper references in PAPER.md, removed obsolete items.
  • Updated to the new range definition (±2^l now means [-2^(l-1)+1, 2^(l-1)] instead of the previous [-2^l, 2^l]). This caused a bit of a chain reaction:
    • SecretSigned::assert_exponent_range() logic changed.
    • SecretSigned::random_in_exp_range*() logic changed, and also exp was changed to exponent to match the assertion name.
    • PublicSigned::from_xof_reader_bounded() changed its behavior to produce the number according to the new range definition, and was renamed to from_xof_reader_in_range().
    • PublicSigned::in_range_bits() changed its behavior according to the new range definition, and was renamed to is_in_exponent_range().
    • Wherever scalars are passed to proofs and Ciphertext constructor they are passed as SecretSigned, to comply with the range requirements in the proofs.
    • conversions::secret_unsigned_from_scalar() removed.
    • Added SecretSigned::new_modulo() constructor to make a signed number in range [-N/2, N/2] from an Uint in range [0, N).
    • Removed Ciphertext::new() and decrypt() (which took unsigned plaintexts), renamed new_signed() and decrypt_signed() to new() and decrypt().
    • Ciphertext::new_with_randomizer() was renamed to new_with_randomizer_unsigned(), since it's now a special one, only used in P_mul. Renamed new_with_randomizer_signed() to new_with_randomizer(), and new_public_with_randomizer_signed() to new_public_with_randomizer().
  • Following that, wherever in the paper e <-- ±q is used, we are sampling the challenge as a Scalar using the new Scalar::from_xof_reader() method (and using that in П^sch as well).
  • Updated paper references and notation in aff-g proof.
  • Updated paper references in prm proof, and started using BitVec for its commitment.
  • Updated dec proof (there were significant changes). Temporarily, it is located in dec_new.rs, will be moved to dec.rs when Presigning is updated.
  • Added elog proof.
  • Added enc-elg proof.
  • Added aff-g* proof.
  • Updated paper references and notation in fac proof, and implemented necessary changes to the algorithm (some variables are calculated differently, and the challenge is now a signed Uint and not a Scalar)
  • Updated paper references and notation in mod proof, and enforced invertibility conditions that were added in '24
  • Updated paper references and notation sch proof
  • Removed enc, log*, mul, mul* proofs - they are not used anymore.
  • Encapsulated the invertibility check in an IsInvertible trait, documenting the choice between GCD and invert()
  • Updated KeyInit and filled in the code for evidence generation/checking. In particular, fixed Self-contained proof of malicious behavior for Round 3 of KeyGen #103 (by using an echo broadcast in Round 2)
  • Updated KeyRefresh to the new version and filled in the code for evidence generation/checking.
  • Updated Presigning/Signing to the new version

TODO:

  • There is still a question of how to trigger aff-g* star checks in Rounds 5 and 6 - what kind of messages does a malicious node need to send? Are they even needed given that we echo-broadcast D, F, \hat{D}, and \hat{F}?
  • Implement AuxGen by cutting out parts of KeyRefresh responsible for share changes (this should wait until we stabilize all the shortcuts and code style)
  • Implement the recommended scheme parameters from Section C.1. Note that there are two possible sets, for 112 bits and 128 bits of security.

@fjarri fjarri self-assigned this Dec 17, 2024
Copy link

codecov bot commented Dec 19, 2024

Codecov Report

Attention: Patch coverage is 96.37496% with 128 lines in your changes missing coverage. Please review.

Project coverage is 95.89%. Comparing base (a3bbfc6) to head (add029f).

Files with missing lines Patch % Lines
synedrion/src/cggmp21/aux_gen.rs 43.13% 29 Missing ⚠️
synedrion/src/www02/key_resharing.rs 30.55% 25 Missing ⚠️
synedrion/src/cggmp21/entities.rs 79.24% 11 Missing ⚠️
synedrion/src/cggmp21/key_refresh.rs 98.28% 9 Missing ⚠️
synedrion/src/tools/protocol_shortcuts.rs 85.24% 9 Missing ⚠️
synedrion/src/cggmp21/sigma/aff_g_star.rs 96.51% 7 Missing ⚠️
synedrion/src/cggmp21/interactive_signing_tests.rs 99.06% 6 Missing ⚠️
synedrion/src/cggmp21/key_init.rs 95.62% 6 Missing ⚠️
synedrion/src/cggmp21/sigma/enc_elg.rs 97.12% 5 Missing ⚠️
synedrion/src/tools/protocol_shortcuts_dev.rs 97.40% 4 Missing ⚠️
... and 8 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #170      +/-   ##
==========================================
+ Coverage   92.46%   95.89%   +3.43%     
==========================================
  Files          35       37       +2     
  Lines        7030     9454    +2424     
==========================================
+ Hits         6500     9066    +2566     
+ Misses        530      388     -142     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@fjarri fjarri force-pushed the new-cggmp branch 10 times, most recently from 12afc7a to e0565ce Compare December 25, 2024 21:04
@fjarri fjarri force-pushed the new-cggmp branch 2 times, most recently from cdb7c84 to 0ca10d8 Compare December 31, 2024 22:56
@fjarri fjarri force-pushed the new-cggmp branch 2 times, most recently from 0fc38fb to 235afa0 Compare January 3, 2025 22:51
@fjarri fjarri force-pushed the new-cggmp branch 9 times, most recently from 3efcfd4 to 0f86f18 Compare January 10, 2025 02:47
Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have looked at Key_init and Key_refresh tests only.

As mentioned I think it's very cool to see the fault injection machinery come together, it's going to be a major help. The code is verbose and repetitive at times, but this is a complex protocol and its tests are always going to reflect that complexity.
Having the right testing tools is about finding that delicate balance between readability&maintainability and expressiveness. I'm sure we'll fiddle with this plenty mroe in the future but this strikes me as much better than we had before.

.collect()
}

fn check_evidence<M>(expected_description: &str) -> Result<(), LocalError>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming nitpick: this does more than merely checking some data against some other; it actually drives the protocol (and checks the outcome). In my head "check" is more "compare these two things and yell if they don't match".

How about a refactor to something more classic like "let r: Result<…, …> = run(); assert_eq!(r, …, "bla bla");"?

Less invasively: a rename to assert_outcome(expected)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a refactor to something more classic like "let r: Result<…, …> = run(); assert_eq!(r, …, "bla bla");"?

It checks a number of things internally:

  • the malicious node does not create any malicious behavior evidence
  • all the other nodes create an evidence for the malicious node
  • the evidence description matches the expected one

Not sure if it's worth packing in one variable.

synedrion/src/cggmp21/key_init_tests.rs Show resolved Hide resolved
synedrion/src/cggmp21/key_init_tests.rs Show resolved Hide resolved
synedrion/src/cggmp21/key_refresh_tests.rs Outdated Show resolved Hide resolved

fn check_evidence<M>(expected_description: &str) -> Result<(), LocalError>
where
M: Misbehaving<Id, (), EntryPoint = KeyRefresh<P, Id>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a pity that check_evidence and make_entry_points have to be instantiated for each EntryPoint. As a new reader of the code, I have to look rather carefully before I spot that this one is for KeyRefresh and the other is KeyInit.
Maybe we can have a macro at some point to make the critical parts more visible, e.g.:
check_evidence!(KeyInit, …, …);
check_evidence!(KeyRefresh, …, …);

synedrion/src/tools/protocol_shortcuts_dev.rs Show resolved Hide resolved
EP: 'static + Debug + EntryPoint<SP::Verifier>,
SP: SessionParameters,
{
let prefix = match part {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, but maybe "phase" is more descriptive than "part" here? ModifyPhase and CheckPhase etc?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not really a phase, since they are delivered simultaneously. It mimics the ProtocolMessagePart terminology from manul

synedrion/src/tools/protocol_shortcuts_dev.rs Outdated Show resolved Hide resolved
synedrion/src/tools/protocol_shortcuts_dev.rs Outdated Show resolved Hide resolved
synedrion/src/cggmp21/key_init_tests.rs Show resolved Hide resolved
@fjarri fjarri force-pushed the new-cggmp branch 5 times, most recently from 9a937ba to d3a940f Compare January 22, 2025 23:59
Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of PAPER.md and README.md

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
PAPER.md Show resolved Hide resolved
PAPER.md Show resolved Hide resolved
PAPER.md Show resolved Hide resolved

Q: In Fig. 5 the initial commitment in the Schnorr proof (`A_i`) is sent twice (in R2 and then R3, as a part of `psi_i`), and then the equality of those two values is checked in Output, right before checking the proof itself. But the commitment value is used right after that in the `vrfy` step, so if it doesn't match the rest of the proof, the verification will fail. So is there any security reason for sending the commitment twice? (I understand that it does constitute a minor performance optimization)
The above item leads to another problem. If those values are indeed echo-broadcasted, what malicious actions of one node can lead to passing the `П^{dec}` check on other nodes, but failing one of the `П^{aff-g*}` ones?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a little bit concerning. Something worth asking the authors directly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did, about a week ago (along with sending them the list of all the other new typos). No response yet.

I guess it's not concerning for them since it's an extra check, not a missing check, so it doesn't compromise the security. But it is concerning for me since I can't test it :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it sort of hinges on whether we're interested in provable aborts. The authors always talk about identifiable aborts only, which don't need echo-broadcasting of those values, so these checks may be needed to make the П^{aff-g*} aborts identifiable. But my understanding is that we do want provable aborts (which I questioned in entropyxyz/manul#39), so I'm operating based on that.

PAPER.md Outdated Show resolved Hide resolved
Copy link
Contributor

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed aff_g_star.rs

Comment on lines +90 to +92
elements: Box<[AffGStarProofElement<P>]>,
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really ok to crash the whole process when this happens? I mean maybe it is, but perhaps it's a design constraint we should make very clear that we're making: when synedrion encounters a catastrophic error (a bug) it will go down.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment supposed to be attached to the assertions at the start of new()? I thought about it myself, and actually thought I filed an issue about it, but I guess I haven't. Filed #181

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR though.

synedrion/src/paillier/rsa.rs Outdated Show resolved Hide resolved
Comment on lines +112 to +126

let cap_a = (public.cap_c * &alpha + Ciphertext::new_with_randomizer(public.pk0, &beta, &r)).to_wire();
let cap_r = secret_scalar_from_signed::<P>(&alpha).mul_by_generator();
let cap_b = Ciphertext::new_with_randomizer(public.pk1, &beta, &s).to_wire();

let ephemeral = AffGStarProofEphemeral::<P> { alpha, beta, r, s };
let commitment = AffGStarProofCommitment { cap_a, cap_r, cap_b };

(ephemeral, commitment)
})
.unzip();

let mut reader = XofHasher::new_with_dst(HASH_TAG)
// commitments
.chain(&commitments)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the Shamir transform right? How can I double check (against the paper?) that we actually have all the data that we need baked into the reader? Does the order of the params matter here you reckon?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, Shamir transform. That's described in Section 3.4.1. x there are the public parameters, and w are the secret parameters. So as far as I understand it, it prescribes hashing both the public parameters and the commitment into the challenge.

Ideally I think we should have the corresponding public parameters struct to implement Hashable, that will remove the need for duplication of the parameter list.

As for the order, I don't think it matters, it's a hash after all. As long as it's the same on both sides.

synedrion/src/cggmp21/sigma/aff_g_star.rs Show resolved Hide resolved
synedrion/src/cggmp21/sigma/aff_g_star.rs Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment