diff --git a/src/scalar.rs b/src/scalar.rs index 294f127..5d12d6b 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -32,6 +32,7 @@ use std::ops::{Index, IndexMut}; use rand::Rng; use field::{load3, load4}; +use util::CTAssignable; /// The `Scalar` struct represents an element in ℤ/lℤ, where /// @@ -61,6 +62,37 @@ impl IndexMut for Scalar { } } +impl CTAssignable for Scalar { + /// Conditionally assign another Scalar to this one. + /// + /// ``` + /// # use curve25519_dalek::scalar::Scalar; + /// # use curve25519_dalek::util::CTAssignable; + /// let a = Scalar([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /// 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + /// let b = Scalar([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + /// 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]); + /// let mut t = a; + /// t.conditional_assign(&b, 0u8); + /// assert!(t[0] == a[0]); + /// t.conditional_assign(&b, 1u8); + /// assert!(t[0] == b[0]); + /// ``` + /// + /// # Preconditions + /// + /// * `choice` in {0,1} + // XXX above test checks first byte because Scalar does not impl Eq + fn conditional_assign(&mut self, other: &Scalar, choice: u8) { + // if choice = 0u8, mask = (-0i8) as u8 = 00000000 + // if choice = 1u8, mask = (-1i8) as u8 = 11111111 + let mask = -(choice as i8) as u8; + for i in 0..32 { + self[i] ^= mask & (self[i] ^ other[i]); + } + } +} + impl Scalar { /// Return a `Scalar` chosen uniformly at random using a CSPRNG. /// Panics if the operating system's CSPRNG is unavailable.