1 // -*- mode: rust; -*-
2 //
3 // This file is part of curve25519-dalek.
4 // Copyright (c) 2016-2019 Isis Lovecruft, Henry de Valence
5 // See LICENSE for licensing information.
6 //
7 // Authors:
8 // - Isis Agora Lovecruft <isis@patternsinthevoid.net>
9 // - Henry de Valence <hdevalence@hdevalence.ca>
10 
11 //! Various constants, such as the Ristretto and Ed25519 basepoints.
12 //!
13 //! Most of the constants are given with
14 //! `LONG_DESCRIPTIVE_UPPER_CASE_NAMES`, but they can be brought into
15 //! scope using a `let` binding:
16 //!
17 //! ```
18 //! use curve25519_dalek::constants;
19 //! use curve25519_dalek::traits::IsIdentity;
20 //!
21 //! let B = &constants::RISTRETTO_BASEPOINT_TABLE;
22 //! let l = &constants::BASEPOINT_ORDER;
23 //!
24 //! let A = l * B;
25 //! assert!(A.is_identity());
26 //! ```
27 
28 #![allow(non_snake_case)]
29 
30 use edwards::CompressedEdwardsY;
31 use ristretto::RistrettoPoint;
32 use ristretto::CompressedRistretto;
33 use montgomery::MontgomeryPoint;
34 use scalar::Scalar;
35 
36 #[cfg(feature = "u64_backend")]
37 pub use backend::serial::u64::constants::*;
38 #[cfg(feature = "u32_backend")]
39 pub use backend::serial::u32::constants::*;
40 
41 /// The Ed25519 basepoint, in `CompressedEdwardsY` format.
42 ///
43 /// This is the little-endian byte encoding of \\( 4/5 \pmod p \\),
44 /// which is the \\(y\\)-coordinate of the Ed25519 basepoint.
45 ///
46 /// The sign bit is 0 since the basepoint has \\(x\\) chosen to be positive.
47 pub const ED25519_BASEPOINT_COMPRESSED: CompressedEdwardsY =
48     CompressedEdwardsY([0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
49                         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
50                         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
51                         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66]);
52 
53 /// The X25519 basepoint, in `MontgomeryPoint` format.
54 pub const X25519_BASEPOINT: MontgomeryPoint =
55     MontgomeryPoint([0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
59 
60 /// The Ristretto basepoint, in `CompressedRistretto` format.
61 pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto =
62     CompressedRistretto([0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71,
63                          0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f,
64                          0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d,
65                          0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76]);
66 
67 /// The Ristretto basepoint, as a `RistrettoPoint`.
68 ///
69 /// This is called `_POINT` to distinguish it from `_TABLE`, which
70 /// provides fast scalar multiplication.
71 pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT);
72 
73 /// `BASEPOINT_ORDER` is the order of the Ristretto group and of the Ed25519 basepoint, i.e.,
74 /// $$
75 /// \ell = 2^\{252\} + 27742317777372353535851937790883648493.
76 /// $$
77 pub const BASEPOINT_ORDER: Scalar = Scalar{
78     bytes: [
79         0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
80         0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
81         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
83     ],
84 };
85 
86 use ristretto::RistrettoBasepointTable;
87 /// The Ristretto basepoint, as a `RistrettoBasepointTable` for scalar multiplication.
88 pub const RISTRETTO_BASEPOINT_TABLE: RistrettoBasepointTable
89     = RistrettoBasepointTable(ED25519_BASEPOINT_TABLE);
90 
91 #[cfg(test)]
92 mod test {
93     use field::FieldElement;
94     use traits::{IsIdentity, ValidityCheck};
95     use constants;
96 
97     #[test]
test_eight_torsion()98     fn test_eight_torsion() {
99         for i in 0..8 {
100             let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(3);
101             assert!(Q.is_valid());
102             assert!(Q.is_identity());
103         }
104     }
105 
106     #[test]
test_four_torsion()107     fn test_four_torsion() {
108         for i in (0..8).filter(|i| i % 2 == 0) {
109             let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(2);
110             assert!(Q.is_valid());
111             assert!(Q.is_identity());
112         }
113     }
114 
115     #[test]
test_two_torsion()116     fn test_two_torsion() {
117         for i in (0..8).filter(|i| i % 4 == 0) {
118             let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(1);
119             assert!(Q.is_valid());
120             assert!(Q.is_identity());
121         }
122     }
123 
124     /// Test that SQRT_M1 is the positive square root of -1
125     #[test]
test_sqrt_minus_one()126     fn test_sqrt_minus_one() {
127         let minus_one = FieldElement::minus_one();
128         let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1;
129         assert_eq!(minus_one,  sqrt_m1_sq);
130         assert_eq!(constants::SQRT_M1.is_negative().unwrap_u8(), 0);
131     }
132 
133     #[test]
test_sqrt_constants_sign()134     fn test_sqrt_constants_sign() {
135         let minus_one = FieldElement::minus_one();
136         let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt();
137         assert_eq!(was_nonzero_square.unwrap_u8(), 1u8);
138         let sign_test_sqrt  = &invsqrt_m1 * &constants::SQRT_M1;
139         assert_eq!(sign_test_sqrt, minus_one);
140     }
141 
142     /// Test that d = -121665/121666
143     #[test]
144     #[cfg(feature = "u32_backend")]
test_d_vs_ratio()145     fn test_d_vs_ratio() {
146         use backend::serial::u32::field::FieldElement2625;
147         let a = -&FieldElement2625([121665,0,0,0,0,0,0,0,0,0]);
148         let b =   FieldElement2625([121666,0,0,0,0,0,0,0,0,0]);
149         let d = &a * &b.invert();
150         let d2 = &d + &d;
151         assert_eq!(d, constants::EDWARDS_D);
152         assert_eq!(d2, constants::EDWARDS_D2);
153     }
154 
155     /// Test that d = -121665/121666
156     #[test]
157     #[cfg(feature = "u64_backend")]
test_d_vs_ratio()158     fn test_d_vs_ratio() {
159         use backend::serial::u64::field::FieldElement51;
160         let a = -&FieldElement51([121665,0,0,0,0]);
161         let b =   FieldElement51([121666,0,0,0,0]);
162         let d = &a * &b.invert();
163         let d2 = &d + &d;
164         assert_eq!(d, constants::EDWARDS_D);
165         assert_eq!(d2, constants::EDWARDS_D2);
166     }
167 
168     #[test]
test_sqrt_ad_minus_one()169     fn test_sqrt_ad_minus_one() {
170         let a = FieldElement::minus_one();
171         let ad_minus_one = &(&a * &constants::EDWARDS_D) + &a;
172         let should_be_ad_minus_one = constants::SQRT_AD_MINUS_ONE.square();
173         assert_eq!(should_be_ad_minus_one, ad_minus_one);
174     }
175 
176 }
177