1#![allow(non_snake_case)]
14
15use cfg_if::cfg_if;
16
17use crate::edwards::CompressedEdwardsY;
18use crate::montgomery::MontgomeryPoint;
19use crate::ristretto::{CompressedRistretto, RistrettoPoint};
20use crate::scalar::Scalar;
21
22#[cfg(feature = "precomputed-tables")]
23use crate::edwards::EdwardsBasepointTable;
24
25cfg_if! {
26 if #[cfg(curve25519_dalek_backend = "fiat")] {
27 #[cfg(curve25519_dalek_bits = "32")]
28 pub use crate::backend::serial::fiat_u32::constants::*;
29 #[cfg(curve25519_dalek_bits = "64")]
30 pub use crate::backend::serial::fiat_u64::constants::*;
31 } else {
32 #[cfg(curve25519_dalek_bits = "32")]
33 pub use crate::backend::serial::u32::constants::*;
34 #[cfg(curve25519_dalek_bits = "64")]
35 pub use crate::backend::serial::u64::constants::*;
36 }
37}
38
39pub const ED25519_BASEPOINT_COMPRESSED: CompressedEdwardsY = CompressedEdwardsY([
46 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
47 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
48]);
49
50pub const X25519_BASEPOINT: MontgomeryPoint = MontgomeryPoint([
52 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54]);
55
56pub const RISTRETTO_BASEPOINT_COMPRESSED: CompressedRistretto = CompressedRistretto([
58 0xe2, 0xf2, 0xae, 0x0a, 0x6a, 0xbc, 0x4e, 0x71, 0xa8, 0x84, 0xa9, 0x61, 0xc5, 0x00, 0x51, 0x5f,
59 0x58, 0xe3, 0x0b, 0x6a, 0xa5, 0x82, 0xdd, 0x8d, 0xb6, 0xa6, 0x59, 0x45, 0xe0, 0x8d, 0x2d, 0x76,
60]);
61
62pub const RISTRETTO_BASEPOINT_POINT: RistrettoPoint = RistrettoPoint(ED25519_BASEPOINT_POINT);
67
68pub(crate) const BASEPOINT_ORDER: Scalar = Scalar {
73 bytes: [
74 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde,
75 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x10,
77 ],
78};
79
80#[cfg(feature = "precomputed-tables")]
81use crate::ristretto::RistrettoBasepointTable;
82
83#[cfg(feature = "precomputed-tables")]
85pub static RISTRETTO_BASEPOINT_TABLE: &RistrettoBasepointTable = unsafe {
86 &*(ED25519_BASEPOINT_TABLE as *const EdwardsBasepointTable as *const RistrettoBasepointTable)
89};
90
91#[rustfmt::skip]
98pub static X25519_LOW_ORDER_POINTS: [MontgomeryPoint; 7] = [
99 MontgomeryPoint([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
101
102 MontgomeryPoint([0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
104
105 MontgomeryPoint([0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00]),
107
108 MontgomeryPoint([0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57]),
110
111 MontgomeryPoint([0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]),
113
114 MontgomeryPoint([0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f]),
116
117 MontgomeryPoint([0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f])
119];
120
121#[cfg(test)]
122mod test {
123 use crate::constants;
124 use crate::field::FieldElement;
125 use crate::montgomery::MontgomeryPoint;
126 use crate::traits::{IsIdentity, ValidityCheck};
127
128 #[test]
129 fn test_eight_torsion() {
130 for i in 0..8 {
131 let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(3);
132 assert!(Q.is_valid());
133 assert!(Q.is_identity());
134 }
135 }
136
137 #[test]
138 fn test_four_torsion() {
139 for i in (0..8).filter(|i| i % 2 == 0) {
140 let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(2);
141 assert!(Q.is_valid());
142 assert!(Q.is_identity());
143 }
144 }
145
146 #[test]
147 fn test_two_torsion() {
148 for i in (0..8).filter(|i| i % 4 == 0) {
149 let Q = constants::EIGHT_TORSION[i].mul_by_pow_2(1);
150 assert!(Q.is_valid());
151 assert!(Q.is_identity());
152 }
153 }
154
155 #[test]
157 fn test_sqrt_minus_one() {
158 let minus_one = FieldElement::MINUS_ONE;
159 let sqrt_m1_sq = &constants::SQRT_M1 * &constants::SQRT_M1;
160 assert_eq!(minus_one, sqrt_m1_sq);
161 assert!(bool::from(!constants::SQRT_M1.is_negative()));
162 }
163
164 #[test]
165 fn test_sqrt_constants_sign() {
166 let minus_one = FieldElement::MINUS_ONE;
167 let (was_nonzero_square, invsqrt_m1) = minus_one.invsqrt();
168 assert!(bool::from(was_nonzero_square));
169 let sign_test_sqrt = &invsqrt_m1 * &constants::SQRT_M1;
170 assert_eq!(sign_test_sqrt, minus_one);
171 }
172
173 #[test]
175 #[cfg(all(curve25519_dalek_bits = "32", not(curve25519_dalek_backend = "fiat")))]
176 fn test_d_vs_ratio() {
177 use crate::backend::serial::u32::field::FieldElement2625;
178 let a = -&FieldElement2625([121665, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
179 let b = FieldElement2625([121666, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
180 let d = &a * &b.invert();
181 let d2 = &d + &d;
182 assert_eq!(d, constants::EDWARDS_D);
183 assert_eq!(d2, constants::EDWARDS_D2);
184 }
185
186 #[test]
188 #[cfg(all(curve25519_dalek_bits = "64", not(curve25519_dalek_backend = "fiat")))]
189 fn test_d_vs_ratio() {
190 use crate::backend::serial::u64::field::FieldElement51;
191 let a = -&FieldElement51([121665, 0, 0, 0, 0]);
192 let b = FieldElement51([121666, 0, 0, 0, 0]);
193 let d = &a * &b.invert();
194 let d2 = &d + &d;
195 assert_eq!(d, constants::EDWARDS_D);
196 assert_eq!(d2, constants::EDWARDS_D2);
197 }
198
199 #[test]
200 fn test_sqrt_ad_minus_one() {
201 let a = FieldElement::MINUS_ONE;
202 let ad_minus_one = &(&a * &constants::EDWARDS_D) + &a;
203 let should_be_ad_minus_one = constants::SQRT_AD_MINUS_ONE.square();
204 assert_eq!(should_be_ad_minus_one, ad_minus_one);
205 }
206
207 #[test]
208 fn low_order_point_scalar_mul() {
209 let scalar = [
211 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46,
212 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 0x50, 0x6a, 0x22, 0x44,
213 0xba, 0x44, 0x9a, 0xc4,
214 ];
215
216 for low_order_point in constants::X25519_LOW_ORDER_POINTS {
217 let output = low_order_point.mul_clamped(scalar);
218 assert_eq!(output, MontgomeryPoint([0; 32]));
219 }
220 }
221
222 #[test]
224 #[cfg(feature = "digest")]
225 fn test_sqrt_a_minus_2() {
226 let one = FieldElement::ONE;
227 let a_minus_two = &(&constants::MONTGOMERY_A_NEG - &one) - &one;
228
229 assert_eq!(constants::ED25519_SQRTAM2.square(), a_minus_two)
230 }
231}