Skip to content

Commit

Permalink
Removed bytestring_bits_le helper function
Browse files Browse the repository at this point in the history
  • Loading branch information
rozbb committed Jul 30, 2023
1 parent 61d9e1a commit b06ae94
Showing 1 changed file with 23 additions and 18 deletions.
41 changes: 23 additions & 18 deletions curve25519-dalek/src/montgomery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,6 @@ impl Zeroize for MontgomeryPoint {
}
}

/// Given a bytestring that's little-endian at the byte level, return an iterator over all the
/// bits, in little-endian order.
pub(crate) fn bytestring_bits_le(x: &[u8]) -> impl DoubleEndedIterator<Item = bool> + '_ {
let bitlen = x.len() * 8;
(0..bitlen).map(|i| {
// As i runs from 0..256, the bottom 3 bits index the bit, while the upper bits index
// the byte. Since self.bytes is little-endian at the byte level, this iterator is
// little-endian on the bit level
((x[i >> 3] >> (i & 7)) & 1u8) == 1
})
}

impl MontgomeryPoint {
/// Fixed-base scalar multiplication (i.e. multiplication by the base point).
pub fn mul_base(scalar: &Scalar) -> Self {
Expand All @@ -138,12 +126,17 @@ impl MontgomeryPoint {
/// Multiply this point by `clamp_integer(bytes)`. For a description of clamping, see
/// [`clamp_integer`].
pub fn mul_clamped(self, bytes: [u8; 32]) -> Self {
// Clamp the integer, convert to bits, and multiply
let clamped = clamp_integer(bytes);
// Clamping sets the the MSB 0, so we skip it
let le_bits = bytestring_bits_le(&clamped).rev().skip(1);

self._mul_bits_be(le_bits)
// We have to construct a Scalar that is not reduced mod l, which breaks scalar invariant
// #2. But #2 is not necessary for correctness of variable-base multiplication. All that
// needs to hold is invariant #1, i.e., the scalar is less than 2^255. This is guaranteed
// by clamping.
// Further, we don't do any reduction or arithmetic with this clamped value, so there's no
// issues arising from the fact that the curve point is not necessarily in the prime-order
// subgroup.
let s = Scalar {
bytes: clamp_integer(bytes),
};
s * self
}

/// Multiply the basepoint by `clamp_integer(bytes)`. For a description of clamping, see
Expand Down Expand Up @@ -533,6 +526,18 @@ mod test {
EdwardsPoint::mul_base(&s)
}

/// Given a bytestring that's little-endian at the byte level, return an iterator over all the
/// bits, in little-endian order.
fn bytestring_bits_le(x: &[u8]) -> impl DoubleEndedIterator<Item = bool> + '_ {
let bitlen = x.len() * 8;
(0..bitlen).map(|i| {
// As i runs from 0..256, the bottom 3 bits index the bit, while the upper bits index
// the byte. Since self.bytes is little-endian at the byte level, this iterator is
// little-endian on the bit level
((x[i >> 3] >> (i & 7)) & 1u8) == 1
})
}

#[test]
fn montgomery_ladder_matches_edwards_scalarmult() {
let mut csprng = rand_core::OsRng;
Expand Down

0 comments on commit b06ae94

Please sign in to comment.