From 58a55117be50fda390380a5596a21cc2456d7efa Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Sat, 8 Jul 2017 18:22:28 -0700 Subject: [PATCH] Rename Decaf to Ristretto --- src/constants.rs | 14 +- src/edwards.rs | 14 -- src/lib.rs | 2 +- src/{decaf.rs => ristretto.rs} | 333 +++++++++++++++++---------------- 4 files changed, 177 insertions(+), 186 deletions(-) rename src/{decaf.rs => ristretto.rs} (67%) diff --git a/src/constants.rs b/src/constants.rs index 4c08102..f2bca03 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -20,7 +20,7 @@ use edwards::CompressedEdwardsY; #[cfg(feature = "yolocrypto")] -use decaf::{DecafPoint, DecafBasepointTable}; +use ristretto::{RistrettoPoint, RistrettoBasepointTable}; use montgomery::CompressedMontgomeryU; use scalar::Scalar; @@ -61,10 +61,10 @@ pub const BASE_COMPRESSED_MONTGOMERY: CompressedMontgomeryU = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); -/// The Ed25519 basepoint, as a `DecafPoint`. This is called `_POINT` to distinguish it from +/// The Ed25519 basepoint, as a `RistrettoPoint`. This is called `_POINT` to distinguish it from /// `_TABLE`, which provides fast scalar multiplication. -#[cfg(feature = "yolocrypto")] pub const DECAF_ED25519_BASEPOINT_POINT: DecafPoint = -DecafPoint(ED25519_BASEPOINT_POINT); +#[cfg(feature = "yolocrypto")] +pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT); /// `l` is the order of base point, i.e. 2^252 + /// 27742317777372353535851937790883648493, in little-endian form @@ -88,9 +88,9 @@ pub const l_minus_2: Scalar = Scalar([ 0xeb, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 ]); #[cfg(feature = "yolocrypto")] -/// The Ed25519 basepoint -pub const DECAF_ED25519_BASEPOINT_TABLE: DecafBasepointTable - = DecafBasepointTable(ED25519_BASEPOINT_TABLE); +/// The Ed25519 basepoint, as a RistrettoPoint +pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable + = RistrettoBasepointTable(ED25519_BASEPOINT_TABLE); #[cfg(test)] mod test { diff --git a/src/edwards.rs b/src/edwards.rs index 0b8b333..16c7469 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -1269,8 +1269,6 @@ pub mod vartime { #[cfg(test)] mod test { - #[cfg(feature = "yolocrypto")] - use decaf::DecafPoint; use field::FieldElement; use scalar::Scalar; use subtle::ConditionallyAssignable; @@ -1550,18 +1548,6 @@ mod test { assert!(P1.compress().to_bytes() == P2.compress().to_bytes()); } - #[test] - #[cfg(feature = "yolocrypto")] - fn scalarmult_decafpoint_works_both_ways() { - let P: DecafPoint = DecafPoint(constants::ED25519_BASEPOINT_POINT); - let s: Scalar = A_SCALAR; - - let P1 = &P * &s; - let P2 = &s * &P; - - assert!(P1.compress().as_bytes() == P2.compress().as_bytes()); - } - mod vartime { use super::super::*; use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT}; diff --git a/src/lib.rs b/src/lib.rs index 31c18ff..64583db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,7 +76,7 @@ pub mod montgomery; // Feature gate decaf while our implementation is unfinished and probably incorrect. #[cfg(feature = "yolocrypto")] -pub mod decaf; +pub mod ristretto; // Other miscelaneous utilities. diff --git a/src/decaf.rs b/src/ristretto.rs similarity index 67% rename from src/decaf.rs rename to src/ristretto.rs index 9bc2c8a..43584b4 100644 --- a/src/decaf.rs +++ b/src/ristretto.rs @@ -8,7 +8,7 @@ // - Isis Agora Lovecruft // - Henry de Valence -//! An implementation of Mike Hamburg's Decaf cofactor-eliminating +//! An implementation of Mike Hamburg's Ristretto cofactor-eliminating //! point-compression scheme, providing a prime-order group on top of //! a non-prime-order elliptic curve. //! @@ -50,26 +50,21 @@ use subtle::ConditionallyNegatable; // Compressed points // ------------------------------------------------------------------------ -/// A point serialized using Mike Hamburg's Decaf scheme. +/// A point serialized using Mike Hamburg's Ristretto scheme. /// /// XXX think about how this API should work #[derive(Copy, Clone, Eq, PartialEq)] -pub struct CompressedDecaf(pub [u8; 32]); +pub struct CompressedRistretto(pub [u8; 32]); -/// The result of compressing a `DecafPoint`. -impl CompressedDecaf { - /// Convert this `CompressedDecaf` to an array of bytes. - pub fn to_bytes(&self) -> [u8; 32] { - self.0 - } - - /// View this `CompressedDecaf` as an array of bytes. +/// The result of compressing a `RistrettoPoint`. +impl CompressedRistretto { + /// View this `CompressedRistretto` as an array of bytes. pub fn as_bytes<'a>(&'a self) -> &'a [u8; 32] { &self.0 } - /// Attempt to decompress to an `DecafPoint`. - pub fn decompress(&self) -> Option { + /// Attempt to decompress to an `RistrettoPoint`. + pub fn decompress(&self) -> Option { // XXX should decoding be CT ? // XXX need to check that xy is nonnegative and reject otherwise let s = FieldElement::from_bytes(self.as_bytes()); @@ -116,25 +111,25 @@ impl CompressedDecaf { // Use the value of 1/Z previously computed in the batch inversion let xy = &T * &Zinv; if (Y.is_nonzero() & xy.is_nonnegative_decaf()) == 1u8 { - Some(DecafPoint(ExtendedPoint{ X: X, Y: Y, Z: Z, T: T })) + Some(RistrettoPoint(ExtendedPoint{ X: X, Y: Y, Z: Z, T: T })) } else { None } } } -impl Identity for CompressedDecaf { - fn identity() -> CompressedDecaf { - CompressedDecaf([0u8; 32]) +impl Identity for CompressedRistretto { + fn identity() -> CompressedRistretto { + CompressedRistretto([0u8; 32]) } } // ------------------------------------------------------------------------ // Serde support // ------------------------------------------------------------------------ -// Serializes to and from `DecafPoint` directly, doing compression +// Serializes to and from `RistrettoPoint` directly, doing compression // and decompression internally. This means that users can create -// structs containing `DecafPoint`s and use Serde's derived +// structs containing `RistrettoPoint`s and use Serde's derived // serializers to serialize those structures. #[cfg(feature = "serde")] @@ -143,7 +138,7 @@ use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; use serde::de::Visitor; #[cfg(feature = "serde")] -impl Serialize for DecafPoint { +impl Serialize for RistrettoPoint { fn serialize(&self, serializer: S) -> Result where S: Serializer { @@ -152,25 +147,25 @@ impl Serialize for DecafPoint { } #[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for DecafPoint { +impl<'de> Deserialize<'de> for RistrettoPoint { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - struct DecafPointVisitor; + struct RistrettoPointVisitor; - impl<'de> Visitor<'de> for DecafPointVisitor { - type Value = DecafPoint; + impl<'de> Visitor<'de> for RistrettoPointVisitor { + type Value = RistrettoPoint; fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - formatter.write_str("a valid point in Decaf format") + formatter.write_str("a valid point in Ristretto format") } - fn visit_bytes(self, v: &[u8]) -> Result + fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error { if v.len() == 32 { let arr32 = array_ref!(v, 0, 32); // &[u8;32] from &[u8] - CompressedDecaf(*arr32) + CompressedRistretto(*arr32) .decompress() .ok_or(serde::de::Error::custom("decompression failed")) } else { @@ -179,7 +174,7 @@ impl<'de> Deserialize<'de> for DecafPoint { } } - deserializer.deserialize_bytes(DecafPointVisitor) + deserializer.deserialize_bytes(RistrettoPointVisitor) } } @@ -191,11 +186,11 @@ impl<'de> Deserialize<'de> for DecafPoint { /// // XXX think about how this API should work #[derive(Copy, Clone)] -pub struct DecafPoint(pub ExtendedPoint); +pub struct RistrettoPoint(pub ExtendedPoint); -impl DecafPoint { - /// Compress in Decaf format. - pub fn compress(&self) -> CompressedDecaf { +impl RistrettoPoint { + /// Compress in Ristretto format. + pub fn compress(&self) -> CompressedRistretto { // Q: Do we want to encode twisted or untwisted? // // Notes: @@ -205,7 +200,7 @@ impl DecafPoint { // // Internally, we operate on the curve with a = -1, d = // -121665/121666, a.k.a., the twist. But maybe we would like - // to use Decaf on the untwisted curve with a = 1, d = + // to use Ristretto on the untwisted curve with a = 1, d = // 121665/121666. (why? interop?) // // Fix i, a square root of -1 (mod p). @@ -215,7 +210,7 @@ impl DecafPoint { // let untwisted_X = &self.X * &constants::MSQRT_M1; // etc. // - // Step 0: pre-rotation, needed for Decaf with E[8] = Z/8. + // Step 0: pre-rotation, needed for Ristretto with E[8] = Z/8. // // We want to select a point (x,y) in the coset P + E[4] with // y nonzero and xy nonnegative. The naive approach is as @@ -341,7 +336,7 @@ impl DecafPoint { let mut s = &u * &(&(&r * &(&minus_ZX - &dYT)) + &Y); let neg = s.is_negative_decaf(); s.conditional_negate(neg); - CompressedDecaf(s.to_bytes()) + CompressedRistretto(s.to_bytes()) } /// Return the coset self + E[4], for debugging. @@ -359,7 +354,7 @@ impl DecafPoint { /// /// This method is not public because it's just used for hashing /// to a point -- proper elligator support is deferred for now. - pub fn elligator_decaf_flavour(r_0: &FieldElement) -> DecafPoint { + pub fn elligator_decaf_flavour(r_0: &FieldElement) -> RistrettoPoint { // Follows Appendix C of the Decaf paper. // Use n = 2 as the quadratic nonresidue so that n*x = x + x. let minus_one = -&FieldElement::one(); @@ -418,10 +413,10 @@ impl DecafPoint { }; // Convert to extended and return. - DecafPoint(P.to_extended()) + RistrettoPoint(P.to_extended()) } - /// Return a `DecafPoint` chosen uniformly at random using a user-provided RNG. + /// Return a `RistrettoPoint` chosen uniformly at random using a user-provided RNG. /// /// # Inputs /// @@ -429,21 +424,21 @@ impl DecafPoint { /// /// # Returns /// - /// A random element of the Decaf group. + /// A random element of the Ristretto group. /// /// # Implementation /// - /// Uses the Decaf-flavoured Elligator 2 map, so that the discrete log of the + /// Uses the Ristretto-flavoured Elligator 2 map, so that the discrete log of the /// output point with respect to any other point should be unknown. #[cfg(feature = "std")] pub fn random(rng: &mut T) -> Self { let mut field_bytes = [0u8; 32]; rng.fill_bytes(&mut field_bytes); let r_0 = FieldElement::from_bytes(&field_bytes); - DecafPoint::elligator_decaf_flavour(&r_0) + RistrettoPoint::elligator_decaf_flavour(&r_0) } - /// Hash a slice of bytes into a `DecafPoint`. + /// Hash a slice of bytes into a `RistrettoPoint`. /// /// Takes a type parameter `D`, which is any `Digest` producing 32 /// bytes (256 bits) of output. @@ -452,14 +447,14 @@ impl DecafPoint { /// /// # Implementation /// - /// Uses the Decaf-flavoured Elligator 2 map, so that the discrete log of the + /// Uses the Ristretto-flavoured Elligator 2 map, so that the discrete log of the /// output point with respect to any other point should be unknown. /// /// # Example /// /// ``` /// # extern crate curve25519_dalek; - /// # use curve25519_dalek::decaf::DecafPoint; + /// # use curve25519_dalek::ristretto::RistrettoPoint; /// extern crate sha2; /// use sha2::Sha256; /// @@ -467,37 +462,37 @@ impl DecafPoint { /// # // See https://doc.rust-lang.org/book/documentation.html#documentation-as-tests /// # fn main() { /// let msg = "To really appreciate architecture, you may even need to commit a murder"; - /// let P = DecafPoint::hash_from_bytes::(msg.as_bytes()); + /// let P = RistrettoPoint::hash_from_bytes::(msg.as_bytes()); /// # } /// ``` /// - pub fn hash_from_bytes(input: &[u8]) -> DecafPoint + pub fn hash_from_bytes(input: &[u8]) -> RistrettoPoint where D: Digest + Default { let mut hash = D::default(); hash.input(input); - DecafPoint::from_hash(hash) + RistrettoPoint::from_hash(hash) } - /// Construct a `DecafPoint` from an existing `Digest` instance. + /// Construct a `RistrettoPoint` from an existing `Digest` instance. /// /// Use this instead of `hash_from_bytes` if it is more convenient /// to stream data into the `Digest` than to pass a single byte /// slice. - pub fn from_hash(hash: D) -> DecafPoint + pub fn from_hash(hash: D) -> RistrettoPoint where D: Digest + Default { // XXX this seems clumsy let mut output = [0u8; 32]; output.copy_from_slice(hash.result().as_slice()); let r_0 = FieldElement::from_bytes(&output); - DecafPoint::elligator_decaf_flavour(&r_0) + RistrettoPoint::elligator_decaf_flavour(&r_0) } } -impl Identity for DecafPoint { - fn identity() -> DecafPoint { - DecafPoint(ExtendedPoint::identity()) +impl Identity for RistrettoPoint { + fn identity() -> RistrettoPoint { + RistrettoPoint(ExtendedPoint::identity()) } } @@ -507,77 +502,77 @@ impl Identity for DecafPoint { /// XXX check whether there's a simple way to do equality checking /// with cofactor 8, not just cofactor 4, and add a CT equality function? -impl PartialEq for DecafPoint { - fn eq(&self, other: &DecafPoint) -> bool { +impl PartialEq for RistrettoPoint { + fn eq(&self, other: &RistrettoPoint) -> bool { let self_compressed = self.compress(); let other_compressed = other.compress(); self_compressed == other_compressed } } -impl Eq for DecafPoint {} +impl Eq for RistrettoPoint {} // ------------------------------------------------------------------------ // Arithmetic // ------------------------------------------------------------------------ -impl<'a, 'b> Add<&'b DecafPoint> for &'a DecafPoint { - type Output = DecafPoint; +impl<'a, 'b> Add<&'b RistrettoPoint> for &'a RistrettoPoint { + type Output = RistrettoPoint; - fn add(self, other: &'b DecafPoint) -> DecafPoint { - DecafPoint(&self.0 + &other.0) + fn add(self, other: &'b RistrettoPoint) -> RistrettoPoint { + RistrettoPoint(&self.0 + &other.0) } } -impl<'b> AddAssign<&'b DecafPoint> for DecafPoint { - fn add_assign(&mut self, _rhs: &DecafPoint) { - *self = (self as &DecafPoint) + _rhs; +impl<'b> AddAssign<&'b RistrettoPoint> for RistrettoPoint { + fn add_assign(&mut self, _rhs: &RistrettoPoint) { + *self = (self as &RistrettoPoint) + _rhs; } } -impl<'a, 'b> Sub<&'b DecafPoint> for &'a DecafPoint { - type Output = DecafPoint; +impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint { + type Output = RistrettoPoint; - fn sub(self, other: &'b DecafPoint) -> DecafPoint { - DecafPoint(&self.0 - &other.0) + fn sub(self, other: &'b RistrettoPoint) -> RistrettoPoint { + RistrettoPoint(&self.0 - &other.0) } } -impl<'b> SubAssign<&'b DecafPoint> for DecafPoint { - fn sub_assign(&mut self, _rhs: &DecafPoint) { - *self = (self as &DecafPoint) - _rhs; +impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint { + fn sub_assign(&mut self, _rhs: &RistrettoPoint) { + *self = (self as &RistrettoPoint) - _rhs; } } -impl<'a> Neg for &'a DecafPoint { - type Output = DecafPoint; +impl<'a> Neg for &'a RistrettoPoint { + type Output = RistrettoPoint; - fn neg(self) -> DecafPoint { - DecafPoint(-&self.0) + fn neg(self) -> RistrettoPoint { + RistrettoPoint(-&self.0) } } -impl<'b> MulAssign<&'b Scalar> for DecafPoint { +impl<'b> MulAssign<&'b Scalar> for RistrettoPoint { fn mul_assign(&mut self, scalar: &'b Scalar) { - let result = (self as &DecafPoint) * scalar; + let result = (self as &RistrettoPoint) * scalar; *self = result; } } -impl<'a, 'b> Mul<&'b Scalar> for &'a DecafPoint { - type Output = DecafPoint; +impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoPoint { + type Output = RistrettoPoint; /// Scalar multiplication: compute `scalar * self`. - fn mul(self, scalar: &'b Scalar) -> DecafPoint { - DecafPoint(&self.0 * scalar) + fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { + RistrettoPoint(&self.0 * scalar) } } -impl<'a, 'b> Mul<&'b DecafPoint> for &'a Scalar { - type Output = DecafPoint; +impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar { + type Output = RistrettoPoint; /// Scalar multiplication: compute `self * scalar`. - fn mul(self, point: &'b DecafPoint) -> DecafPoint { - DecafPoint(self * &point.0) + fn mul(self, point: &'b RistrettoPoint) -> RistrettoPoint { + RistrettoPoint(self * &point.0) } } @@ -589,46 +584,46 @@ impl<'a, 'b> Mul<&'b DecafPoint> for &'a Scalar { /// /// # Input /// -/// A vector of `Scalar`s and a vector of `DecafPoints`. It is an -/// error to call this function with two vectors of different lengths. +/// An iterable of `Scalar`s and a iterable of `DecafPoints`. It is an +/// error to call this function with two iterators of different lengths. #[cfg(any(feature = "alloc", feature = "std"))] -pub fn multiscalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> DecafPoint +pub fn multiscalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> RistrettoPoint where I: IntoIterator, - J: IntoIterator, + J: IntoIterator, { let extended_points = points.into_iter().map(|P| &P.0); - DecafPoint(edwards::multiscalar_mult(scalars, extended_points)) + RistrettoPoint(edwards::multiscalar_mult(scalars, extended_points)) } /// Precomputation #[derive(Clone)] -pub struct DecafBasepointTable(pub EdwardsBasepointTable); +pub struct RistrettoBasepointTable(pub EdwardsBasepointTable); -impl<'a, 'b> Mul<&'b Scalar> for &'a DecafBasepointTable { - type Output = DecafPoint; +impl<'a, 'b> Mul<&'b Scalar> for &'a RistrettoBasepointTable { + type Output = RistrettoPoint; - fn mul(self, scalar: &'b Scalar) -> DecafPoint { - DecafPoint(&self.0 * scalar) + fn mul(self, scalar: &'b Scalar) -> RistrettoPoint { + RistrettoPoint(&self.0 * scalar) } } -impl<'a, 'b> Mul<&'a DecafBasepointTable> for &'b Scalar { - type Output = DecafPoint; +impl<'a, 'b> Mul<&'a RistrettoBasepointTable> for &'b Scalar { + type Output = RistrettoPoint; - fn mul(self, basepoint_table: &'a DecafBasepointTable) -> DecafPoint { - DecafPoint(self * &basepoint_table.0) + fn mul(self, basepoint_table: &'a RistrettoBasepointTable) -> RistrettoPoint { + RistrettoPoint(self * &basepoint_table.0) } } -impl DecafBasepointTable { +impl RistrettoBasepointTable { /// Create a precomputed table of multiples of the given `basepoint`. - pub fn create(basepoint: &DecafPoint) -> DecafBasepointTable { - DecafBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) + pub fn create(basepoint: &RistrettoPoint) -> RistrettoBasepointTable { + RistrettoBasepointTable(EdwardsBasepointTable::create(&basepoint.0)) } - /// Get the basepoint for this table as a `DecafPoint`. - pub fn basepoint(&self) -> DecafPoint { - DecafPoint(self.0.basepoint()) + /// Get the basepoint for this table as a `RistrettoPoint`. + pub fn basepoint(&self) -> RistrettoPoint { + RistrettoPoint(self.0.basepoint()) } } @@ -636,7 +631,7 @@ impl DecafBasepointTable { // Constant-time conditional assignment // ------------------------------------------------------------------------ -impl ConditionallyAssignable for DecafPoint { +impl ConditionallyAssignable for RistrettoPoint { /// Conditionally assign `other` to `self`, if `choice == 1u8`. /// /// # Example @@ -648,11 +643,11 @@ impl ConditionallyAssignable for DecafPoint { /// # use subtle::ConditionallyAssignable; /// # /// # use curve25519_dalek::edwards::Identity; - /// # use curve25519_dalek::decaf::DecafPoint; + /// # use curve25519_dalek::ristretto::RistrettoPoint; /// # use curve25519_dalek::constants; /// # fn main() { - /// let A = DecafPoint::identity(); - /// let B = constants::DECAF_ED25519_BASEPOINT_POINT; + /// let A = RistrettoPoint::identity(); + /// let B = constants::RISTRETTO_BASEPOINT_POINT; /// /// let mut P = A; /// @@ -662,7 +657,7 @@ impl ConditionallyAssignable for DecafPoint { /// assert!(P == B); /// # } /// ``` - fn conditional_assign(&mut self, other: &DecafPoint, choice: u8) { + fn conditional_assign(&mut self, other: &RistrettoPoint, choice: u8) { self.0.X.conditional_assign(&other.0.X, choice); self.0.Y.conditional_assign(&other.0.Y, choice); self.0.Z.conditional_assign(&other.0.Z, choice); @@ -674,16 +669,16 @@ impl ConditionallyAssignable for DecafPoint { // Debug traits // ------------------------------------------------------------------------ -impl Debug for CompressedDecaf { +impl Debug for CompressedRistretto { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "CompressedDecaf: {:?}", self.as_bytes()) + write!(f, "CompressedRistretto: {:?}", self.as_bytes()) } } -impl Debug for DecafPoint { +impl Debug for RistrettoPoint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let coset = self.coset4(); - write!(f, "DecafPoint: coset \n{:?}\n{:?}\n{:?}\n{:?}", + write!(f, "RistrettoPoint: coset \n{:?}\n{:?}\n{:?}\n{:?}", coset[0], coset[1], coset[2], coset[3]) } } @@ -693,7 +688,7 @@ impl Debug for DecafPoint { // ------------------------------------------------------------------------ pub mod vartime { - //! Variable-time operations on decaf points, useful for non-secret data. + //! Variable-time operations on ristretto points, useful for non-secret data. use super::*; /// Given a vector of public scalars and a vector of (possibly secret) @@ -703,14 +698,14 @@ pub mod vartime { /// /// # Input /// - /// A vector of `Scalar`s and a vector of `ExtendedPoints`. It is an + /// A vector of `Scalar`s and a vector of `RistrettoPoints`. It is an /// error to call this function with two vectors of different lengths. - pub fn multiscalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> DecafPoint + pub fn multiscalar_mult<'a, 'b, I, J>(scalars: I, points: J) -> RistrettoPoint where I: IntoIterator, - J: IntoIterator + J: IntoIterator { let extended_points = points.into_iter().map(|P| &P.0); - DecafPoint(edwards::vartime::multiscalar_mult(scalars, extended_points)) + RistrettoPoint(edwards::vartime::multiscalar_mult(scalars, extended_points)) } } @@ -735,39 +730,49 @@ mod test { #[test] #[cfg(feature = "serde")] fn serde_cbor_basepoint_roundtrip() { - let output = serde_cbor::to_vec(&constants::DECAF_ED25519_BASEPOINT_POINT).unwrap(); - let parsed: DecafPoint = serde_cbor::from_slice(&output).unwrap(); - assert_eq!(parsed, constants::DECAF_ED25519_BASEPOINT_POINT); + let output = serde_cbor::to_vec(&constants::RISTRETTO_BASEPOINT_POINT).unwrap(); + let parsed: RistrettoPoint = serde_cbor::from_slice(&output).unwrap(); + assert_eq!(parsed, constants::RISTRETTO_BASEPOINT_POINT); } + #[test] + fn scalarmult_ristrettopoint_works_both_ways() { + let P = constants::RISTRETTO_BASEPOINT_POINT; + let s = Scalar::from_u64(999); + + let P1 = &P * &s; + let P2 = &s * &P; + + assert!(P1.compress().as_bytes() == P2.compress().as_bytes()); + } #[test] - fn decaf_decompress_negative_s_fails() { + fn decompress_negative_s_fails() { // constants::d is neg, so decompression should fail as |d| != d. - let bad_compressed = CompressedDecaf(constants::d.to_bytes()); + let bad_compressed = CompressedRistretto(constants::d.to_bytes()); assert!(bad_compressed.decompress().is_none()); } #[test] - fn decaf_decompress_id() { - let compressed_id = CompressedDecaf::identity(); + fn decompress_id() { + let compressed_id = CompressedRistretto::identity(); let id = compressed_id.decompress().unwrap(); assert_eq!(id.0.compress(), CompressedEdwardsY::identity()); } #[test] - fn decaf_compress_id() { - let id = DecafPoint::identity(); - assert_eq!(id.compress(), CompressedDecaf::identity()); + fn compress_id() { + let id = RistrettoPoint::identity(); + assert_eq!(id.compress(), CompressedRistretto::identity()); } #[test] - fn decaf_basepoint_roundtrip() { - let bp_compressed_decaf = constants::DECAF_ED25519_BASEPOINT_POINT.compress(); - let bp_recaf = bp_compressed_decaf.decompress().unwrap().0; + fn basepoint_roundtrip() { + let bp_compressed_ristretto = constants::RISTRETTO_BASEPOINT_POINT.compress(); + let bp_recaf = bp_compressed_ristretto.decompress().unwrap().0; // Check that bp_recaf differs from bp by a point of order 4 - let diff = &constants::ED25519_BASEPOINT_POINT - &bp_recaf; - let diff4 = diff.mult_by_pow_2(4); // XXX this is wrong + let diff = &constants::RISTRETTO_BASEPOINT_POINT.0 - &bp_recaf; + let diff4 = diff.mult_by_pow_2(2); assert_eq!(diff4.compress(), CompressedEdwardsY::identity()); } @@ -776,54 +781,54 @@ mod test { // Table of encodings of (1+i)*basepoint // Generated using the previous naive implementation. let compressed = [ - CompressedDecaf([141, 190, 226, 107, 177, 201, 35, 118, 14, 55, 160, 165, 242, 207, 121, 161, 177, 80, 8, 132, 205, 254, 101, 169, 233, 65, 124, 96, 255, 182, 249, 40]), - CompressedDecaf([131, 57, 148, 16, 8, 196, 141, 82, 144, 220, 105, 112, 66, 33, 48, 16, 182, 198, 173, 35, 248, 181, 92, 231, 222, 35, 85, 56, 5, 252, 91, 40]), - CompressedDecaf([199, 132, 32, 144, 156, 143, 81, 170, 240, 56, 232, 6, 178, 37, 118, 190, 110, 201, 26, 173, 156, 97, 59, 162, 240, 247, 226, 107, 197, 111, 107, 26]), - CompressedDecaf([210, 120, 34, 214, 175, 27, 61, 6, 229, 181, 216, 36, 11, 245, 146, 232, 130, 215, 77, 29, 210, 30, 54, 155, 191, 81, 59, 124, 174, 3, 135, 36]), - CompressedDecaf([155, 52, 159, 52, 189, 27, 181, 0, 245, 131, 0, 197, 79, 208, 252, 122, 104, 161, 245, 143, 67, 94, 13, 129, 153, 173, 129, 179, 118, 231, 90, 52]), - CompressedDecaf([42, 117, 252, 118, 8, 1, 72, 25, 111, 246, 247, 103, 236, 86, 235, 29, 100, 156, 186, 209, 159, 21, 61, 26, 249, 25, 137, 228, 84, 23, 10, 27]), - CompressedDecaf([21, 126, 181, 117, 58, 90, 216, 28, 184, 57, 9, 23, 158, 68, 159, 171, 109, 150, 232, 140, 144, 73, 139, 122, 124, 105, 125, 160, 94, 185, 150, 52]), - CompressedDecaf([232, 167, 112, 233, 126, 33, 105, 63, 151, 6, 88, 225, 181, 17, 223, 12, 116, 138, 203, 47, 243, 225, 50, 171, 21, 220, 186, 179, 132, 20, 48, 6]), - CompressedDecaf([99, 44, 97, 48, 242, 174, 78, 198, 112, 154, 146, 36, 239, 34, 94, 4, 0, 244, 175, 34, 46, 0, 83, 187, 5, 163, 225, 63, 51, 237, 234, 22]), - CompressedDecaf([2, 33, 89, 176, 178, 123, 159, 75, 235, 172, 251, 11, 137, 177, 90, 122, 149, 186, 52, 243, 153, 190, 185, 202, 59, 137, 204, 160, 150, 152, 148, 55]), - CompressedDecaf([245, 79, 78, 226, 114, 69, 247, 112, 18, 54, 90, 225, 176, 77, 231, 235, 196, 123, 49, 221, 34, 205, 151, 228, 244, 112, 82, 58, 30, 31, 58, 12]), - CompressedDecaf([135, 53, 175, 167, 13, 94, 62, 31, 29, 248, 13, 132, 29, 69, 7, 188, 145, 49, 62, 55, 181, 109, 214, 11, 248, 162, 70, 15, 236, 126, 100, 60]), - CompressedDecaf([98, 150, 69, 229, 144, 122, 237, 107, 127, 177, 33, 64, 59, 173, 210, 102, 74, 34, 23, 16, 252, 117, 14, 97, 231, 178, 63, 193, 157, 28, 178, 17]), - CompressedDecaf([222, 104, 6, 1, 72, 12, 72, 178, 204, 238, 128, 70, 41, 150, 235, 96, 153, 150, 18, 4, 141, 206, 0, 38, 122, 112, 249, 51, 94, 251, 20, 57]), - CompressedDecaf([7, 221, 140, 57, 13, 146, 248, 27, 56, 4, 128, 23, 145, 120, 126, 4, 158, 173, 52, 213, 164, 250, 26, 55, 89, 96, 187, 111, 211, 18, 63, 19]), - CompressedDecaf([91, 213, 193, 10, 102, 92, 199, 124, 61, 176, 1, 47, 111, 59, 183, 91, 79, 56, 208, 109, 172, 209, 17, 167, 229, 216, 3, 236, 200, 208, 15, 20]), + CompressedRistretto([141, 190, 226, 107, 177, 201, 35, 118, 14, 55, 160, 165, 242, 207, 121, 161, 177, 80, 8, 132, 205, 254, 101, 169, 233, 65, 124, 96, 255, 182, 249, 40]), + CompressedRistretto([131, 57, 148, 16, 8, 196, 141, 82, 144, 220, 105, 112, 66, 33, 48, 16, 182, 198, 173, 35, 248, 181, 92, 231, 222, 35, 85, 56, 5, 252, 91, 40]), + CompressedRistretto([199, 132, 32, 144, 156, 143, 81, 170, 240, 56, 232, 6, 178, 37, 118, 190, 110, 201, 26, 173, 156, 97, 59, 162, 240, 247, 226, 107, 197, 111, 107, 26]), + CompressedRistretto([210, 120, 34, 214, 175, 27, 61, 6, 229, 181, 216, 36, 11, 245, 146, 232, 130, 215, 77, 29, 210, 30, 54, 155, 191, 81, 59, 124, 174, 3, 135, 36]), + CompressedRistretto([155, 52, 159, 52, 189, 27, 181, 0, 245, 131, 0, 197, 79, 208, 252, 122, 104, 161, 245, 143, 67, 94, 13, 129, 153, 173, 129, 179, 118, 231, 90, 52]), + CompressedRistretto([42, 117, 252, 118, 8, 1, 72, 25, 111, 246, 247, 103, 236, 86, 235, 29, 100, 156, 186, 209, 159, 21, 61, 26, 249, 25, 137, 228, 84, 23, 10, 27]), + CompressedRistretto([21, 126, 181, 117, 58, 90, 216, 28, 184, 57, 9, 23, 158, 68, 159, 171, 109, 150, 232, 140, 144, 73, 139, 122, 124, 105, 125, 160, 94, 185, 150, 52]), + CompressedRistretto([232, 167, 112, 233, 126, 33, 105, 63, 151, 6, 88, 225, 181, 17, 223, 12, 116, 138, 203, 47, 243, 225, 50, 171, 21, 220, 186, 179, 132, 20, 48, 6]), + CompressedRistretto([99, 44, 97, 48, 242, 174, 78, 198, 112, 154, 146, 36, 239, 34, 94, 4, 0, 244, 175, 34, 46, 0, 83, 187, 5, 163, 225, 63, 51, 237, 234, 22]), + CompressedRistretto([2, 33, 89, 176, 178, 123, 159, 75, 235, 172, 251, 11, 137, 177, 90, 122, 149, 186, 52, 243, 153, 190, 185, 202, 59, 137, 204, 160, 150, 152, 148, 55]), + CompressedRistretto([245, 79, 78, 226, 114, 69, 247, 112, 18, 54, 90, 225, 176, 77, 231, 235, 196, 123, 49, 221, 34, 205, 151, 228, 244, 112, 82, 58, 30, 31, 58, 12]), + CompressedRistretto([135, 53, 175, 167, 13, 94, 62, 31, 29, 248, 13, 132, 29, 69, 7, 188, 145, 49, 62, 55, 181, 109, 214, 11, 248, 162, 70, 15, 236, 126, 100, 60]), + CompressedRistretto([98, 150, 69, 229, 144, 122, 237, 107, 127, 177, 33, 64, 59, 173, 210, 102, 74, 34, 23, 16, 252, 117, 14, 97, 231, 178, 63, 193, 157, 28, 178, 17]), + CompressedRistretto([222, 104, 6, 1, 72, 12, 72, 178, 204, 238, 128, 70, 41, 150, 235, 96, 153, 150, 18, 4, 141, 206, 0, 38, 122, 112, 249, 51, 94, 251, 20, 57]), + CompressedRistretto([7, 221, 140, 57, 13, 146, 248, 27, 56, 4, 128, 23, 145, 120, 126, 4, 158, 173, 52, 213, 164, 250, 26, 55, 89, 96, 187, 111, 211, 18, 63, 19]), + CompressedRistretto([91, 213, 193, 10, 102, 92, 199, 124, 61, 176, 1, 47, 111, 59, 183, 91, 79, 56, 208, 109, 172, 209, 17, 167, 229, 216, 3, 236, 200, 208, 15, 20]), ]; - let mut bp = constants::DECAF_ED25519_BASEPOINT_POINT; + let mut bp = RistrettoPoint::identity(); for i in 0..16 { assert_eq!(bp.compress(), compressed[i]); - bp = &bp + &constants::DECAF_ED25519_BASEPOINT_POINT; + bp = &bp + &constants::RISTRETTO_BASEPOINT_POINT; } } #[test] - fn decaf_four_torsion_basepoint() { - let bp = constants::DECAF_ED25519_BASEPOINT_POINT; + fn four_torsion_basepoint() { + let bp = constants::RISTRETTO_BASEPOINT_POINT; let bp_coset = bp.coset4(); for i in 0..4 { - assert_eq!(bp, DecafPoint(bp_coset[i])); + assert_eq!(bp, RistrettoPoint(bp_coset[i])); } } #[test] - fn decaf_four_torsion_random() { + fn four_torsion_random() { let mut rng = OsRng::new().unwrap(); - let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let B = &constants::RISTRETTO_BASEPOINT_TABLE; let P = B * &Scalar::random(&mut rng); let P_coset = P.coset4(); for i in 0..4 { - assert_eq!(P, DecafPoint(P_coset[i])); + assert_eq!(P, RistrettoPoint(P_coset[i])); } } #[test] - fn decaf_random_roundtrip() { + fn random_roundtrip() { let mut rng = OsRng::new().unwrap(); - let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let B = &constants::RISTRETTO_BASEPOINT_TABLE; for _ in 0..100 { let P = B * &Scalar::random(&mut rng); let compressed_P = P.compress(); @@ -833,13 +838,13 @@ mod test { } #[test] - fn decaf_random_is_valid() { + fn random_is_valid() { let mut rng = OsRng::new().unwrap(); for _ in 0..100 { - let P = DecafPoint::random(&mut rng); + let P = RistrettoPoint::random(&mut rng); // Check that P is on the curve assert!(P.0.is_valid()); - // Check that P is in the image of the decaf map + // Check that P is in the image of the ristretto map P.compress(); } } @@ -855,7 +860,7 @@ mod bench { #[bench] fn decompression(b: &mut Bencher) { let mut rng = OsRng::new().unwrap(); - let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let B = &constants::RISTRETTO_BASEPOINT_TABLE; let P = B * &Scalar::random(&mut rng); let P_compressed = P.compress(); b.iter(|| P_compressed.decompress().unwrap()); @@ -864,7 +869,7 @@ mod bench { #[bench] fn compression(b: &mut Bencher) { let mut rng = OsRng::new().unwrap(); - let B = &constants::DECAF_ED25519_BASEPOINT_TABLE; + let B = &constants::RISTRETTO_BASEPOINT_TABLE; let P = B * &Scalar::random(&mut rng); b.iter(|| P.compress()); }