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

Share recovery and refreshing #26

Merged
merged 15 commits into from
Jan 13, 2023
Merged

Share recovery and refreshing #26

merged 15 commits into from
Jan 13, 2023

Conversation

piotr-roslaniec
Copy link

@piotr-roslaniec piotr-roslaniec commented Jan 4, 2023

  • Based on Simple threshold decryption #20
    • Please review parent PR first
    • Already rebased
  • Closes DKG Key Refreshing via Proactive secret sharing #3
  • Implement share refreshing and share recovery, or "PSS" (Proactive Secret Sharing)
  • How to review this PR:
    • This PR adds three tests in tpke/src/lib.rs that contain three different PSS flows:
      • simple_threshold_decryption_with_share_refreshing_at_point - refreshes a key share knowing the evaluation point of a selected PSS participant
      • simple_threshold_decryption_with_share_recovery_at_point - recovers a key share with no knowledge of the evaluation point of a selected participant. Effectively, we generate a new key share for a new participant. Uses the same implementation as the previous test (section 4.2)
      • simple_threshold_decryption_with_share_refresh - refreshes all key shares for all existing participants. Uses a slightly different approach than the previous implementations
    • You should start by reading the tests and inspecting function calls one by one
    • Code specific to PSS is placed in tpke/src/refresh.rs
    • Other changes are largely irrelevant (code refactoring, comments, todos, etc.)

tpke/src/lib.rs Show resolved Hide resolved
tpke/src/refresh.rs Show resolved Hide resolved
tpke/src/refresh.rs Outdated Show resolved Hide resolved
tpke/src/lib.rs Outdated
@@ -140,7 +136,7 @@ pub fn setup<E: PairingEngine>(
// F_0 - The commitment to the constant term, and is the public key output Y from PVDKG
// TODO: It seems like the rest of the F_i are not computed?
let pubkey = g.mul(x);
let privkey = h.mul(x);
let privkey = h.mul(x); // ek_i in PVSS?
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
let privkey = h.mul(x); // ek_i in PVSS?
let privkey = h.mul(x);

No, this is the private key share, which is different from the protocol-level "private key" (which can be very confusing). Let's call ek_i the (private) blinding key.

tpke/src/lib.rs Outdated
checked_decrypt_with_shared_secret(&ciphertext, aad, &shared_secret)
});
assert!(result.is_err());
}

#[test]
fn simple_threshold_decryption_with_share_refreshing_at_point() {
Copy link
Member

Choose a reason for hiding this comment

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

I think the name "share refresh" here is confusing. We need to agree on a naming convention. Let's assume N is the original number of shares, and t is the threshold. There are 2 different types of share calculation protocols, used in 3 different ways:

  1. Ñ parties (where t <= Ñ <= N) jointly execute a "share refresh" or "share renewal" algorithm, and the output is M new shares (with M <= Ñ), with each of the M new shares substituting the original share (i.e., the original share is deleted). I personally like "share refresh" but the original paper calls it "share renewal" (also fine).
  2. Ñ parties (where t <= Ñ <= N) jointly execute a "share recovery" algorithm, and the output is 1 new share. There are 2 potential variants here:
    2.1. The new share is intended to restore a previously existing share, e.g., due to loss or corruption. It could also be used to on-board a new participant but reusing a previously existing share (sounds like a bad idea, though)
    2.2. The new share is independent from the previously existing shares. We can use this to on-board a new participant into an existing cohort.

In this test, you're actually doing 2.1, but the name "share refresh" is confusing to me. Let's settle in a convention for naming algorithms 1, 2.1 and 2.2 and use it consistently.

d_i
}

fn evaluate_polynomial<E: PairingEngine>(
Copy link
Member

Choose a reason for hiding this comment

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

Maybe there's an arkworks method for this.

Copy link

Choose a reason for hiding this comment

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

let i = p.index;
let x_i = p.public_decryption_contexts[i].domain;
let eval = evaluate_polynomial::<E>(coeffs, &x_i);
let h_g2 = E::G2Projective::from(p.h);
Copy link
Member

Choose a reason for hiding this comment

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

This could be taken outside of the loop, or even moved to a public context, since it's just the H generator in projective representation.

Copy link
Author

Choose a reason for hiding this comment

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

In tpke, public context corresponds to variables shared with other participants, and since they already have h there is no reason to put it there.

The different structs in tpke are going to be refactored so that should bring a bit more clarity.

tpke/src/lib.rs Outdated
@@ -269,6 +265,7 @@ pub fn setup_simple<E: PairingEngine>(
g,
g_inv: E::G1Prepared::from(-g),
h_inv: E::G2Prepared::from(-h),
h, // TODO: Remove this sensitive data here
Copy link
Member

Choose a reason for hiding this comment

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

What sensitive data?

Copy link
Author

@piotr-roslaniec piotr-roslaniec Jan 11, 2023

Choose a reason for hiding this comment

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

It's a left-over TODO. h is just a G2 generator, so it's not sensitive. I didn't know any better when I wrote it, sorry about the confusion.

tpke/src/lib.rs Outdated
p.public_decryption_contexts.pop();
}

// Refresh the share
Copy link
Member

Choose a reason for hiding this comment

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

See comment above wrt to naming convention. The method here is called share recovery but the comment here says refresh.

let recovered_key_share = PrivateKeyShare {
private_key_shares: vec![y_r.into_affine()],
};

Copy link
Member

Choose a reason for hiding this comment

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

We don't need to create decryption shares and encryption/decryption. We can simply reconstruct the original secret before and after. To do so, we just need to get the context.private_key_share elements and combine them with the proper lagrange coefficients.

make_decryption_share(&private_share, &ciphertext)
})
.collect();

Copy link
Member

Choose a reason for hiding this comment

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

Same as above. After the share refreshing algorithm, the shared secret should remain the same.

tpke/src/lib.rs Outdated
.collect::<Vec<_>>();
let lagrange = prepare_combine_simple::<E>(shares_x);

let shared_secret =
Copy link
Member

Choose a reason for hiding this comment

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

This name is confusing. The ferveo paper call this ephemeral shared secret, but I think the word "shared" is misleading and doesn't add anything. Let's rename this to ephemeral secret.

This is important to avoid confusion with the real shared secret (i.e. the distributed secret after the DKG protocol)

let i = p.index;
let mut new_y = E::G2Projective::from(
p.private_key_share.private_key_shares[0], // y_i
);
Copy link
Member

Choose a reason for hiding this comment

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

Why they need to be converted into Projective form?

Copy link
Author

Choose a reason for hiding this comment

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

In arkworks, Projective form is preferred since it "is generally more efficient for arithmetic". The PrivateKeyShares are G2Affine and so we convert to it later on.

@piotr-roslaniec piotr-roslaniec changed the base branch from simple-decryption to main January 11, 2023 14:47
@piotr-roslaniec
Copy link
Author

@theref @cygnusv I've addressed your comments, I just need a thumbs up and we can merge this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Completed
Development

Successfully merging this pull request may close these issues.

DKG Key Refreshing via Proactive secret sharing
3 participants