1 // -*- mode: rust; -*- 2 // 3 // This file is part of curve25519-dalek. 4 // Copyright (c) 2016-2021 isis lovecruft 5 // Copyright (c) 2016-2020 Henry de Valence 6 // See LICENSE for licensing information. 7 // 8 // Authors: 9 // - isis agora lovecruft <isis@patternsinthevoid.net> 10 // - Henry de Valence <hdevalence@hdevalence.ca> 11 12 //! Group operations for Curve25519, in Edwards form. 13 //! 14 //! ## Encoding and Decoding 15 //! 16 //! Encoding is done by converting to and from a `CompressedEdwardsY` 17 //! struct, which is a typed wrapper around `[u8; 32]`. 18 //! 19 //! ## Equality Testing 20 //! 21 //! The `EdwardsPoint` struct implements the `subtle::ConstantTimeEq` 22 //! trait for constant-time equality checking, and the Rust `Eq` trait 23 //! for variable-time equality checking. 24 //! 25 //! ## Cofactor-related functions 26 //! 27 //! The order of the group of points on the curve \\(\mathcal E\\) 28 //! is \\(|\mathcal E| = 8\ell \\), so its structure is \\( \mathcal 29 //! E = \mathcal E[8] \times \mathcal E[\ell]\\). The torsion 30 //! subgroup \\( \mathcal E[8] \\) consists of eight points of small 31 //! order. Technically, all of \\(\mathcal E\\) is torsion, but we 32 //! use the word only to refer to the small \\(\mathcal E[8]\\) part, not 33 //! the large prime-order \\(\mathcal E[\ell]\\) part. 34 //! 35 //! To test if a point is in \\( \mathcal E[8] \\), use 36 //! `EdwardsPoint::is_small_order()`. 37 //! 38 //! To test if a point is in \\( \mathcal E[\ell] \\), use 39 //! `EdwardsPoint::is_torsion_free()`. 40 //! 41 //! To multiply by the cofactor, use `EdwardsPoint::mul_by_cofactor()`. 42 //! 43 //! To avoid dealing with cofactors entirely, consider using Ristretto. 44 //! 45 //! ## Scalars 46 //! 47 //! Scalars are represented by the `Scalar` struct. To construct a scalar with a specific bit 48 //! pattern, see `Scalar::from_bits()`. 49 //! 50 //! ## Scalar Multiplication 51 //! 52 //! Scalar multiplication on Edwards points is provided by: 53 //! 54 //! * the `*` operator between a `Scalar` and a `EdwardsPoint`, which 55 //! performs constant-time variable-base scalar multiplication; 56 //! 57 //! * the `*` operator between a `Scalar` and a 58 //! `EdwardsBasepointTable`, which performs constant-time fixed-base 59 //! scalar multiplication; 60 //! 61 //! * an implementation of the 62 //! [`MultiscalarMul`](../traits/trait.MultiscalarMul.html) trait for 63 //! constant-time variable-base multiscalar multiplication; 64 //! 65 //! * an implementation of the 66 //! [`VartimeMultiscalarMul`](../traits/trait.VartimeMultiscalarMul.html) 67 //! trait for variable-time variable-base multiscalar multiplication; 68 //! 69 //! ## Implementation 70 //! 71 //! The Edwards arithmetic is implemented using the “extended twisted 72 //! coordinates” of Hisil, Wong, Carter, and Dawson, and the 73 //! corresponding complete formulas. For more details, 74 //! see the [`curve_models` submodule][curve_models] 75 //! of the internal documentation. 76 //! 77 //! ## Validity Checking 78 //! 79 //! There is no function for checking whether a point is valid. 80 //! Instead, the `EdwardsPoint` struct is guaranteed to hold a valid 81 //! point on the curve. 82 //! 83 //! We use the Rust type system to make invalid points 84 //! unrepresentable: `EdwardsPoint` objects can only be created via 85 //! successful decompression of a compressed point, or else by 86 //! operations on other (valid) `EdwardsPoint`s. 87 //! 88 //! [curve_models]: https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html 89 90 // We allow non snake_case names because coordinates in projective space are 91 // traditionally denoted by the capitalisation of their respective 92 // counterparts in affine space. Yeah, you heard me, rustc, I'm gonna have my 93 // affine and projective cakes and eat both of them too. 94 #![allow(non_snake_case)] 95 96 use core::borrow::Borrow; 97 use core::fmt::Debug; 98 use core::iter::Iterator; 99 use core::iter::Sum; 100 use core::ops::{Add, Neg, Sub}; 101 use core::ops::{AddAssign, SubAssign}; 102 use core::ops::{Mul, MulAssign}; 103 104 use digest::{generic_array::typenum::U64, Digest}; 105 use subtle::Choice; 106 use subtle::ConditionallyNegatable; 107 use subtle::ConditionallySelectable; 108 use subtle::ConstantTimeEq; 109 110 use zeroize::Zeroize; 111 112 use constants; 113 114 use field::FieldElement; 115 use scalar::Scalar; 116 117 use montgomery::MontgomeryPoint; 118 119 use backend::serial::curve_models::AffineNielsPoint; 120 use backend::serial::curve_models::CompletedPoint; 121 use backend::serial::curve_models::ProjectiveNielsPoint; 122 use backend::serial::curve_models::ProjectivePoint; 123 124 use window::LookupTable; 125 use window::LookupTableRadix16; 126 use window::LookupTableRadix32; 127 use window::LookupTableRadix64; 128 use window::LookupTableRadix128; 129 use window::LookupTableRadix256; 130 131 #[allow(unused_imports)] 132 use prelude::*; 133 134 use traits::BasepointTable; 135 use traits::ValidityCheck; 136 use traits::{Identity, IsIdentity}; 137 138 #[cfg(any(feature = "alloc", feature = "std"))] 139 use traits::MultiscalarMul; 140 #[cfg(any(feature = "alloc", feature = "std"))] 141 use traits::{VartimeMultiscalarMul, VartimePrecomputedMultiscalarMul}; 142 143 #[cfg(not(all( 144 feature = "simd_backend", 145 any(target_feature = "avx2", target_feature = "avx512ifma") 146 )))] 147 use backend::serial::scalar_mul; 148 #[cfg(all( 149 feature = "simd_backend", 150 any(target_feature = "avx2", target_feature = "avx512ifma") 151 ))] 152 use backend::vector::scalar_mul; 153 154 // ------------------------------------------------------------------------ 155 // Compressed points 156 // ------------------------------------------------------------------------ 157 158 /// In "Edwards y" / "Ed25519" format, the curve point \\((x,y)\\) is 159 /// determined by the \\(y\\)-coordinate and the sign of \\(x\\). 160 /// 161 /// The first 255 bits of a `CompressedEdwardsY` represent the 162 /// \\(y\\)-coordinate. The high bit of the 32nd byte gives the sign of \\(x\\). 163 #[derive(Copy, Clone, Eq, PartialEq, Hash)] 164 pub struct CompressedEdwardsY(pub [u8; 32]); 165 166 impl ConstantTimeEq for CompressedEdwardsY { ct_eq(&self, other: &CompressedEdwardsY) -> Choice167 fn ct_eq(&self, other: &CompressedEdwardsY) -> Choice { 168 self.as_bytes().ct_eq(other.as_bytes()) 169 } 170 } 171 172 impl Debug for CompressedEdwardsY { fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result173 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 174 write!(f, "CompressedEdwardsY: {:?}", self.as_bytes()) 175 } 176 } 177 178 impl CompressedEdwardsY { 179 /// View this `CompressedEdwardsY` as an array of bytes. as_bytes(&self) -> &[u8; 32]180 pub fn as_bytes(&self) -> &[u8; 32] { 181 &self.0 182 } 183 184 /// Copy this `CompressedEdwardsY` to an array of bytes. to_bytes(&self) -> [u8; 32]185 pub fn to_bytes(&self) -> [u8; 32] { 186 self.0 187 } 188 189 /// Attempt to decompress to an `EdwardsPoint`. 190 /// 191 /// Returns `None` if the input is not the \\(y\\)-coordinate of a 192 /// curve point. decompress(&self) -> Option<EdwardsPoint>193 pub fn decompress(&self) -> Option<EdwardsPoint> { 194 let Y = FieldElement::from_bytes(self.as_bytes()); 195 let Z = FieldElement::one(); 196 let YY = Y.square(); 197 let u = &YY - &Z; // u = y²-1 198 let v = &(&YY * &constants::EDWARDS_D) + &Z; // v = dy²+1 199 let (is_valid_y_coord, mut X) = FieldElement::sqrt_ratio_i(&u, &v); 200 201 if is_valid_y_coord.unwrap_u8() != 1u8 { return None; } 202 203 // FieldElement::sqrt_ratio_i always returns the nonnegative square root, 204 // so we negate according to the supplied sign bit. 205 let compressed_sign_bit = Choice::from(self.as_bytes()[31] >> 7); 206 X.conditional_negate(compressed_sign_bit); 207 208 Some(EdwardsPoint{ X, Y, Z, T: &X * &Y }) 209 } 210 } 211 212 // ------------------------------------------------------------------------ 213 // Serde support 214 // ------------------------------------------------------------------------ 215 // Serializes to and from `EdwardsPoint` directly, doing compression 216 // and decompression internally. This means that users can create 217 // structs containing `EdwardsPoint`s and use Serde's derived 218 // serializers to serialize those structures. 219 220 #[cfg(feature = "serde")] 221 use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; 222 #[cfg(feature = "serde")] 223 use serde::de::Visitor; 224 225 #[cfg(feature = "serde")] 226 impl Serialize for EdwardsPoint { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer227 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 228 where S: Serializer 229 { 230 use serde::ser::SerializeTuple; 231 let mut tup = serializer.serialize_tuple(32)?; 232 for byte in self.compress().as_bytes().iter() { 233 tup.serialize_element(byte)?; 234 } 235 tup.end() 236 } 237 } 238 239 #[cfg(feature = "serde")] 240 impl Serialize for CompressedEdwardsY { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer241 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 242 where S: Serializer 243 { 244 use serde::ser::SerializeTuple; 245 let mut tup = serializer.serialize_tuple(32)?; 246 for byte in self.as_bytes().iter() { 247 tup.serialize_element(byte)?; 248 } 249 tup.end() 250 } 251 } 252 253 #[cfg(feature = "serde")] 254 impl<'de> Deserialize<'de> for EdwardsPoint { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>255 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 256 where D: Deserializer<'de> 257 { 258 struct EdwardsPointVisitor; 259 260 impl<'de> Visitor<'de> for EdwardsPointVisitor { 261 type Value = EdwardsPoint; 262 263 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 264 formatter.write_str("a valid point in Edwards y + sign format") 265 } 266 267 fn visit_seq<A>(self, mut seq: A) -> Result<EdwardsPoint, A::Error> 268 where A: serde::de::SeqAccess<'de> 269 { 270 let mut bytes = [0u8; 32]; 271 for i in 0..32 { 272 bytes[i] = seq.next_element()? 273 .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; 274 } 275 CompressedEdwardsY(bytes) 276 .decompress() 277 .ok_or(serde::de::Error::custom("decompression failed")) 278 } 279 } 280 281 deserializer.deserialize_tuple(32, EdwardsPointVisitor) 282 } 283 } 284 285 #[cfg(feature = "serde")] 286 impl<'de> Deserialize<'de> for CompressedEdwardsY { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>287 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 288 where D: Deserializer<'de> 289 { 290 struct CompressedEdwardsYVisitor; 291 292 impl<'de> Visitor<'de> for CompressedEdwardsYVisitor { 293 type Value = CompressedEdwardsY; 294 295 fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 296 formatter.write_str("32 bytes of data") 297 } 298 299 fn visit_seq<A>(self, mut seq: A) -> Result<CompressedEdwardsY, A::Error> 300 where A: serde::de::SeqAccess<'de> 301 { 302 let mut bytes = [0u8; 32]; 303 for i in 0..32 { 304 bytes[i] = seq.next_element()? 305 .ok_or(serde::de::Error::invalid_length(i, &"expected 32 bytes"))?; 306 } 307 Ok(CompressedEdwardsY(bytes)) 308 } 309 } 310 311 deserializer.deserialize_tuple(32, CompressedEdwardsYVisitor) 312 } 313 } 314 315 // ------------------------------------------------------------------------ 316 // Internal point representations 317 // ------------------------------------------------------------------------ 318 319 /// An `EdwardsPoint` represents a point on the Edwards form of Curve25519. 320 #[derive(Copy, Clone)] 321 #[allow(missing_docs)] 322 pub struct EdwardsPoint { 323 pub(crate) X: FieldElement, 324 pub(crate) Y: FieldElement, 325 pub(crate) Z: FieldElement, 326 pub(crate) T: FieldElement, 327 } 328 329 // ------------------------------------------------------------------------ 330 // Constructors 331 // ------------------------------------------------------------------------ 332 333 impl Identity for CompressedEdwardsY { identity() -> CompressedEdwardsY334 fn identity() -> CompressedEdwardsY { 335 CompressedEdwardsY([1, 0, 0, 0, 0, 0, 0, 0, 336 0, 0, 0, 0, 0, 0, 0, 0, 337 0, 0, 0, 0, 0, 0, 0, 0, 338 0, 0, 0, 0, 0, 0, 0, 0]) 339 } 340 } 341 342 impl Default for CompressedEdwardsY { default() -> CompressedEdwardsY343 fn default() -> CompressedEdwardsY { 344 CompressedEdwardsY::identity() 345 } 346 } 347 348 impl CompressedEdwardsY { 349 /// Construct a `CompressedEdwardsY` from a slice of bytes. 350 /// 351 /// # Panics 352 /// 353 /// If the input `bytes` slice does not have a length of 32. from_slice(bytes: &[u8]) -> CompressedEdwardsY354 pub fn from_slice(bytes: &[u8]) -> CompressedEdwardsY { 355 let mut tmp = [0u8; 32]; 356 357 tmp.copy_from_slice(bytes); 358 359 CompressedEdwardsY(tmp) 360 } 361 } 362 363 impl Identity for EdwardsPoint { identity() -> EdwardsPoint364 fn identity() -> EdwardsPoint { 365 EdwardsPoint { 366 X: FieldElement::zero(), 367 Y: FieldElement::one(), 368 Z: FieldElement::one(), 369 T: FieldElement::zero(), 370 } 371 } 372 } 373 374 impl Default for EdwardsPoint { default() -> EdwardsPoint375 fn default() -> EdwardsPoint { 376 EdwardsPoint::identity() 377 } 378 } 379 380 // ------------------------------------------------------------------------ 381 // Zeroize implementations for wiping points from memory 382 // ------------------------------------------------------------------------ 383 384 impl Zeroize for CompressedEdwardsY { 385 /// Reset this `CompressedEdwardsY` to the compressed form of the identity element. zeroize(&mut self)386 fn zeroize(&mut self) { 387 self.0.zeroize(); 388 self.0[0] = 1; 389 } 390 } 391 392 impl Zeroize for EdwardsPoint { 393 /// Reset this `CompressedEdwardsPoint` to the identity element. zeroize(&mut self)394 fn zeroize(&mut self) { 395 self.X.zeroize(); 396 self.Y = FieldElement::one(); 397 self.Z = FieldElement::one(); 398 self.T.zeroize(); 399 } 400 } 401 402 // ------------------------------------------------------------------------ 403 // Validity checks (for debugging, not CT) 404 // ------------------------------------------------------------------------ 405 406 impl ValidityCheck for EdwardsPoint { is_valid(&self) -> bool407 fn is_valid(&self) -> bool { 408 let point_on_curve = self.to_projective().is_valid(); 409 let on_segre_image = (&self.X * &self.Y) == (&self.Z * &self.T); 410 411 point_on_curve && on_segre_image 412 } 413 } 414 415 // ------------------------------------------------------------------------ 416 // Constant-time assignment 417 // ------------------------------------------------------------------------ 418 419 impl ConditionallySelectable for EdwardsPoint { conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint420 fn conditional_select(a: &EdwardsPoint, b: &EdwardsPoint, choice: Choice) -> EdwardsPoint { 421 EdwardsPoint { 422 X: FieldElement::conditional_select(&a.X, &b.X, choice), 423 Y: FieldElement::conditional_select(&a.Y, &b.Y, choice), 424 Z: FieldElement::conditional_select(&a.Z, &b.Z, choice), 425 T: FieldElement::conditional_select(&a.T, &b.T, choice), 426 } 427 } 428 } 429 430 // ------------------------------------------------------------------------ 431 // Equality 432 // ------------------------------------------------------------------------ 433 434 impl ConstantTimeEq for EdwardsPoint { ct_eq(&self, other: &EdwardsPoint) -> Choice435 fn ct_eq(&self, other: &EdwardsPoint) -> Choice { 436 // We would like to check that the point (X/Z, Y/Z) is equal to 437 // the point (X'/Z', Y'/Z') without converting into affine 438 // coordinates (x, y) and (x', y'), which requires two inversions. 439 // We have that X = xZ and X' = x'Z'. Thus, x = x' is equivalent to 440 // (xZ)Z' = (x'Z')Z, and similarly for the y-coordinate. 441 442 (&self.X * &other.Z).ct_eq(&(&other.X * &self.Z)) 443 & (&self.Y * &other.Z).ct_eq(&(&other.Y * &self.Z)) 444 } 445 } 446 447 impl PartialEq for EdwardsPoint { eq(&self, other: &EdwardsPoint) -> bool448 fn eq(&self, other: &EdwardsPoint) -> bool { 449 self.ct_eq(other).unwrap_u8() == 1u8 450 } 451 } 452 453 impl Eq for EdwardsPoint {} 454 455 // ------------------------------------------------------------------------ 456 // Point conversions 457 // ------------------------------------------------------------------------ 458 459 impl EdwardsPoint { 460 /// Convert to a ProjectiveNielsPoint to_projective_niels(&self) -> ProjectiveNielsPoint461 pub(crate) fn to_projective_niels(&self) -> ProjectiveNielsPoint { 462 ProjectiveNielsPoint{ 463 Y_plus_X: &self.Y + &self.X, 464 Y_minus_X: &self.Y - &self.X, 465 Z: self.Z, 466 T2d: &self.T * &constants::EDWARDS_D2, 467 } 468 } 469 470 /// Convert the representation of this point from extended 471 /// coordinates to projective coordinates. 472 /// 473 /// Free. to_projective(&self) -> ProjectivePoint474 pub(crate) fn to_projective(&self) -> ProjectivePoint { 475 ProjectivePoint{ 476 X: self.X, 477 Y: self.Y, 478 Z: self.Z, 479 } 480 } 481 482 /// Dehomogenize to a AffineNielsPoint. 483 /// Mainly for testing. to_affine_niels(&self) -> AffineNielsPoint484 pub(crate) fn to_affine_niels(&self) -> AffineNielsPoint { 485 let recip = self.Z.invert(); 486 let x = &self.X * &recip; 487 let y = &self.Y * &recip; 488 let xy2d = &(&x * &y) * &constants::EDWARDS_D2; 489 AffineNielsPoint{ 490 y_plus_x: &y + &x, 491 y_minus_x: &y - &x, 492 xy2d 493 } 494 } 495 496 /// Convert this `EdwardsPoint` on the Edwards model to the 497 /// corresponding `MontgomeryPoint` on the Montgomery model. 498 /// 499 /// This function has one exceptional case; the identity point of 500 /// the Edwards curve is sent to the 2-torsion point \\((0,0)\\) 501 /// on the Montgomery curve. 502 /// 503 /// Note that this is a one-way conversion, since the Montgomery 504 /// model does not retain sign information. to_montgomery(&self) -> MontgomeryPoint505 pub fn to_montgomery(&self) -> MontgomeryPoint { 506 // We have u = (1+y)/(1-y) = (Z+Y)/(Z-Y). 507 // 508 // The denominator is zero only when y=1, the identity point of 509 // the Edwards curve. Since 0.invert() = 0, in this case we 510 // compute the 2-torsion point (0,0). 511 let U = &self.Z + &self.Y; 512 let W = &self.Z - &self.Y; 513 let u = &U * &W.invert(); 514 MontgomeryPoint(u.to_bytes()) 515 } 516 517 /// Compress this point to `CompressedEdwardsY` format. compress(&self) -> CompressedEdwardsY518 pub fn compress(&self) -> CompressedEdwardsY { 519 let recip = self.Z.invert(); 520 let x = &self.X * &recip; 521 let y = &self.Y * &recip; 522 let mut s: [u8; 32]; 523 524 s = y.to_bytes(); 525 s[31] ^= x.is_negative().unwrap_u8() << 7; 526 CompressedEdwardsY(s) 527 } 528 529 /// Perform hashing to the group using the Elligator2 map 530 /// 531 /// See https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-10#section-6.7.1 hash_from_bytes<D>(bytes: &[u8]) -> EdwardsPoint where D: Digest<OutputSize = U64> + Default,532 pub fn hash_from_bytes<D>(bytes: &[u8]) -> EdwardsPoint 533 where 534 D: Digest<OutputSize = U64> + Default, 535 { 536 let mut hash = D::new(); 537 hash.update(bytes); 538 let h = hash.finalize(); 539 let mut res = [0u8; 32]; 540 res.copy_from_slice(&h[..32]); 541 542 let sign_bit = (res[31] & 0x80) >> 7; 543 544 let fe = FieldElement::from_bytes(&res); 545 546 let M1 = crate::montgomery::elligator_encode(&fe); 547 let E1_opt = M1.to_edwards(sign_bit); 548 549 E1_opt 550 .expect("Montgomery conversion to Edwards point in Elligator failed") 551 .mul_by_cofactor() 552 } 553 } 554 555 // ------------------------------------------------------------------------ 556 // Doubling 557 // ------------------------------------------------------------------------ 558 559 impl EdwardsPoint { 560 /// Add this point to itself. double(&self) -> EdwardsPoint561 pub(crate) fn double(&self) -> EdwardsPoint { 562 self.to_projective().double().to_extended() 563 } 564 } 565 566 // ------------------------------------------------------------------------ 567 // Addition and Subtraction 568 // ------------------------------------------------------------------------ 569 570 impl<'a, 'b> Add<&'b EdwardsPoint> for &'a EdwardsPoint { 571 type Output = EdwardsPoint; add(self, other: &'b EdwardsPoint) -> EdwardsPoint572 fn add(self, other: &'b EdwardsPoint) -> EdwardsPoint { 573 (self + &other.to_projective_niels()).to_extended() 574 } 575 } 576 577 define_add_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); 578 579 impl<'b> AddAssign<&'b EdwardsPoint> for EdwardsPoint { add_assign(&mut self, _rhs: &'b EdwardsPoint)580 fn add_assign(&mut self, _rhs: &'b EdwardsPoint) { 581 *self = (self as &EdwardsPoint) + _rhs; 582 } 583 } 584 585 define_add_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); 586 587 impl<'a, 'b> Sub<&'b EdwardsPoint> for &'a EdwardsPoint { 588 type Output = EdwardsPoint; sub(self, other: &'b EdwardsPoint) -> EdwardsPoint589 fn sub(self, other: &'b EdwardsPoint) -> EdwardsPoint { 590 (self - &other.to_projective_niels()).to_extended() 591 } 592 } 593 594 define_sub_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint, Output = EdwardsPoint); 595 596 impl<'b> SubAssign<&'b EdwardsPoint> for EdwardsPoint { sub_assign(&mut self, _rhs: &'b EdwardsPoint)597 fn sub_assign(&mut self, _rhs: &'b EdwardsPoint) { 598 *self = (self as &EdwardsPoint) - _rhs; 599 } 600 } 601 602 define_sub_assign_variants!(LHS = EdwardsPoint, RHS = EdwardsPoint); 603 604 impl<T> Sum<T> for EdwardsPoint 605 where 606 T: Borrow<EdwardsPoint> 607 { sum<I>(iter: I) -> Self where I: Iterator<Item = T>608 fn sum<I>(iter: I) -> Self 609 where 610 I: Iterator<Item = T> 611 { 612 iter.fold(EdwardsPoint::identity(), |acc, item| acc + item.borrow()) 613 } 614 } 615 616 617 // ------------------------------------------------------------------------ 618 // Negation 619 // ------------------------------------------------------------------------ 620 621 impl<'a> Neg for &'a EdwardsPoint { 622 type Output = EdwardsPoint; 623 neg(self) -> EdwardsPoint624 fn neg(self) -> EdwardsPoint { 625 EdwardsPoint{ 626 X: -(&self.X), 627 Y: self.Y, 628 Z: self.Z, 629 T: -(&self.T), 630 } 631 } 632 } 633 634 impl Neg for EdwardsPoint { 635 type Output = EdwardsPoint; 636 neg(self) -> EdwardsPoint637 fn neg(self) -> EdwardsPoint { 638 -&self 639 } 640 } 641 642 // ------------------------------------------------------------------------ 643 // Scalar multiplication 644 // ------------------------------------------------------------------------ 645 646 impl<'b> MulAssign<&'b Scalar> for EdwardsPoint { mul_assign(&mut self, scalar: &'b Scalar)647 fn mul_assign(&mut self, scalar: &'b Scalar) { 648 let result = (self as &EdwardsPoint) * scalar; 649 *self = result; 650 } 651 } 652 653 define_mul_assign_variants!(LHS = EdwardsPoint, RHS = Scalar); 654 655 define_mul_variants!(LHS = EdwardsPoint, RHS = Scalar, Output = EdwardsPoint); 656 define_mul_variants!(LHS = Scalar, RHS = EdwardsPoint, Output = EdwardsPoint); 657 658 impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsPoint { 659 type Output = EdwardsPoint; 660 /// Scalar multiplication: compute `scalar * self`. 661 /// 662 /// For scalar multiplication of a basepoint, 663 /// `EdwardsBasepointTable` is approximately 4x faster. mul(self, scalar: &'b Scalar) -> EdwardsPoint664 fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { 665 scalar_mul::variable_base::mul(self, scalar) 666 } 667 } 668 669 impl<'a, 'b> Mul<&'b EdwardsPoint> for &'a Scalar { 670 type Output = EdwardsPoint; 671 672 /// Scalar multiplication: compute `scalar * self`. 673 /// 674 /// For scalar multiplication of a basepoint, 675 /// `EdwardsBasepointTable` is approximately 4x faster. mul(self, point: &'b EdwardsPoint) -> EdwardsPoint676 fn mul(self, point: &'b EdwardsPoint) -> EdwardsPoint { 677 point * self 678 } 679 } 680 681 // ------------------------------------------------------------------------ 682 // Multiscalar Multiplication impls 683 // ------------------------------------------------------------------------ 684 685 // These use the iterator's size hint and the target settings to 686 // forward to a specific backend implementation. 687 688 #[cfg(feature = "alloc")] 689 impl MultiscalarMul for EdwardsPoint { 690 type Point = EdwardsPoint; 691 multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator, J::Item: Borrow<EdwardsPoint>,692 fn multiscalar_mul<I, J>(scalars: I, points: J) -> EdwardsPoint 693 where 694 I: IntoIterator, 695 I::Item: Borrow<Scalar>, 696 J: IntoIterator, 697 J::Item: Borrow<EdwardsPoint>, 698 { 699 // Sanity-check lengths of input iterators 700 let mut scalars = scalars.into_iter(); 701 let mut points = points.into_iter(); 702 703 // Lower and upper bounds on iterators 704 let (s_lo, s_hi) = scalars.by_ref().size_hint(); 705 let (p_lo, p_hi) = points.by_ref().size_hint(); 706 707 // They should all be equal 708 assert_eq!(s_lo, p_lo); 709 assert_eq!(s_hi, Some(s_lo)); 710 assert_eq!(p_hi, Some(p_lo)); 711 712 // Now we know there's a single size. When we do 713 // size-dependent algorithm dispatch, use this as the hint. 714 let _size = s_lo; 715 716 scalar_mul::straus::Straus::multiscalar_mul(scalars, points) 717 } 718 } 719 720 #[cfg(feature = "alloc")] 721 impl VartimeMultiscalarMul for EdwardsPoint { 722 type Point = EdwardsPoint; 723 optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint> where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator<Item = Option<EdwardsPoint>>,724 fn optional_multiscalar_mul<I, J>(scalars: I, points: J) -> Option<EdwardsPoint> 725 where 726 I: IntoIterator, 727 I::Item: Borrow<Scalar>, 728 J: IntoIterator<Item = Option<EdwardsPoint>>, 729 { 730 // Sanity-check lengths of input iterators 731 let mut scalars = scalars.into_iter(); 732 let mut points = points.into_iter(); 733 734 // Lower and upper bounds on iterators 735 let (s_lo, s_hi) = scalars.by_ref().size_hint(); 736 let (p_lo, p_hi) = points.by_ref().size_hint(); 737 738 // They should all be equal 739 assert_eq!(s_lo, p_lo); 740 assert_eq!(s_hi, Some(s_lo)); 741 assert_eq!(p_hi, Some(p_lo)); 742 743 // Now we know there's a single size. 744 // Use this as the hint to decide which algorithm to use. 745 let size = s_lo; 746 747 if size < 190 { 748 scalar_mul::straus::Straus::optional_multiscalar_mul(scalars, points) 749 } else { 750 scalar_mul::pippenger::Pippenger::optional_multiscalar_mul(scalars, points) 751 } 752 } 753 } 754 755 /// Precomputation for variable-time multiscalar multiplication with `EdwardsPoint`s. 756 // This wraps the inner implementation in a facade type so that we can 757 // decouple stability of the inner type from the stability of the 758 // outer type. 759 #[cfg(feature = "alloc")] 760 pub struct VartimeEdwardsPrecomputation(scalar_mul::precomputed_straus::VartimePrecomputedStraus); 761 762 #[cfg(feature = "alloc")] 763 impl VartimePrecomputedMultiscalarMul for VartimeEdwardsPrecomputation { 764 type Point = EdwardsPoint; 765 new<I>(static_points: I) -> Self where I: IntoIterator, I::Item: Borrow<Self::Point>,766 fn new<I>(static_points: I) -> Self 767 where 768 I: IntoIterator, 769 I::Item: Borrow<Self::Point>, 770 { 771 Self(scalar_mul::precomputed_straus::VartimePrecomputedStraus::new(static_points)) 772 } 773 optional_mixed_multiscalar_mul<I, J, K>( &self, static_scalars: I, dynamic_scalars: J, dynamic_points: K, ) -> Option<Self::Point> where I: IntoIterator, I::Item: Borrow<Scalar>, J: IntoIterator, J::Item: Borrow<Scalar>, K: IntoIterator<Item = Option<Self::Point>>,774 fn optional_mixed_multiscalar_mul<I, J, K>( 775 &self, 776 static_scalars: I, 777 dynamic_scalars: J, 778 dynamic_points: K, 779 ) -> Option<Self::Point> 780 where 781 I: IntoIterator, 782 I::Item: Borrow<Scalar>, 783 J: IntoIterator, 784 J::Item: Borrow<Scalar>, 785 K: IntoIterator<Item = Option<Self::Point>>, 786 { 787 self.0 788 .optional_mixed_multiscalar_mul(static_scalars, dynamic_scalars, dynamic_points) 789 } 790 } 791 792 impl EdwardsPoint { 793 /// Compute \\(aA + bB\\) in variable time, where \\(B\\) is the Ed25519 basepoint. vartime_double_scalar_mul_basepoint( a: &Scalar, A: &EdwardsPoint, b: &Scalar, ) -> EdwardsPoint794 pub fn vartime_double_scalar_mul_basepoint( 795 a: &Scalar, 796 A: &EdwardsPoint, 797 b: &Scalar, 798 ) -> EdwardsPoint { 799 scalar_mul::vartime_double_base::mul(a, A, b) 800 } 801 } 802 803 macro_rules! impl_basepoint_table { 804 (Name = $name:ident, LookupTable = $table:ident, Point = $point:ty, Radix = $radix:expr, Additions = $adds:expr) => { 805 806 /// A precomputed table of multiples of a basepoint, for accelerating 807 /// fixed-base scalar multiplication. One table, for the Ed25519 808 /// basepoint, is provided in the `constants` module. 809 /// 810 /// The basepoint tables are reasonably large, so they should probably be boxed. 811 /// 812 /// The sizes for the tables and the number of additions required for one scalar 813 /// multiplication are as follows: 814 /// 815 /// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A 816 /// (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`]) 817 /// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A 818 /// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A 819 /// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A 820 /// 821 /// # Why 33 additions for radix-256? 822 /// 823 /// Normally, the radix-256 tables would allow for only 32 additions per scalar 824 /// multiplication. However, due to the fact that standardised definitions of 825 /// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar 826 /// invariants, when converting such an unreduced scalar's representation to 827 /// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last 828 /// coefficient (the coefficients are `i8`s). When, \\(w\\), the power-of-2 of 829 /// the radix, is \\(w < 8\\), we can fold the final carry onto the last 830 /// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so 831 /// $$ 832 /// d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8} 833 /// $$ 834 /// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we 835 /// add the carry bit onto an additional coefficient. 836 #[derive(Clone)] 837 pub struct $name(pub(crate) [$table<AffineNielsPoint>; 32]); 838 839 impl BasepointTable for $name { 840 type Point = $point; 841 842 /// Create a table of precomputed multiples of `basepoint`. 843 fn create(basepoint: &$point) -> $name { 844 // XXX use init_with 845 let mut table = $name([$table::default(); 32]); 846 let mut P = *basepoint; 847 for i in 0..32 { 848 // P = (2w)^i * B 849 table.0[i] = $table::from(&P); 850 P = P.mul_by_pow_2($radix + $radix); 851 } 852 table 853 } 854 855 /// Get the basepoint for this table as an `EdwardsPoint`. 856 fn basepoint(&self) -> $point { 857 // self.0[0].select(1) = 1*(16^2)^0*B 858 // but as an `AffineNielsPoint`, so add identity to convert to extended. 859 (&<$point>::identity() + &self.0[0].select(1)).to_extended() 860 } 861 862 /// The computation uses Pippeneger's algorithm, as described for the 863 /// specific case of radix-16 on page 13 of the Ed25519 paper. 864 /// 865 /// # Piggenger's Algorithm Generalised 866 /// 867 /// Write the scalar \\(a\\) in radix-\\(w\\), where \\(w\\) is a power of 868 /// 2, with coefficients in \\([\frac{-w}{2},\frac{w}{2})\\), i.e., 869 /// $$ 870 /// a = a\_0 + a\_1 w\^1 + \cdots + a\_{x} w\^{x}, 871 /// $$ 872 /// with 873 /// $$ 874 /// \frac{-w}{2} \leq a_i < \frac{w}{2}, \cdots, \frac{-w}{2} \leq a\_{x} \leq \frac{w}{2} 875 /// $$ 876 /// and the number of additions, \\(x\\), is given by \\(x = \lceil \frac{256}{w} \rceil\\). 877 /// Then 878 /// $$ 879 /// a B = a\_0 B + a\_1 w\^1 B + \cdots + a\_{x-1} w\^{x-1} B. 880 /// $$ 881 /// Grouping even and odd coefficients gives 882 /// $$ 883 /// \begin{aligned} 884 /// a B = \quad a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B \\\\ 885 /// + a\_1 w\^1 B +& a\_3 w\^3 B + \cdots + a\_{x-1} w\^{x-1} B \\\\ 886 /// = \quad(a\_0 w\^0 B +& a\_2 w\^2 B + \cdots + a\_{x-2} w\^{x-2} B) \\\\ 887 /// + w(a\_1 w\^0 B +& a\_3 w\^2 B + \cdots + a\_{x-1} w\^{x-2} B). \\\\ 888 /// \end{aligned} 889 /// $$ 890 /// For each \\(i = 0 \ldots 31\\), we create a lookup table of 891 /// $$ 892 /// [w\^{2i} B, \ldots, \frac{w}{2}\cdotw\^{2i} B], 893 /// $$ 894 /// and use it to select \\( y \cdot w\^{2i} \cdot B \\) in constant time. 895 /// 896 /// The radix-\\(w\\) representation requires that the scalar is bounded 897 /// by \\(2\^{255}\\), which is always the case. 898 /// 899 /// The above algorithm is trivially generalised to other powers-of-2 radices. 900 fn basepoint_mul(&self, scalar: &Scalar) -> $point { 901 let a = scalar.to_radix_2w($radix); 902 903 let tables = &self.0; 904 let mut P = <$point>::identity(); 905 906 for i in (0..$adds).filter(|x| x % 2 == 1) { 907 P = (&P + &tables[i/2].select(a[i])).to_extended(); 908 } 909 910 P = P.mul_by_pow_2($radix); 911 912 for i in (0..$adds).filter(|x| x % 2 == 0) { 913 P = (&P + &tables[i/2].select(a[i])).to_extended(); 914 } 915 916 P 917 } 918 } 919 920 impl<'a, 'b> Mul<&'b Scalar> for &'a $name { 921 type Output = $point; 922 923 /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by 924 /// computing the multiple \\(aB\\) of this basepoint \\(B\\). 925 fn mul(self, scalar: &'b Scalar) -> $point { 926 // delegate to a private function so that its documentation appears in internal docs 927 self.basepoint_mul(scalar) 928 } 929 } 930 931 impl<'a, 'b> Mul<&'a $name> for &'b Scalar { 932 type Output = $point; 933 934 /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by 935 /// computing the multiple \\(aB\\) of this basepoint \\(B\\). 936 fn mul(self, basepoint_table: &'a $name) -> $point { 937 basepoint_table * self 938 } 939 } 940 941 impl Debug for $name { 942 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 943 write!(f, "{:?}([\n", stringify!($name))?; 944 for i in 0..32 { 945 write!(f, "\t{:?},\n", &self.0[i])?; 946 } 947 write!(f, "])") 948 } 949 } 950 951 }} // End macro_rules! impl_basepoint_table 952 953 // The number of additions required is ceil(256/w) where w is the radix representation. 954 impl_basepoint_table! {Name = EdwardsBasepointTableRadix16, LookupTable = LookupTableRadix16, Point = EdwardsPoint, Radix = 4, Additions = 64} 955 impl_basepoint_table! {Name = EdwardsBasepointTableRadix32, LookupTable = LookupTableRadix32, Point = EdwardsPoint, Radix = 5, Additions = 52} 956 impl_basepoint_table! {Name = EdwardsBasepointTableRadix64, LookupTable = LookupTableRadix64, Point = EdwardsPoint, Radix = 6, Additions = 43} 957 impl_basepoint_table! {Name = EdwardsBasepointTableRadix128, LookupTable = LookupTableRadix128, Point = EdwardsPoint, Radix = 7, Additions = 37} 958 impl_basepoint_table! {Name = EdwardsBasepointTableRadix256, LookupTable = LookupTableRadix256, Point = EdwardsPoint, Radix = 8, Additions = 33} 959 960 // ------------------------------------------------------------------------------------- 961 // BEGIN legacy 3.x series code for backwards compatibility with BasepointTable trait 962 // ------------------------------------------------------------------------------------- 963 964 /// A precomputed table of multiples of a basepoint, for accelerating 965 /// fixed-base scalar multiplication. One table, for the Ed25519 966 /// basepoint, is provided in the `constants` module. 967 /// 968 /// The basepoint tables are reasonably large, so they should probably be boxed. 969 /// 970 /// The sizes for the tables and the number of additions required for one scalar 971 /// multiplication are as follows: 972 /// 973 /// * [`EdwardsBasepointTableRadix16`]: 30KB, 64A 974 /// (this is the default size, and is used for [`ED25519_BASEPOINT_TABLE`]) 975 /// * [`EdwardsBasepointTableRadix64`]: 120KB, 43A 976 /// * [`EdwardsBasepointTableRadix128`]: 240KB, 37A 977 /// * [`EdwardsBasepointTableRadix256`]: 480KB, 33A 978 /// 979 /// # Why 33 additions for radix-256? 980 /// 981 /// Normally, the radix-256 tables would allow for only 32 additions per scalar 982 /// multiplication. However, due to the fact that standardised definitions of 983 /// legacy protocols—such as x25519—require allowing unreduced 255-bit scalar 984 /// invariants, when converting such an unreduced scalar's representation to 985 /// radix-\\(2^{8}\\), we cannot guarantee the carry bit will fit in the last 986 /// coefficient (the coefficients are `i8`s). When, \\(w\\), the power-of-2 of 987 /// the radix, is \\(w < 8\\), we can fold the final carry onto the last 988 /// coefficient, \\(d\\), because \\(d < 2^{w/2}\\), so 989 /// $$ 990 /// d + carry \cdot 2^{w} = d + 1 \cdot 2^{w} < 2^{w+1} < 2^{8} 991 /// $$ 992 /// When \\(w = 8\\), we can't fit \\(carry \cdot 2^{w}\\) into an `i8`, so we 993 /// add the carry bit onto an additional coefficient. 994 #[derive(Clone)] 995 pub struct EdwardsBasepointTable(pub(crate) [LookupTable<AffineNielsPoint>; 32]); 996 997 impl EdwardsBasepointTable { 998 /// Create a table of precomputed multiples of `basepoint`. 999 #[allow(warnings)] create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable1000 pub fn create(basepoint: &EdwardsPoint) -> EdwardsBasepointTable { 1001 Self(EdwardsBasepointTableRadix16::create(basepoint).0) 1002 } 1003 1004 /// The computation uses Pippenger's algorithm, as described on 1005 /// page 13 of the Ed25519 paper. Write the scalar \\(a\\) in radix \\(16\\) with 1006 /// coefficients in \\([-8,8)\\), i.e., 1007 /// $$ 1008 /// a = a\_0 + a\_1 16\^1 + \cdots + a\_{63} 16\^{63}, 1009 /// $$ 1010 /// with \\(-8 \leq a_i < 8\\), \\(-8 \leq a\_{63} \leq 8\\). Then 1011 /// $$ 1012 /// a B = a\_0 B + a\_1 16\^1 B + \cdots + a\_{63} 16\^{63} B. 1013 /// $$ 1014 /// Grouping even and odd coefficients gives 1015 /// $$ 1016 /// \begin{aligned} 1017 /// a B = \quad a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B \\\\ 1018 /// + a\_1 16\^1 B +& a\_3 16\^3 B + \cdots + a\_{63} 16\^{63} B \\\\ 1019 /// = \quad(a\_0 16\^0 B +& a\_2 16\^2 B + \cdots + a\_{62} 16\^{62} B) \\\\ 1020 /// + 16(a\_1 16\^0 B +& a\_3 16\^2 B + \cdots + a\_{63} 16\^{62} B). \\\\ 1021 /// \end{aligned} 1022 /// $$ 1023 /// For each \\(i = 0 \ldots 31\\), we create a lookup table of 1024 /// $$ 1025 /// [16\^{2i} B, \ldots, 8\cdot16\^{2i} B], 1026 /// $$ 1027 /// and use it to select \\( x \cdot 16\^{2i} \cdot B \\) in constant time. 1028 /// 1029 /// The radix-\\(16\\) representation requires that the scalar is bounded 1030 /// by \\(2\^{255}\\), which is always the case. 1031 #[allow(warnings)] basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint1032 pub fn basepoint_mul(&self, scalar: &Scalar) -> EdwardsPoint { 1033 let a = scalar.to_radix_16(); 1034 1035 let tables = &self.0; 1036 let mut P = EdwardsPoint::identity(); 1037 1038 for i in (0..64).filter(|x| x % 2 == 1) { 1039 P = (&P + &tables[i/2].select(a[i])).to_extended(); 1040 } 1041 1042 P = P.mul_by_pow_2(4); 1043 1044 for i in (0..64).filter(|x| x % 2 == 0) { 1045 P = (&P + &tables[i/2].select(a[i])).to_extended(); 1046 } 1047 1048 P 1049 } 1050 1051 /// Get the basepoint for this table as an `EdwardsPoint`. 1052 #[allow(warnings)] basepoint(&self) -> EdwardsPoint1053 pub fn basepoint(&self) -> EdwardsPoint { 1054 (&EdwardsPoint::identity() + &self.0[0].select(1)).to_extended() 1055 } 1056 } 1057 1058 impl<'a, 'b> Mul<&'b Scalar> for &'a EdwardsBasepointTable { 1059 type Output = EdwardsPoint; 1060 1061 /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by 1062 /// computing the multiple \\(aB\\) of this basepoint \\(B\\). mul(self, scalar: &'b Scalar) -> EdwardsPoint1063 fn mul(self, scalar: &'b Scalar) -> EdwardsPoint { 1064 // delegate to a private function so that its documentation appears in internal docs 1065 self.basepoint_mul(scalar) 1066 } 1067 } 1068 1069 impl<'a, 'b> Mul<&'a EdwardsBasepointTable> for &'b Scalar { 1070 type Output = EdwardsPoint; 1071 1072 /// Construct an `EdwardsPoint` from a `Scalar` \\(a\\) by 1073 /// computing the multiple \\(aB\\) of this basepoint \\(B\\). mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint1074 fn mul(self, basepoint_table: &'a EdwardsBasepointTable) -> EdwardsPoint { 1075 basepoint_table * self 1076 } 1077 } 1078 1079 // ------------------------------------------------------------------------------------- 1080 // END legacy 3.x series code for backwards compatibility with BasepointTable trait 1081 // ------------------------------------------------------------------------------------- 1082 1083 macro_rules! impl_basepoint_table_conversions { 1084 (LHS = $lhs:ty, RHS = $rhs:ty) => { 1085 impl<'a> From<&'a $lhs> for $rhs { 1086 fn from(table: &'a $lhs) -> $rhs { 1087 <$rhs>::create(&table.basepoint()) 1088 } 1089 } 1090 1091 impl<'a> From<&'a $rhs> for $lhs { 1092 fn from(table: &'a $rhs) -> $lhs { 1093 <$lhs>::create(&table.basepoint()) 1094 } 1095 } 1096 } 1097 } 1098 1099 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix32} 1100 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix64} 1101 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix128} 1102 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix16, RHS = EdwardsBasepointTableRadix256} 1103 1104 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix64} 1105 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix128} 1106 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix32, RHS = EdwardsBasepointTableRadix256} 1107 1108 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix128} 1109 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix64, RHS = EdwardsBasepointTableRadix256} 1110 1111 impl_basepoint_table_conversions!{LHS = EdwardsBasepointTableRadix128, RHS = EdwardsBasepointTableRadix256} 1112 1113 impl EdwardsPoint { 1114 /// Multiply by the cofactor: return \\([8]P\\). mul_by_cofactor(&self) -> EdwardsPoint1115 pub fn mul_by_cofactor(&self) -> EdwardsPoint { 1116 self.mul_by_pow_2(3) 1117 } 1118 1119 /// Compute \\([2\^k] P \\) by successive doublings. Requires \\( k > 0 \\). mul_by_pow_2(&self, k: u32) -> EdwardsPoint1120 pub(crate) fn mul_by_pow_2(&self, k: u32) -> EdwardsPoint { 1121 debug_assert!( k > 0 ); 1122 let mut r: CompletedPoint; 1123 let mut s = self.to_projective(); 1124 for _ in 0..(k-1) { 1125 r = s.double(); s = r.to_projective(); 1126 } 1127 // Unroll last iteration so we can go directly to_extended() 1128 s.double().to_extended() 1129 } 1130 1131 /// Determine if this point is of small order. 1132 /// 1133 /// # Return 1134 /// 1135 /// * `true` if `self` is in the torsion subgroup \\( \mathcal E[8] \\); 1136 /// * `false` if `self` is not in the torsion subgroup \\( \mathcal E[8] \\). 1137 /// 1138 /// # Example 1139 /// 1140 /// ``` 1141 /// use curve25519_dalek::constants; 1142 /// 1143 /// // Generator of the prime-order subgroup 1144 /// let P = constants::ED25519_BASEPOINT_POINT; 1145 /// // Generator of the torsion subgroup 1146 /// let Q = constants::EIGHT_TORSION[1]; 1147 /// 1148 /// // P has large order 1149 /// assert_eq!(P.is_small_order(), false); 1150 /// 1151 /// // Q has small order 1152 /// assert_eq!(Q.is_small_order(), true); 1153 /// ``` is_small_order(&self) -> bool1154 pub fn is_small_order(&self) -> bool { 1155 self.mul_by_cofactor().is_identity() 1156 } 1157 1158 /// Determine if this point is “torsion-free”, i.e., is contained in 1159 /// the prime-order subgroup. 1160 /// 1161 /// # Return 1162 /// 1163 /// * `true` if `self` has zero torsion component and is in the 1164 /// prime-order subgroup; 1165 /// * `false` if `self` has a nonzero torsion component and is not 1166 /// in the prime-order subgroup. 1167 /// 1168 /// # Example 1169 /// 1170 /// ``` 1171 /// use curve25519_dalek::constants; 1172 /// 1173 /// // Generator of the prime-order subgroup 1174 /// let P = constants::ED25519_BASEPOINT_POINT; 1175 /// // Generator of the torsion subgroup 1176 /// let Q = constants::EIGHT_TORSION[1]; 1177 /// 1178 /// // P is torsion-free 1179 /// assert_eq!(P.is_torsion_free(), true); 1180 /// 1181 /// // P + Q is not torsion-free 1182 /// assert_eq!((P+Q).is_torsion_free(), false); 1183 /// ``` is_torsion_free(&self) -> bool1184 pub fn is_torsion_free(&self) -> bool { 1185 (self * constants::BASEPOINT_ORDER).is_identity() 1186 } 1187 } 1188 1189 // ------------------------------------------------------------------------ 1190 // Debug traits 1191 // ------------------------------------------------------------------------ 1192 1193 impl Debug for EdwardsPoint { fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result1194 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { 1195 write!(f, "EdwardsPoint{{\n\tX: {:?},\n\tY: {:?},\n\tZ: {:?},\n\tT: {:?}\n}}", 1196 &self.X, &self.Y, &self.Z, &self.T) 1197 } 1198 } 1199 1200 // ------------------------------------------------------------------------ 1201 // Tests 1202 // ------------------------------------------------------------------------ 1203 1204 #[cfg(test)] 1205 mod test { 1206 use field::FieldElement; 1207 use scalar::Scalar; 1208 use subtle::ConditionallySelectable; 1209 use constants; 1210 use super::*; 1211 1212 /// X coordinate of the basepoint. 1213 /// = 15112221349535400772501151409588531511454012693041857206046113283949847762202 1214 static BASE_X_COORD_BYTES: [u8; 32] = 1215 [0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 1216 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21]; 1217 1218 /// Compressed Edwards Y form of 2*basepoint. 1219 static BASE2_CMPRSSD: CompressedEdwardsY = 1220 CompressedEdwardsY([0xc9, 0xa3, 0xf8, 0x6a, 0xae, 0x46, 0x5f, 0xe, 1221 0x56, 0x51, 0x38, 0x64, 0x51, 0x0f, 0x39, 0x97, 1222 0x56, 0x1f, 0xa2, 0xc9, 0xe8, 0x5e, 0xa2, 0x1d, 1223 0xc2, 0x29, 0x23, 0x09, 0xf3, 0xcd, 0x60, 0x22]); 1224 1225 /// Compressed Edwards Y form of 16*basepoint. 1226 static BASE16_CMPRSSD: CompressedEdwardsY = 1227 CompressedEdwardsY([0xeb, 0x27, 0x67, 0xc1, 0x37, 0xab, 0x7a, 0xd8, 1228 0x27, 0x9c, 0x07, 0x8e, 0xff, 0x11, 0x6a, 0xb0, 1229 0x78, 0x6e, 0xad, 0x3a, 0x2e, 0x0f, 0x98, 0x9f, 1230 0x72, 0xc3, 0x7f, 0x82, 0xf2, 0x96, 0x96, 0x70]); 1231 1232 /// 4493907448824000747700850167940867464579944529806937181821189941592931634714 1233 pub static A_SCALAR: Scalar = Scalar{ 1234 bytes: [ 1235 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, 1236 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, 1237 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, 1238 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, 1239 ], 1240 }; 1241 1242 /// 2506056684125797857694181776241676200180934651973138769173342316833279714961 1243 pub static B_SCALAR: Scalar = Scalar{ 1244 bytes: [ 1245 0x91, 0x26, 0x7a, 0xcf, 0x25, 0xc2, 0x09, 0x1b, 1246 0xa2, 0x17, 0x74, 0x7b, 0x66, 0xf0, 0xb3, 0x2e, 1247 0x9d, 0xf2, 0xa5, 0x67, 0x41, 0xcf, 0xda, 0xc4, 1248 0x56, 0xa7, 0xd4, 0xaa, 0xb8, 0x60, 0x8a, 0x05, 1249 ], 1250 }; 1251 1252 /// A_SCALAR * basepoint, computed with ed25519.py 1253 pub static A_TIMES_BASEPOINT: CompressedEdwardsY = CompressedEdwardsY([ 1254 0xea, 0x27, 0xe2, 0x60, 0x53, 0xdf, 0x1b, 0x59, 1255 0x56, 0xf1, 0x4d, 0x5d, 0xec, 0x3c, 0x34, 0xc3, 1256 0x84, 0xa2, 0x69, 0xb7, 0x4c, 0xc3, 0x80, 0x3e, 1257 0xa8, 0xe2, 0xe7, 0xc9, 0x42, 0x5e, 0x40, 0xa5]); 1258 1259 /// A_SCALAR * (A_TIMES_BASEPOINT) + B_SCALAR * BASEPOINT 1260 /// computed with ed25519.py 1261 static DOUBLE_SCALAR_MULT_RESULT: CompressedEdwardsY = CompressedEdwardsY([ 1262 0x7d, 0xfd, 0x6c, 0x45, 0xaf, 0x6d, 0x6e, 0x0e, 1263 0xba, 0x20, 0x37, 0x1a, 0x23, 0x64, 0x59, 0xc4, 1264 0xc0, 0x46, 0x83, 0x43, 0xde, 0x70, 0x4b, 0x85, 1265 0x09, 0x6f, 0xfe, 0x35, 0x4f, 0x13, 0x2b, 0x42]); 1266 1267 /// Test round-trip decompression for the basepoint. 1268 #[test] basepoint_decompression_compression()1269 fn basepoint_decompression_compression() { 1270 let base_X = FieldElement::from_bytes(&BASE_X_COORD_BYTES); 1271 let bp = constants::ED25519_BASEPOINT_COMPRESSED.decompress().unwrap(); 1272 assert!(bp.is_valid()); 1273 // Check that decompression actually gives the correct X coordinate 1274 assert_eq!(base_X, bp.X); 1275 assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); 1276 } 1277 1278 /// Test sign handling in decompression 1279 #[test] decompression_sign_handling()1280 fn decompression_sign_handling() { 1281 // Manually set the high bit of the last byte to flip the sign 1282 let mut minus_basepoint_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes().clone(); 1283 minus_basepoint_bytes[31] |= 1 << 7; 1284 let minus_basepoint = CompressedEdwardsY(minus_basepoint_bytes) 1285 .decompress().unwrap(); 1286 // Test projective coordinates exactly since we know they should 1287 // only differ by a flipped sign. 1288 assert_eq!(minus_basepoint.X, -(&constants::ED25519_BASEPOINT_POINT.X)); 1289 assert_eq!(minus_basepoint.Y, constants::ED25519_BASEPOINT_POINT.Y); 1290 assert_eq!(minus_basepoint.Z, constants::ED25519_BASEPOINT_POINT.Z); 1291 assert_eq!(minus_basepoint.T, -(&constants::ED25519_BASEPOINT_POINT.T)); 1292 } 1293 1294 /// Test that computing 1*basepoint gives the correct basepoint. 1295 #[test] basepoint_mult_one_vs_basepoint()1296 fn basepoint_mult_one_vs_basepoint() { 1297 let bp = &constants::ED25519_BASEPOINT_TABLE * &Scalar::one(); 1298 let compressed = bp.compress(); 1299 assert_eq!(compressed, constants::ED25519_BASEPOINT_COMPRESSED); 1300 } 1301 1302 /// Test that `EdwardsBasepointTable::basepoint()` gives the correct basepoint. 1303 #[test] basepoint_table_basepoint_function_correct()1304 fn basepoint_table_basepoint_function_correct() { 1305 let bp = constants::ED25519_BASEPOINT_TABLE.basepoint(); 1306 assert_eq!(bp.compress(), constants::ED25519_BASEPOINT_COMPRESSED); 1307 } 1308 1309 /// Test `impl Add<EdwardsPoint> for EdwardsPoint` 1310 /// using basepoint + basepoint versus the 2*basepoint constant. 1311 #[test] basepoint_plus_basepoint_vs_basepoint2()1312 fn basepoint_plus_basepoint_vs_basepoint2() { 1313 let bp = constants::ED25519_BASEPOINT_POINT; 1314 let bp_added = &bp + &bp; 1315 assert_eq!(bp_added.compress(), BASE2_CMPRSSD); 1316 } 1317 1318 /// Test `impl Add<ProjectiveNielsPoint> for EdwardsPoint` 1319 /// using the basepoint, basepoint2 constants 1320 #[test] basepoint_plus_basepoint_projective_niels_vs_basepoint2()1321 fn basepoint_plus_basepoint_projective_niels_vs_basepoint2() { 1322 let bp = constants::ED25519_BASEPOINT_POINT; 1323 let bp_added = (&bp + &bp.to_projective_niels()).to_extended(); 1324 assert_eq!(bp_added.compress(), BASE2_CMPRSSD); 1325 } 1326 1327 /// Test `impl Add<AffineNielsPoint> for EdwardsPoint` 1328 /// using the basepoint, basepoint2 constants 1329 #[test] basepoint_plus_basepoint_affine_niels_vs_basepoint2()1330 fn basepoint_plus_basepoint_affine_niels_vs_basepoint2() { 1331 let bp = constants::ED25519_BASEPOINT_POINT; 1332 let bp_affine_niels = bp.to_affine_niels(); 1333 let bp_added = (&bp + &bp_affine_niels).to_extended(); 1334 assert_eq!(bp_added.compress(), BASE2_CMPRSSD); 1335 } 1336 1337 /// Check that equality of `EdwardsPoints` handles projective 1338 /// coordinates correctly. 1339 #[test] extended_point_equality_handles_scaling()1340 fn extended_point_equality_handles_scaling() { 1341 let mut two_bytes = [0u8; 32]; two_bytes[0] = 2; 1342 let id1 = EdwardsPoint::identity(); 1343 let id2 = EdwardsPoint{ 1344 X: FieldElement::zero(), 1345 Y: FieldElement::from_bytes(&two_bytes), 1346 Z: FieldElement::from_bytes(&two_bytes), 1347 T: FieldElement::zero() 1348 }; 1349 assert_eq!(id1.ct_eq(&id2).unwrap_u8(), 1u8); 1350 } 1351 1352 /// Sanity check for conversion to precomputed points 1353 #[test] to_affine_niels_clears_denominators()1354 fn to_affine_niels_clears_denominators() { 1355 // construct a point as aB so it has denominators (ie. Z != 1) 1356 let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; 1357 let aB_affine_niels = aB.to_affine_niels(); 1358 let also_aB = (&EdwardsPoint::identity() + &aB_affine_niels).to_extended(); 1359 assert_eq!( aB.compress(), 1360 also_aB.compress()); 1361 } 1362 1363 /// Test basepoint_mult versus a known scalar multiple from ed25519.py 1364 #[test] basepoint_mult_vs_ed25519py()1365 fn basepoint_mult_vs_ed25519py() { 1366 let aB = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; 1367 assert_eq!(aB.compress(), A_TIMES_BASEPOINT); 1368 } 1369 1370 /// Test that multiplication by the basepoint order kills the basepoint 1371 #[test] basepoint_mult_by_basepoint_order()1372 fn basepoint_mult_by_basepoint_order() { 1373 let B = &constants::ED25519_BASEPOINT_TABLE; 1374 let should_be_id = B * &constants::BASEPOINT_ORDER; 1375 assert!(should_be_id.is_identity()); 1376 } 1377 1378 /// Test precomputed basepoint mult 1379 #[test] test_precomputed_basepoint_mult()1380 fn test_precomputed_basepoint_mult() { 1381 let aB_1 = &constants::ED25519_BASEPOINT_TABLE * &A_SCALAR; 1382 let aB_2 = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; 1383 assert_eq!(aB_1.compress(), aB_2.compress()); 1384 } 1385 1386 /// Test scalar_mul versus a known scalar multiple from ed25519.py 1387 #[test] scalar_mul_vs_ed25519py()1388 fn scalar_mul_vs_ed25519py() { 1389 let aB = &constants::ED25519_BASEPOINT_POINT * &A_SCALAR; 1390 assert_eq!(aB.compress(), A_TIMES_BASEPOINT); 1391 } 1392 1393 /// Test basepoint.double() versus the 2*basepoint constant. 1394 #[test] basepoint_double_vs_basepoint2()1395 fn basepoint_double_vs_basepoint2() { 1396 assert_eq!(constants::ED25519_BASEPOINT_POINT.double().compress(), 1397 BASE2_CMPRSSD); 1398 } 1399 1400 /// Test that computing 2*basepoint is the same as basepoint.double() 1401 #[test] basepoint_mult_two_vs_basepoint2()1402 fn basepoint_mult_two_vs_basepoint2() { 1403 let two = Scalar::from(2u64); 1404 let bp2 = &constants::ED25519_BASEPOINT_TABLE * &two; 1405 assert_eq!(bp2.compress(), BASE2_CMPRSSD); 1406 } 1407 1408 /// Test that all the basepoint table types compute the same results. 1409 #[test] basepoint_tables()1410 fn basepoint_tables() { 1411 let P = &constants::ED25519_BASEPOINT_POINT; 1412 let a = A_SCALAR; 1413 1414 let table_radix16 = EdwardsBasepointTableRadix16::create(&P); 1415 let table_radix32 = EdwardsBasepointTableRadix32::create(&P); 1416 let table_radix64 = EdwardsBasepointTableRadix64::create(&P); 1417 let table_radix128 = EdwardsBasepointTableRadix128::create(&P); 1418 let table_radix256 = EdwardsBasepointTableRadix256::create(&P); 1419 1420 let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress(); 1421 let aP16 = (&table_radix16 * &a).compress(); 1422 let aP32 = (&table_radix32 * &a).compress(); 1423 let aP64 = (&table_radix64 * &a).compress(); 1424 let aP128 = (&table_radix128 * &a).compress(); 1425 let aP256 = (&table_radix256 * &a).compress(); 1426 1427 assert_eq!(aP, aP16); 1428 assert_eq!(aP16, aP32); 1429 assert_eq!(aP32, aP64); 1430 assert_eq!(aP64, aP128); 1431 assert_eq!(aP128, aP256); 1432 } 1433 1434 // Check a unreduced scalar multiplication by the basepoint tables. 1435 #[test] basepoint_tables_unreduced_scalar()1436 fn basepoint_tables_unreduced_scalar() { 1437 let P = &constants::ED25519_BASEPOINT_POINT; 1438 let a = Scalar::from_bits([ 1439 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1440 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1441 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1442 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1443 ]); 1444 1445 let table_radix16 = EdwardsBasepointTableRadix16::create(&P); 1446 let table_radix32 = EdwardsBasepointTableRadix32::create(&P); 1447 let table_radix64 = EdwardsBasepointTableRadix64::create(&P); 1448 let table_radix128 = EdwardsBasepointTableRadix128::create(&P); 1449 let table_radix256 = EdwardsBasepointTableRadix256::create(&P); 1450 1451 let aP = (&constants::ED25519_BASEPOINT_TABLE * &a).compress(); 1452 let aP16 = (&table_radix16 * &a).compress(); 1453 let aP32 = (&table_radix32 * &a).compress(); 1454 let aP64 = (&table_radix64 * &a).compress(); 1455 let aP128 = (&table_radix128 * &a).compress(); 1456 let aP256 = (&table_radix256 * &a).compress(); 1457 1458 assert_eq!(aP, aP16); 1459 assert_eq!(aP16, aP32); 1460 assert_eq!(aP32, aP64); 1461 assert_eq!(aP64, aP128); 1462 assert_eq!(aP128, aP256); 1463 } 1464 1465 /// Check that converting to projective and then back to extended round-trips. 1466 #[test] basepoint_projective_extended_round_trip()1467 fn basepoint_projective_extended_round_trip() { 1468 assert_eq!(constants::ED25519_BASEPOINT_POINT 1469 .to_projective().to_extended().compress(), 1470 constants::ED25519_BASEPOINT_COMPRESSED); 1471 } 1472 1473 /// Test computing 16*basepoint vs mul_by_pow_2(4) 1474 #[test] basepoint16_vs_mul_by_pow_2_4()1475 fn basepoint16_vs_mul_by_pow_2_4() { 1476 let bp16 = constants::ED25519_BASEPOINT_POINT.mul_by_pow_2(4); 1477 assert_eq!(bp16.compress(), BASE16_CMPRSSD); 1478 } 1479 1480 #[test] impl_sum()1481 fn impl_sum() { 1482 1483 // Test that sum works for non-empty iterators 1484 let BASE = constants::ED25519_BASEPOINT_POINT; 1485 1486 let s1 = Scalar::from(999u64); 1487 let P1 = &BASE * &s1; 1488 1489 let s2 = Scalar::from(333u64); 1490 let P2 = &BASE * &s2; 1491 1492 let vec = vec![P1.clone(), P2.clone()]; 1493 let sum: EdwardsPoint = vec.iter().sum(); 1494 1495 assert_eq!(sum, P1 + P2); 1496 1497 // Test that sum works for the empty iterator 1498 let empty_vector: Vec<EdwardsPoint> = vec![]; 1499 let sum: EdwardsPoint = empty_vector.iter().sum(); 1500 1501 assert_eq!(sum, EdwardsPoint::identity()); 1502 1503 // Test that sum works on owning iterators 1504 let s = Scalar::from(2u64); 1505 let mapped = vec.iter().map(|x| x * s); 1506 let sum: EdwardsPoint = mapped.sum(); 1507 1508 assert_eq!(sum, &P1 * &s + &P2 * &s); 1509 } 1510 1511 1512 /// Test that the conditional assignment trait works for AffineNielsPoints. 1513 #[test] conditional_assign_for_affine_niels_point()1514 fn conditional_assign_for_affine_niels_point() { 1515 let id = AffineNielsPoint::identity(); 1516 let mut p1 = AffineNielsPoint::identity(); 1517 let bp = constants::ED25519_BASEPOINT_POINT.to_affine_niels(); 1518 1519 p1.conditional_assign(&bp, Choice::from(0)); 1520 assert_eq!(p1, id); 1521 p1.conditional_assign(&bp, Choice::from(1)); 1522 assert_eq!(p1, bp); 1523 } 1524 1525 #[test] is_small_order()1526 fn is_small_order() { 1527 // The basepoint has large prime order 1528 assert!(!constants::ED25519_BASEPOINT_POINT.is_small_order()); 1529 // constants::EIGHT_TORSION has all points of small order. 1530 for torsion_point in &constants::EIGHT_TORSION { 1531 assert!(torsion_point.is_small_order()); 1532 } 1533 } 1534 1535 #[test] compressed_identity()1536 fn compressed_identity() { 1537 assert_eq!(EdwardsPoint::identity().compress(), 1538 CompressedEdwardsY::identity()); 1539 } 1540 1541 #[test] is_identity()1542 fn is_identity() { 1543 assert!( EdwardsPoint::identity().is_identity()); 1544 assert!(!constants::ED25519_BASEPOINT_POINT.is_identity()); 1545 } 1546 1547 /// Rust's debug builds have overflow and underflow trapping, 1548 /// and enable `debug_assert!()`. This performs many scalar 1549 /// multiplications to attempt to trigger possible overflows etc. 1550 /// 1551 /// For instance, the `u64` `Mul` implementation for 1552 /// `FieldElements` requires the input `Limb`s to be bounded by 1553 /// 2^54, but we cannot enforce this dynamically at runtime, or 1554 /// statically at compile time (until Rust gets type-level 1555 /// integers, at which point we can encode "bits of headroom" into 1556 /// the type system and prove correctness). 1557 #[test] monte_carlo_overflow_underflow_debug_assert_test()1558 fn monte_carlo_overflow_underflow_debug_assert_test() { 1559 let mut P = constants::ED25519_BASEPOINT_POINT; 1560 // N.B. each scalar_mul does 1407 field mults, 1024 field squarings, 1561 // so this does ~ 1M of each operation. 1562 for _ in 0..1_000 { 1563 P *= &A_SCALAR; 1564 } 1565 } 1566 1567 #[test] scalarmult_extended_point_works_both_ways()1568 fn scalarmult_extended_point_works_both_ways() { 1569 let G: EdwardsPoint = constants::ED25519_BASEPOINT_POINT; 1570 let s: Scalar = A_SCALAR; 1571 1572 let P1 = &G * &s; 1573 let P2 = &s * &G; 1574 1575 assert!(P1.compress().to_bytes() == P2.compress().to_bytes()); 1576 } 1577 1578 // A single iteration of a consistency check for MSM. multiscalar_consistency_iter(n: usize)1579 fn multiscalar_consistency_iter(n: usize) { 1580 use core::iter; 1581 let mut rng = rand::thread_rng(); 1582 1583 // Construct random coefficients x0, ..., x_{n-1}, 1584 // followed by some extra hardcoded ones. 1585 let xs = (0..n) 1586 .map(|_| Scalar::random(&mut rng)) 1587 // The largest scalar allowed by the type system, 2^255-1 1588 .chain(iter::once(Scalar::from_bits([0xff; 32]))) 1589 .collect::<Vec<_>>(); 1590 let check = xs.iter() 1591 .map(|xi| xi * xi) 1592 .sum::<Scalar>(); 1593 1594 // Construct points G_i = x_i * B 1595 let Gs = xs.iter() 1596 .map(|xi| xi * &constants::ED25519_BASEPOINT_TABLE) 1597 .collect::<Vec<_>>(); 1598 1599 // Compute H1 = <xs, Gs> (consttime) 1600 let H1 = EdwardsPoint::multiscalar_mul(&xs, &Gs); 1601 // Compute H2 = <xs, Gs> (vartime) 1602 let H2 = EdwardsPoint::vartime_multiscalar_mul(&xs, &Gs); 1603 // Compute H3 = <xs, Gs> = sum(xi^2) * B 1604 let H3 = &check * &constants::ED25519_BASEPOINT_TABLE; 1605 1606 assert_eq!(H1, H3); 1607 assert_eq!(H2, H3); 1608 } 1609 1610 // Use different multiscalar sizes to hit different internal 1611 // parameters. 1612 1613 #[test] multiscalar_consistency_n_100()1614 fn multiscalar_consistency_n_100() { 1615 let iters = 50; 1616 for _ in 0..iters { 1617 multiscalar_consistency_iter(100); 1618 } 1619 } 1620 1621 #[test] multiscalar_consistency_n_250()1622 fn multiscalar_consistency_n_250() { 1623 let iters = 50; 1624 for _ in 0..iters { 1625 multiscalar_consistency_iter(250); 1626 } 1627 } 1628 1629 #[test] multiscalar_consistency_n_500()1630 fn multiscalar_consistency_n_500() { 1631 let iters = 50; 1632 for _ in 0..iters { 1633 multiscalar_consistency_iter(500); 1634 } 1635 } 1636 1637 #[test] multiscalar_consistency_n_1000()1638 fn multiscalar_consistency_n_1000() { 1639 let iters = 50; 1640 for _ in 0..iters { 1641 multiscalar_consistency_iter(1000); 1642 } 1643 } 1644 1645 #[test] vartime_precomputed_vs_nonprecomputed_multiscalar()1646 fn vartime_precomputed_vs_nonprecomputed_multiscalar() { 1647 let mut rng = rand::thread_rng(); 1648 1649 let B = &::constants::ED25519_BASEPOINT_TABLE; 1650 1651 let static_scalars = (0..128) 1652 .map(|_| Scalar::random(&mut rng)) 1653 .collect::<Vec<_>>(); 1654 1655 let dynamic_scalars = (0..128) 1656 .map(|_| Scalar::random(&mut rng)) 1657 .collect::<Vec<_>>(); 1658 1659 let check_scalar: Scalar = static_scalars 1660 .iter() 1661 .chain(dynamic_scalars.iter()) 1662 .map(|s| s * s) 1663 .sum(); 1664 1665 let static_points = static_scalars.iter().map(|s| s * B).collect::<Vec<_>>(); 1666 let dynamic_points = dynamic_scalars.iter().map(|s| s * B).collect::<Vec<_>>(); 1667 1668 let precomputation = VartimeEdwardsPrecomputation::new(static_points.iter()); 1669 1670 let P = precomputation.vartime_mixed_multiscalar_mul( 1671 &static_scalars, 1672 &dynamic_scalars, 1673 &dynamic_points, 1674 ); 1675 1676 use traits::VartimeMultiscalarMul; 1677 let Q = EdwardsPoint::vartime_multiscalar_mul( 1678 static_scalars.iter().chain(dynamic_scalars.iter()), 1679 static_points.iter().chain(dynamic_points.iter()), 1680 ); 1681 1682 let R = &check_scalar * B; 1683 1684 assert_eq!(P.compress(), R.compress()); 1685 assert_eq!(Q.compress(), R.compress()); 1686 } 1687 1688 mod vartime { 1689 use super::super::*; 1690 use super::{A_SCALAR, B_SCALAR, A_TIMES_BASEPOINT, DOUBLE_SCALAR_MULT_RESULT}; 1691 1692 /// Test double_scalar_mul_vartime vs ed25519.py 1693 #[test] double_scalar_mul_basepoint_vs_ed25519py()1694 fn double_scalar_mul_basepoint_vs_ed25519py() { 1695 let A = A_TIMES_BASEPOINT.decompress().unwrap(); 1696 let result = EdwardsPoint::vartime_double_scalar_mul_basepoint(&A_SCALAR, &A, &B_SCALAR); 1697 assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); 1698 } 1699 1700 #[test] multiscalar_mul_vs_ed25519py()1701 fn multiscalar_mul_vs_ed25519py() { 1702 let A = A_TIMES_BASEPOINT.decompress().unwrap(); 1703 let result = EdwardsPoint::vartime_multiscalar_mul( 1704 &[A_SCALAR, B_SCALAR], 1705 &[A, constants::ED25519_BASEPOINT_POINT] 1706 ); 1707 assert_eq!(result.compress(), DOUBLE_SCALAR_MULT_RESULT); 1708 } 1709 1710 #[test] multiscalar_mul_vartime_vs_consttime()1711 fn multiscalar_mul_vartime_vs_consttime() { 1712 let A = A_TIMES_BASEPOINT.decompress().unwrap(); 1713 let result_vartime = EdwardsPoint::vartime_multiscalar_mul( 1714 &[A_SCALAR, B_SCALAR], 1715 &[A, constants::ED25519_BASEPOINT_POINT] 1716 ); 1717 let result_consttime = EdwardsPoint::multiscalar_mul( 1718 &[A_SCALAR, B_SCALAR], 1719 &[A, constants::ED25519_BASEPOINT_POINT] 1720 ); 1721 1722 assert_eq!(result_vartime.compress(), result_consttime.compress()); 1723 } 1724 } 1725 1726 #[test] 1727 #[cfg(feature = "serde")] serde_bincode_basepoint_roundtrip()1728 fn serde_bincode_basepoint_roundtrip() { 1729 use bincode; 1730 1731 let encoded = bincode::serialize(&constants::ED25519_BASEPOINT_POINT).unwrap(); 1732 let enc_compressed = bincode::serialize(&constants::ED25519_BASEPOINT_COMPRESSED).unwrap(); 1733 assert_eq!(encoded, enc_compressed); 1734 1735 // Check that the encoding is 32 bytes exactly 1736 assert_eq!(encoded.len(), 32); 1737 1738 let dec_uncompressed: EdwardsPoint = bincode::deserialize(&encoded).unwrap(); 1739 let dec_compressed: CompressedEdwardsY = bincode::deserialize(&encoded).unwrap(); 1740 1741 assert_eq!(dec_uncompressed, constants::ED25519_BASEPOINT_POINT); 1742 assert_eq!(dec_compressed, constants::ED25519_BASEPOINT_COMPRESSED); 1743 1744 // Check that the encoding itself matches the usual one 1745 let raw_bytes = constants::ED25519_BASEPOINT_COMPRESSED.as_bytes(); 1746 let bp: EdwardsPoint = bincode::deserialize(raw_bytes).unwrap(); 1747 assert_eq!(bp, constants::ED25519_BASEPOINT_POINT); 1748 } 1749 1750 //////////////////////////////////////////////////////////// 1751 // Signal tests from // 1752 // https://github.com/signalapp/libsignal-protocol-c/ // 1753 //////////////////////////////////////////////////////////// 1754 test_vectors() -> Vec<Vec<&'static str>>1755 fn test_vectors() -> Vec<Vec<&'static str>> { 1756 vec![ 1757 vec![ 1758 "214f306e1576f5a7577636fe303ca2c625b533319f52442b22a9fa3b7ede809f", 1759 "c95becf0f93595174633b9d4d6bbbeb88e16fa257176f877ce426e1424626052", 1760 ], 1761 vec![ 1762 "2eb10d432702ea7f79207da95d206f82d5a3b374f5f89f17a199531f78d3bea6", 1763 "d8f8b508edffbb8b6dab0f602f86a9dd759f800fe18f782fdcac47c234883e7f", 1764 ], 1765 vec![ 1766 "84cbe9accdd32b46f4a8ef51c85fd39d028711f77fb00e204a613fc235fd68b9", 1767 "93c73e0289afd1d1fc9e4e78a505d5d1b2642fbdf91a1eff7d281930654b1453", 1768 ], 1769 vec![ 1770 "c85165952490dc1839cb69012a3d9f2cc4b02343613263ab93a26dc89fd58267", 1771 "43cbe8685fd3c90665b91835debb89ff1477f906f5170f38a192f6a199556537", 1772 ], 1773 vec![ 1774 "26e7fc4a78d863b1a4ccb2ce0951fbcd021e106350730ee4157bacb4502e1b76", 1775 "b6fc3d738c2c40719479b2f23818180cdafa72a14254d4016bbed8f0b788a835", 1776 ], 1777 vec![ 1778 "1618c08ef0233f94f0f163f9435ec7457cd7a8cd4bb6b160315d15818c30f7a2", 1779 "da0b703593b29dbcd28ebd6e7baea17b6f61971f3641cae774f6a5137a12294c", 1780 ], 1781 vec![ 1782 "48b73039db6fcdcb6030c4a38e8be80b6390d8ae46890e77e623f87254ef149c", 1783 "ca11b25acbc80566603eabeb9364ebd50e0306424c61049e1ce9385d9f349966", 1784 ], 1785 vec![ 1786 "a744d582b3a34d14d311b7629da06d003045ae77cebceeb4e0e72734d63bd07d", 1787 "fad25a5ea15d4541258af8785acaf697a886c1b872c793790e60a6837b1adbc0", 1788 ], 1789 vec![ 1790 "80a6ff33494c471c5eff7efb9febfbcf30a946fe6535b3451cda79f2154a7095", 1791 "57ac03913309b3f8cd3c3d4c49d878bb21f4d97dc74a1eaccbe5c601f7f06f47", 1792 ], 1793 vec![ 1794 "f06fc939bc10551a0fd415aebf107ef0b9c4ee1ef9a164157bdd089127782617", 1795 "785b2a6a00a5579cc9da1ff997ce8339b6f9fb46c6f10cf7a12ff2986341a6e0", 1796 ], 1797 ] 1798 } 1799 1800 #[test] elligator_signal_test_vectors()1801 fn elligator_signal_test_vectors() { 1802 for vector in test_vectors().iter() { 1803 let input = hex::decode(vector[0]).unwrap(); 1804 let output = hex::decode(vector[1]).unwrap(); 1805 1806 let point = EdwardsPoint::hash_from_bytes::<sha2::Sha512>(&input); 1807 assert_eq!(point.compress().to_bytes(), output[..]); 1808 } 1809 } 1810 } 1811