-
Notifications
You must be signed in to change notification settings - Fork 48
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
Add (R)OLE to mpz #103
Add (R)OLE to mpz #103
Conversation
47766a1
to
9e137d0
Compare
3af76ed
to
8661279
Compare
ccce5dd
to
ad39a0a
Compare
This will need to be adapted/rebased to the new architecture for IO. |
ad39a0a
to
c70c750
Compare
Rebased and adapted to new IO design. Should be ready for review. |
c70c750
to
950c87b
Compare
Rebased onto |
Im happy to review this once we all agree on what specific approach we will be taking for E2F and GHASH. For now, we only tentatively agreed to use the PADO's approach with modifications to work around the 0 input issue.
|
I haven't gone very deep in review here yet, but lets address some high level points:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some WIP review here that I'll just post in addition to my previous comment.
Additionally, I was expecting to see the use of a PRF in the OLEe implementation, but saw it no where? It looked like you are operating directly on the ROT messages instead of using them as keys to the PRF.
I think we can avoid any mention of ROT in this crate, we simply use ROT to sample the PRF keys for KOS16.
crates/mpz-ole-core/src/ideal/ole.rs
Outdated
use rand::{rngs::ThreadRng, thread_rng}; | ||
|
||
/// The OLE functionality | ||
pub struct OLEFunctionality<F> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend sticking to Ideal*
, "functionality" is a mouthful for a type name.
crates/mpz-ole-core/src/ole/mod.rs
Outdated
@@ -0,0 +1,3 @@ | |||
//! Provides implementations of OLE with errors (OLEe) protocols. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! Provides implementations of OLE with errors (OLEe) protocols. | |
//! Oblivious linear evaluation protocols |
The "with errors" should be a caveat documented on the specific implementation, not at the module level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're at it, we can be more verbose in our comments "oblivious linear evaluation" is also a short-hand which may be confusing to the uninitiated. The full term "oblivious linear function evalution", i.e. there exists a linear function which gets evaluated obliviously.
crates/mpz-ole-core/src/ideal/mod.rs
Outdated
@@ -0,0 +1,7 @@ | |||
//! This module provides ideal functionalities for OLE and ROLE. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! This module provides ideal functionalities for OLE and ROLE. | |
//! Ideal OLE functionalities. |
They're all just variants of OLE, we can keep the module doc general
@@ -0,0 +1,94 @@ | |||
//! This module provides an ideal ROLE functionality. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! This module provides an ideal ROLE functionality. | |
//! Ideal ROLE. |
Style wise, I think I prefer very succinct module and type headlines. It just reads cleaner with rustdoc to avoid leading words like "this module provides..." etc. Of course, its totally fine to be more verbose in the following description
use mpz_fields::Field; | ||
use rand::{rngs::ThreadRng, thread_rng}; | ||
|
||
/// The ROLE functionality |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// The ROLE functionality | |
/// Ideal ROLE. |
crates/mpz-ole-core/src/lib.rs
Outdated
//! This crate provides implementations of different Oblivious Linear Evaluation with Errors (OLEe) | ||
//! flavors. It provides the core logic of the protocols without I/O. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! This crate provides implementations of different Oblivious Linear Evaluation with Errors (OLEe) | |
//! flavors. It provides the core logic of the protocols without I/O. | |
//! Core implementations of various Oblivious Linear Evaluation protocols. |
/// Workaround because of feature `generic_const_exprs` not available in stable. | ||
/// | ||
/// This is used to check at compile-time that the correct const-generic implementation is used for | ||
/// a specific field. | ||
struct Check<const N: usize, F: Field>(std::marker::PhantomData<F>); | ||
|
||
impl<const N: usize, F: Field> Check<N, F> { | ||
const IS_BITSIZE_CORRECT: () = assert!( | ||
N as u32 == F::BIT_SIZE / 8, | ||
"Wrong bit size used for field. You need to use `F::BIT_SIZE` for N." | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should just add an associated const BYTE_SIZE
to Field
crates/mpz-ole-core/src/role/mod.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this entire module and focus on OLEe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nice thing of going from ROLE -> OLE is that ROLE can be preprocessed. If we do not use ROLE to instantiate OLE then we probably go with Gilboa99, which does not allow preprocessing.
00cd519
to
73441ff
Compare
Thanks for the review.
|
I went the route of using PRNGs for ROLE. So that you also have a Setup call and Extend calls. I don't think that this works. Relevant PR tlsnotary/docs-mdbook#65 |
In steps 1 and 2 of your
KOS16 indeed does implement VOLE, or in our case I'm not quite sure that your protocol is secure. Re-iterating, it looks to me to be COPEe where each extend call to COPEe is then followed by a share adjustment to convert the VOLE into an OLE. This would imply you can get n-OLE from VOLE simply with this share adjustment. Maybe that's true, but it's not self-evident to me that it's secure. |
I am not sure what you mean by
When I designed this, I tried to come up with with a |
- also fixed bug in ideal functionality of role
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Algorithms LGTM 👍
I would suggest that you refactor a bit more to remove the *Sender
and *Receiver
types, as they have no internal state and complicate the API. Instead of an actor operating on data, we should instead provide newtypes for the data and implement the API directly on them. For example:
pub struct SenderShare<F>(F);
impl<F: Field> SenderShare<F> {
pub fn new(share: F, corr: [[F; 2]; F::BIT_LENGTH]) -> (Self, MaskedInput<F>) {
...
}
pub fn adjust(self, target: F) -> (SenderAdjust<F>, ShareAdjust<F>) {
...
}
}
pub struct ReceiverShare<F>(F);
impl<F: Field> ReceiverShare<F> {
pub fn new(
share: F,
sender_input: MaskedInput<F>,
corr: [F; F::BIT_LENGTH]
) -> Self {
...
}
pub fn adjust(self, target: F) -> (ReceiverAdjust<F>, ShareAdjust<F>) {
...
}
}
pub struct ShareAdjust<F>(F);
pub struct SenderAdjust<F>(F);
impl<F: Field> SenderAdjust<F> {
pub fn finish(self, receiver_adjust: ShareAdjust<F>) -> SenderShare<F> {
...
}
}
pub struct ReceiverAdjust<F>(F);
impl<F: Field> ReceiverAdjust<F> {
pub fn finish(self, sender_adjust: ShareAdjust<F>) -> ReceiverShare<F> {
...
}
}
This would just be the core API, we can still add the sender and receiver types to store the preprocessed OLEs
pub fn generate( | ||
&self, | ||
delta_k: &[F], | ||
t_delta_i: &[[u8; N]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t_delta_i
can instead be [F]
and its up to the user to provide it in that format. We can add the bit iterator trait as a bound on F (not on the Field trait itself).
))); | ||
} | ||
|
||
let delta_i: Vec<bool> = delta_k.iter_lsb0().collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we can avoid this extra allocation using iterator combinators
/// # Returns | ||
/// | ||
/// * `ui` - The correlations, which will be sent to the receiver. | ||
/// * `t0k` - The sender's final OLE output summands. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are simply "the Sender's shares", maybe ak
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to use the MASCOT paper's notation for this module, so that understanding it and checking for correctness is as easy as possible.
crates/mpz-ole-core/src/ideal.rs
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than having multiple methods here which mutable some internal state of the functionality, I think it can simply provide a method like:
pub fn execute<F: Field>(
&mut self,
sender_input: Vec<F>,
receiver_input: Vec<F>
) -> (Vec<F>, Vec<F>)
Alright, I tried it out and it seems to work out quite nicely. |
- also use correct type for `adjust` methods.
- Shifted share logic to `core` module.
- Added tests. - Refactored test helper functions.
Closing in favor of #135. |
This PR adds OLE and ROLE to mpz by introducing two new crates and creates the building blocks, like e.g. traits and module structure, for future OLE flavors and additional implementations.
I still need to do some small improvements here and there, but thought it is a good idea to get it out now.Ready for review.