/rust/registry/src/index.crates.io-1949cf8c6b5b557f/p256-0.13.2/src/arithmetic/field.rs
Line | Count | Source |
1 | | //! Field arithmetic modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1 |
2 | | |
3 | | #![allow(clippy::assign_op_pattern, clippy::op_ref)] |
4 | | |
5 | | #[cfg_attr(target_pointer_width = "32", path = "field/field32.rs")] |
6 | | #[cfg_attr(target_pointer_width = "64", path = "field/field64.rs")] |
7 | | mod field_impl; |
8 | | |
9 | | use self::field_impl::*; |
10 | | use crate::{FieldBytes, NistP256}; |
11 | | use core::{ |
12 | | fmt::{self, Debug}, |
13 | | iter::{Product, Sum}, |
14 | | ops::{AddAssign, Mul, MulAssign, Neg, SubAssign}, |
15 | | }; |
16 | | use elliptic_curve::{ |
17 | | bigint::U256, |
18 | | ff::PrimeField, |
19 | | subtle::{Choice, ConstantTimeEq, CtOption}, |
20 | | }; |
21 | | |
22 | | /// Field modulus serialized as hex. |
23 | | /// p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1 |
24 | | const MODULUS_HEX: &str = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"; |
25 | | |
26 | | /// Constant representing the modulus. |
27 | | pub const MODULUS: U256 = U256::from_be_hex(MODULUS_HEX); |
28 | | |
29 | | /// R^2 = 2^512 mod p |
30 | | const R_2: U256 = |
31 | | U256::from_be_hex("00000004fffffffdfffffffffffffffefffffffbffffffff0000000000000003"); |
32 | | |
33 | | /// An element in the finite field modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1. |
34 | | /// |
35 | | /// The internal representation is in little-endian order. Elements are always in |
36 | | /// Montgomery form; i.e., FieldElement(a) = aR mod p, with R = 2^256. |
37 | | #[derive(Clone, Copy)] |
38 | | pub struct FieldElement(pub(crate) U256); |
39 | | |
40 | | primeorder::impl_mont_field_element!( |
41 | | NistP256, |
42 | | FieldElement, |
43 | | FieldBytes, |
44 | | U256, |
45 | | MODULUS, |
46 | | Fe, |
47 | | fe_from_montgomery, |
48 | | fe_to_montgomery, |
49 | | fe_add, |
50 | | fe_sub, |
51 | | fe_mul, |
52 | | fe_neg, |
53 | | fe_square |
54 | | ); |
55 | | |
56 | | impl FieldElement { |
57 | | /// Returns the multiplicative inverse of self, if self is non-zero. |
58 | 8.64k | pub fn invert(&self) -> CtOption<Self> { |
59 | 8.64k | CtOption::new(self.invert_unchecked(), !self.is_zero()) |
60 | 8.64k | } |
61 | | |
62 | | /// Returns the multiplicative inverse of self. |
63 | | /// |
64 | | /// Does not check that self is non-zero. |
65 | 8.64k | const fn invert_unchecked(&self) -> Self { |
66 | | // We need to find b such that b * a ≡ 1 mod p. As we are in a prime |
67 | | // field, we can apply Fermat's Little Theorem: |
68 | | // |
69 | | // a^p ≡ a mod p |
70 | | // a^(p-1) ≡ 1 mod p |
71 | | // a^(p-2) * a ≡ 1 mod p |
72 | | // |
73 | | // Thus inversion can be implemented with a single exponentiation. |
74 | | |
75 | 8.64k | let t111 = self.multiply(&self.multiply(&self.square()).square()); |
76 | 8.64k | let t111111 = t111.multiply(&t111.sqn(3)); |
77 | 8.64k | let x15 = t111111.sqn(6).multiply(&t111111).sqn(3).multiply(&t111); |
78 | 8.64k | let x16 = x15.square().multiply(self); |
79 | 8.64k | let i53 = x16.sqn(16).multiply(&x16).sqn(15); |
80 | 8.64k | let x47 = x15.multiply(&i53); |
81 | 8.64k | x47.multiply(&i53.sqn(17).multiply(self).sqn(143).multiply(&x47).sqn(47)) |
82 | 8.64k | .sqn(2) |
83 | 8.64k | .multiply(self) |
84 | 8.64k | } |
85 | | |
86 | | /// Returns the square root of self mod p, or `None` if no square root exists. |
87 | 0 | pub fn sqrt(&self) -> CtOption<Self> { |
88 | | // We need to find alpha such that alpha^2 = beta mod p. For secp256r1, |
89 | | // p ≡ 3 mod 4. By Euler's Criterion, beta^(p-1)/2 ≡ 1 mod p. So: |
90 | | // |
91 | | // alpha^2 = beta beta^((p - 1) / 2) mod p ≡ beta^((p + 1) / 2) mod p |
92 | | // alpha = ± beta^((p + 1) / 4) mod p |
93 | | // |
94 | | // Thus sqrt can be implemented with a single exponentiation. |
95 | | |
96 | 0 | let t11 = self.mul(&self.square()); |
97 | 0 | let t1111 = t11.mul(&t11.sqn(2)); |
98 | 0 | let t11111111 = t1111.mul(&t1111.sqn(4)); |
99 | 0 | let x16 = t11111111.sqn(8).mul(&t11111111); |
100 | 0 | let sqrt = x16 |
101 | 0 | .sqn(16) |
102 | 0 | .mul(&x16) |
103 | 0 | .sqn(32) |
104 | 0 | .mul(self) |
105 | 0 | .sqn(96) |
106 | 0 | .mul(self) |
107 | 0 | .sqn(94); |
108 | | |
109 | 0 | CtOption::new( |
110 | 0 | sqrt, |
111 | 0 | (&sqrt * &sqrt).ct_eq(self), // Only return Some if it's the square root. |
112 | | ) |
113 | 0 | } |
114 | | |
115 | | /// Returns self^(2^n) mod p |
116 | 77.7k | const fn sqn(&self, n: usize) -> Self { |
117 | 77.7k | let mut x = *self; |
118 | 77.7k | let mut i = 0; |
119 | 2.25M | while i < n { |
120 | 2.17M | x = x.square(); |
121 | 2.17M | i += 1; |
122 | 2.17M | } |
123 | 77.7k | x |
124 | 77.7k | } |
125 | | } |
126 | | |
127 | | impl PrimeField for FieldElement { |
128 | | type Repr = FieldBytes; |
129 | | |
130 | | const MODULUS: &'static str = MODULUS_HEX; |
131 | | const NUM_BITS: u32 = 256; |
132 | | const CAPACITY: u32 = 255; |
133 | | const TWO_INV: Self = Self::from_u64(2).invert_unchecked(); |
134 | | const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(6); |
135 | | const S: u32 = 1; |
136 | | const ROOT_OF_UNITY: Self = |
137 | | Self::from_hex("ffffffff00000001000000000000000000000000fffffffffffffffffffffffe"); |
138 | | const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked(); |
139 | | const DELTA: Self = Self::from_u64(36); |
140 | | |
141 | | #[inline] |
142 | 144 | fn from_repr(bytes: FieldBytes) -> CtOption<Self> { |
143 | 144 | Self::from_bytes(&bytes) |
144 | 144 | } <p256::arithmetic::field::FieldElement as ff::PrimeField>::from_repr Line | Count | Source | 142 | 144 | fn from_repr(bytes: FieldBytes) -> CtOption<Self> { | 143 | 144 | Self::from_bytes(&bytes) | 144 | 144 | } |
Unexecuted instantiation: <p256::arithmetic::field::FieldElement as ff::PrimeField>::from_repr |
145 | | |
146 | | #[inline] |
147 | 16.6k | fn to_repr(&self) -> FieldBytes { |
148 | 16.6k | self.to_bytes() |
149 | 16.6k | } <p256::arithmetic::field::FieldElement as ff::PrimeField>::to_repr Line | Count | Source | 147 | 16.6k | fn to_repr(&self) -> FieldBytes { | 148 | 16.6k | self.to_bytes() | 149 | 16.6k | } |
Unexecuted instantiation: <p256::arithmetic::field::FieldElement as ff::PrimeField>::to_repr |
150 | | |
151 | | #[inline] |
152 | 3.26k | fn is_odd(&self) -> Choice { |
153 | 3.26k | self.is_odd() |
154 | 3.26k | } <p256::arithmetic::field::FieldElement as ff::PrimeField>::is_odd Line | Count | Source | 152 | 3.26k | fn is_odd(&self) -> Choice { | 153 | 3.26k | self.is_odd() | 154 | 3.26k | } |
Unexecuted instantiation: <p256::arithmetic::field::FieldElement as ff::PrimeField>::is_odd |
155 | | } |
156 | | |
157 | | impl Debug for FieldElement { |
158 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
159 | 0 | write!(f, "FieldElement(0x{:X})", &self.0) |
160 | 0 | } |
161 | | } |
162 | | |
163 | | #[cfg(test)] |
164 | | mod tests { |
165 | | use super::FieldElement; |
166 | | use crate::{test_vectors::field::DBL_TEST_VECTORS, FieldBytes}; |
167 | | use elliptic_curve::{bigint::U256, ff::PrimeField}; |
168 | | use primeorder::{ |
169 | | impl_field_identity_tests, impl_field_invert_tests, impl_field_sqrt_tests, |
170 | | impl_primefield_tests, |
171 | | }; |
172 | | use proptest::{num, prelude::*}; |
173 | | |
174 | | /// t = (modulus - 1) >> S |
175 | | const T: [u64; 4] = [ |
176 | | 0xffffffffffffffff, |
177 | | 0x000000007fffffff, |
178 | | 0x8000000000000000, |
179 | | 0x7fffffff80000000, |
180 | | ]; |
181 | | |
182 | | impl_field_identity_tests!(FieldElement); |
183 | | impl_field_invert_tests!(FieldElement); |
184 | | impl_field_sqrt_tests!(FieldElement); |
185 | | impl_primefield_tests!(FieldElement, T); |
186 | | |
187 | | #[test] |
188 | | fn from_bytes() { |
189 | | assert_eq!( |
190 | | FieldElement::from_bytes(&FieldBytes::default()).unwrap(), |
191 | | FieldElement::ZERO |
192 | | ); |
193 | | assert_eq!( |
194 | | FieldElement::from_bytes( |
195 | | &[ |
196 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
197 | | 0, 0, 0, 0, 0, 1 |
198 | | ] |
199 | | .into() |
200 | | ) |
201 | | .unwrap(), |
202 | | FieldElement::ONE |
203 | | ); |
204 | | assert!(bool::from( |
205 | | FieldElement::from_bytes(&[0xff; 32].into()).is_none() |
206 | | )); |
207 | | } |
208 | | |
209 | | #[test] |
210 | | fn to_bytes() { |
211 | | assert_eq!(FieldElement::ZERO.to_bytes(), FieldBytes::default()); |
212 | | assert_eq!( |
213 | | FieldElement::ONE.to_bytes(), |
214 | | [ |
215 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
216 | | 0, 0, 0, 1 |
217 | | ] |
218 | | .into() |
219 | | ); |
220 | | } |
221 | | |
222 | | #[test] |
223 | | fn repeated_add() { |
224 | | let mut r = FieldElement::ONE; |
225 | | for i in 0..DBL_TEST_VECTORS.len() { |
226 | | assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); |
227 | | r = r + &r; |
228 | | } |
229 | | } |
230 | | |
231 | | #[test] |
232 | | fn repeated_double() { |
233 | | let mut r = FieldElement::ONE; |
234 | | for i in 0..DBL_TEST_VECTORS.len() { |
235 | | assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); |
236 | | r = r.double(); |
237 | | } |
238 | | } |
239 | | |
240 | | #[test] |
241 | | fn repeated_mul() { |
242 | | let mut r = FieldElement::ONE; |
243 | | let two = r + &r; |
244 | | for i in 0..DBL_TEST_VECTORS.len() { |
245 | | assert_eq!(r.to_bytes(), DBL_TEST_VECTORS[i].into()); |
246 | | r = r * &two; |
247 | | } |
248 | | } |
249 | | |
250 | | #[test] |
251 | | fn negation() { |
252 | | let two = FieldElement::ONE.double(); |
253 | | let neg_two = -two; |
254 | | assert_eq!(two + &neg_two, FieldElement::ZERO); |
255 | | assert_eq!(-neg_two, two); |
256 | | } |
257 | | |
258 | | #[test] |
259 | | fn pow_vartime() { |
260 | | let one = FieldElement::ONE; |
261 | | let two = one + &one; |
262 | | let four = two.square(); |
263 | | assert_eq!(two.pow_vartime(&[2, 0, 0, 0]), four); |
264 | | } |
265 | | |
266 | | proptest! { |
267 | | /// This checks behaviour well within the field ranges, because it doesn't set the |
268 | | /// highest limb. |
269 | | #[cfg(target_pointer_width = "32")] |
270 | | #[test] |
271 | | fn add_then_sub( |
272 | | a0 in num::u32::ANY, |
273 | | a1 in num::u32::ANY, |
274 | | a2 in num::u32::ANY, |
275 | | a3 in num::u32::ANY, |
276 | | a4 in num::u32::ANY, |
277 | | a5 in num::u32::ANY, |
278 | | a6 in num::u32::ANY, |
279 | | b0 in num::u32::ANY, |
280 | | b1 in num::u32::ANY, |
281 | | b2 in num::u32::ANY, |
282 | | b3 in num::u32::ANY, |
283 | | b4 in num::u32::ANY, |
284 | | b5 in num::u32::ANY, |
285 | | b6 in num::u32::ANY, |
286 | | ) { |
287 | | let a = FieldElement(U256::from_words([a0, a1, a2, a3, a4, a5, a6, 0])); |
288 | | let b = FieldElement(U256::from_words([b0, b1, b2, b3, b4, b5, b6, 0])); |
289 | | assert_eq!(a.add(&b).sub(&a), b); |
290 | | } |
291 | | |
292 | | /// This checks behaviour well within the field ranges, because it doesn't set the |
293 | | /// highest limb. |
294 | | #[cfg(target_pointer_width = "64")] |
295 | | #[test] |
296 | | fn add_then_sub( |
297 | | a0 in num::u64::ANY, |
298 | | a1 in num::u64::ANY, |
299 | | a2 in num::u64::ANY, |
300 | | b0 in num::u64::ANY, |
301 | | b1 in num::u64::ANY, |
302 | | b2 in num::u64::ANY, |
303 | | ) { |
304 | | let a = FieldElement(U256::from_words([a0, a1, a2, 0])); |
305 | | let b = FieldElement(U256::from_words([b0, b1, b2, 0])); |
306 | | assert_eq!(a.add(&b).sub(&a), b); |
307 | | } |
308 | | } |
309 | | } |