-
Notifications
You must be signed in to change notification settings - Fork 477
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
curve25519: Add arbitrary integer multiplication with MontgomeryPoint::mul_bits_be
#555
Conversation
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.
ACK ed53307 reviewed the code and it seems correct, haven't tested it yet
curve25519-dalek/src/montgomery.rs
Outdated
fn mul_bits_be(self, bits: impl Iterator<Item = bool>) -> MontgomeryPoint { | ||
self.mul_bits_be(bits) |
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.
Is this supposed to be pub
?
It looks like it calls itself and infinitely recurses? Is it supposed to call self._mul_bits_be
?
If the intent is for this to be pub
, I worry about people accidentally discovering it. Feature-gating on hazmat
alone isn't a great deterrent since other dependencies can activate the feature. Putting it in the hazmat
module would better prevent accidental discovery/misuse IMO (and free up the mul_bits_be
name so you don't need a _
-prefixed version)
At the very least, it could use a more stringent warning label.
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.
Oh good points. I agree it'd be best to put it in the hazmat
module. Will fix.
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.
Acutally, this is a question: should this method be feature-gated? There's two main misuses I can think of:
- If someone used this method instead of
mul_clamped
. This could leak up to 3 secret bits. Not great. - If someone used this method instead of
Mul<Scalar> for MontgomeryPoint
. This would be fine, actually. In the worst case, this is equivalent to doing the scalar mul. In the best case, this is more correct than the scalar mul, because the point being multiplied might not be in the prime-order subgroup, and so the scalar mul made no sense anyway.
So the question is if case (1) is likely and worth avoiding. I'm not sure. If someone wanted to multiply by some arbitrary bytestring today, they can already do Scalar::from_bytes_mod_order(bytes) * point
. If the bytestring is uniform, then this is already equivalent to mul_bits_be
with 50% probability.
My vote is to let this function be public, and let it have the documentation note I just added.
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 have a wild suggestion, how do people think about a RingElement
type that is over the full curve's order? is this too much for that kind of feature?
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.
My vote is to let this function be public, and let it have the documentation note I just added.
@rozbb seems okay if it comes with a warning and steers people towards the other options unless they know what they're doing.
Edit: looks like you do already have a note about using mul_clamped
, so that's fine
is this too much for that kind of feature?
@elichai might be overkill
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.
RingElement is overkill imo. We don't define a way to add or multiply two numbers mod 8p, so it'd be a pretty useless ring element. Integer multiplication is broad enough for this use case imo
curve25519-dalek/src/montgomery.rs
Outdated
/// Curve25519 uses _clamped multiplication_, explained | ||
/// [here](https://neilmadden.blog/2020/05/28/whats-the-curve25519-clamping-all-about/). | ||
/// When in doubt, use [`Self::mul_clamped`]. | ||
pub fn mul_bits_be(self, bits: impl Iterator<Item = bool>) -> MontgomeryPoint { |
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.
Do we care that this doesn't enforce how many bits are passed? ie you can pass an empty iter and it will be equivalent to multiplying by zero, or you can pass a longer iterator and compute a "longer" multiplication
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.
Should it use ExactSizeIterator
and assert len == 256? that would still allow multiplying by something bigger than the curve's order though
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 do like how it's infallible now.
Perhaps it could have a debug_assert!
? That wouldn't necessarily require ExactSizeIterator
, it would just need a sort of postcondition check that it iterated over 256 bits.
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.
Why limit the function at all? Multiplication by arbitrary integers is always well-defined. If you don't want to reduce then you're free not to
There is occasionally a need to multiply a non-prime-order Montgomery point by an integer. There's currently no way to do this, since our only methods are multiplication by
Scalar
(doesn't make sense in the non-prime-order case), andMontgomeryPoint::mul_base_clamped
clamps the integer before multiplying.So we define
MontgomeryPoint::mul_bits_be
, gated behindhazmat
, which takes a big-endian representation of an integer and multiplies the point by that integer.cc @elichai