Skip to content

Commit f0f7477

Browse files
authored
k256+p256: move Scalar impl blocks to top of module (#516)
Reorders the impl blocks containing inherent constants/methods to the top of the module, following suit with how the `affine` and `projective` modules have been reorganized.
1 parent 39b9001 commit f0f7477

File tree

2 files changed

+278
-278
lines changed

2 files changed

+278
-278
lines changed

k256/src/arithmetic/scalar.rs

Lines changed: 136 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -77,141 +77,6 @@ const FRAC_MODULUS_2: U256 = ORDER.shr_vartime(1);
7777
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
7878
pub struct Scalar(U256);
7979

80-
impl Field for Scalar {
81-
fn random(rng: impl RngCore) -> Self {
82-
// Uses rejection sampling as the default random generation method,
83-
// which produces a uniformly random distribution of scalars.
84-
//
85-
// This method is not constant time, but should be secure so long as
86-
// rejected RNG outputs are unrelated to future ones (which is a
87-
// necessary property of a `CryptoRng`).
88-
//
89-
// With an unbiased RNG, the probability of failing to complete after 4
90-
// iterations is vanishingly small.
91-
Self::generate_vartime(rng)
92-
}
93-
94-
fn zero() -> Self {
95-
Self::ZERO
96-
}
97-
98-
fn one() -> Self {
99-
Self::ONE
100-
}
101-
102-
#[must_use]
103-
fn square(&self) -> Self {
104-
Scalar::square(self)
105-
}
106-
107-
#[must_use]
108-
fn double(&self) -> Self {
109-
self.add(self)
110-
}
111-
112-
fn invert(&self) -> CtOption<Self> {
113-
Scalar::invert(self)
114-
}
115-
116-
/// Tonelli-Shank's algorithm for q mod 16 = 1
117-
/// <https://eprint.iacr.org/2012/685.pdf> (page 12, algorithm 5)
118-
#[allow(clippy::many_single_char_names)]
119-
fn sqrt(&self) -> CtOption<Self> {
120-
// Note: `pow_vartime` is constant-time with respect to `self`
121-
let w = self.pow_vartime(&[
122-
0x777fa4bd19a06c82,
123-
0xfd755db9cd5e9140,
124-
0xffffffffffffffff,
125-
0x1ffffffffffffff,
126-
]);
127-
128-
let mut v = Self::S;
129-
let mut x = *self * w;
130-
let mut b = x * w;
131-
let mut z = Self::root_of_unity();
132-
133-
for max_v in (1..=Self::S).rev() {
134-
let mut k = 1;
135-
let mut tmp = b.square();
136-
let mut j_less_than_v = Choice::from(1);
137-
138-
for j in 2..max_v {
139-
let tmp_is_one = tmp.ct_eq(&Self::one());
140-
let squared = Self::conditional_select(&tmp, &z, tmp_is_one).square();
141-
tmp = Self::conditional_select(&squared, &tmp, tmp_is_one);
142-
let new_z = Self::conditional_select(&z, &squared, tmp_is_one);
143-
j_less_than_v &= !j.ct_eq(&v);
144-
k = u32::conditional_select(&j, &k, tmp_is_one);
145-
z = Self::conditional_select(&z, &new_z, j_less_than_v);
146-
}
147-
148-
let result = x * z;
149-
x = Self::conditional_select(&result, &x, b.ct_eq(&Self::one()));
150-
z = z.square();
151-
b *= z;
152-
v = k;
153-
}
154-
155-
CtOption::new(x, x.square().ct_eq(self))
156-
}
157-
}
158-
159-
impl PrimeField for Scalar {
160-
type Repr = FieldBytes;
161-
162-
const NUM_BITS: u32 = 256;
163-
const CAPACITY: u32 = 255;
164-
const S: u32 = 6;
165-
166-
/// Attempts to parse the given byte array as an SEC1-encoded scalar.
167-
///
168-
/// Returns None if the byte array does not contain a big-endian integer in the range
169-
/// [0, p).
170-
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
171-
let inner = U256::from_be_byte_array(bytes);
172-
CtOption::new(Self(inner), inner.ct_lt(&Secp256k1::ORDER))
173-
}
174-
175-
fn to_repr(&self) -> FieldBytes {
176-
self.to_bytes()
177-
}
178-
179-
fn is_odd(&self) -> Choice {
180-
self.0.is_odd()
181-
}
182-
183-
fn multiplicative_generator() -> Self {
184-
7u64.into()
185-
}
186-
187-
fn root_of_unity() -> Self {
188-
Scalar::from_repr(arr![u8;
189-
0x0c, 0x1d, 0xc0, 0x60, 0xe7, 0xa9, 0x19, 0x86, 0xdf, 0x98, 0x79, 0xa3, 0xfb, 0xc4,
190-
0x83, 0xa8, 0x98, 0xbd, 0xea, 0xb6, 0x80, 0x75, 0x60, 0x45, 0x99, 0x2f, 0x4b, 0x54,
191-
0x02, 0xb0, 0x52, 0xf2
192-
])
193-
.unwrap()
194-
}
195-
}
196-
197-
#[cfg(feature = "bits")]
198-
#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
199-
impl PrimeFieldBits for Scalar {
200-
#[cfg(target_pointer_width = "32")]
201-
type ReprBits = [u32; 8];
202-
203-
#[cfg(target_pointer_width = "64")]
204-
type ReprBits = [u64; 4];
205-
206-
fn to_le_bits(&self) -> ScalarBits {
207-
self.into()
208-
}
209-
210-
fn char_le_bits() -> ScalarBits {
211-
ORDER.to_uint_array().into()
212-
}
213-
}
214-
21580
impl Scalar {
21681
/// Zero scalar.
21782
pub const ZERO: Self = Self(U256::ZERO);
@@ -281,7 +146,7 @@ impl Scalar {
281146
let x56 = x28.pow2k(28).mul(&x28);
282147

283148
#[rustfmt::skip]
284-
let res = x56
149+
let res = x56
285150
.pow2k(56).mul(&x56)
286151
.pow2k(14).mul(&x14)
287152
.pow2k(3).mul(&x_101)
@@ -357,6 +222,141 @@ impl Scalar {
357222
}
358223
}
359224

225+
impl Field for Scalar {
226+
fn random(rng: impl RngCore) -> Self {
227+
// Uses rejection sampling as the default random generation method,
228+
// which produces a uniformly random distribution of scalars.
229+
//
230+
// This method is not constant time, but should be secure so long as
231+
// rejected RNG outputs are unrelated to future ones (which is a
232+
// necessary property of a `CryptoRng`).
233+
//
234+
// With an unbiased RNG, the probability of failing to complete after 4
235+
// iterations is vanishingly small.
236+
Self::generate_vartime(rng)
237+
}
238+
239+
fn zero() -> Self {
240+
Self::ZERO
241+
}
242+
243+
fn one() -> Self {
244+
Self::ONE
245+
}
246+
247+
#[must_use]
248+
fn square(&self) -> Self {
249+
Scalar::square(self)
250+
}
251+
252+
#[must_use]
253+
fn double(&self) -> Self {
254+
self.add(self)
255+
}
256+
257+
fn invert(&self) -> CtOption<Self> {
258+
Scalar::invert(self)
259+
}
260+
261+
/// Tonelli-Shank's algorithm for q mod 16 = 1
262+
/// <https://eprint.iacr.org/2012/685.pdf> (page 12, algorithm 5)
263+
#[allow(clippy::many_single_char_names)]
264+
fn sqrt(&self) -> CtOption<Self> {
265+
// Note: `pow_vartime` is constant-time with respect to `self`
266+
let w = self.pow_vartime(&[
267+
0x777fa4bd19a06c82,
268+
0xfd755db9cd5e9140,
269+
0xffffffffffffffff,
270+
0x1ffffffffffffff,
271+
]);
272+
273+
let mut v = Self::S;
274+
let mut x = *self * w;
275+
let mut b = x * w;
276+
let mut z = Self::root_of_unity();
277+
278+
for max_v in (1..=Self::S).rev() {
279+
let mut k = 1;
280+
let mut tmp = b.square();
281+
let mut j_less_than_v = Choice::from(1);
282+
283+
for j in 2..max_v {
284+
let tmp_is_one = tmp.ct_eq(&Self::one());
285+
let squared = Self::conditional_select(&tmp, &z, tmp_is_one).square();
286+
tmp = Self::conditional_select(&squared, &tmp, tmp_is_one);
287+
let new_z = Self::conditional_select(&z, &squared, tmp_is_one);
288+
j_less_than_v &= !j.ct_eq(&v);
289+
k = u32::conditional_select(&j, &k, tmp_is_one);
290+
z = Self::conditional_select(&z, &new_z, j_less_than_v);
291+
}
292+
293+
let result = x * z;
294+
x = Self::conditional_select(&result, &x, b.ct_eq(&Self::one()));
295+
z = z.square();
296+
b *= z;
297+
v = k;
298+
}
299+
300+
CtOption::new(x, x.square().ct_eq(self))
301+
}
302+
}
303+
304+
impl PrimeField for Scalar {
305+
type Repr = FieldBytes;
306+
307+
const NUM_BITS: u32 = 256;
308+
const CAPACITY: u32 = 255;
309+
const S: u32 = 6;
310+
311+
/// Attempts to parse the given byte array as an SEC1-encoded scalar.
312+
///
313+
/// Returns None if the byte array does not contain a big-endian integer in the range
314+
/// [0, p).
315+
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
316+
let inner = U256::from_be_byte_array(bytes);
317+
CtOption::new(Self(inner), inner.ct_lt(&Secp256k1::ORDER))
318+
}
319+
320+
fn to_repr(&self) -> FieldBytes {
321+
self.to_bytes()
322+
}
323+
324+
fn is_odd(&self) -> Choice {
325+
self.0.is_odd()
326+
}
327+
328+
fn multiplicative_generator() -> Self {
329+
7u64.into()
330+
}
331+
332+
fn root_of_unity() -> Self {
333+
Scalar::from_repr(arr![u8;
334+
0x0c, 0x1d, 0xc0, 0x60, 0xe7, 0xa9, 0x19, 0x86, 0xdf, 0x98, 0x79, 0xa3, 0xfb, 0xc4,
335+
0x83, 0xa8, 0x98, 0xbd, 0xea, 0xb6, 0x80, 0x75, 0x60, 0x45, 0x99, 0x2f, 0x4b, 0x54,
336+
0x02, 0xb0, 0x52, 0xf2
337+
])
338+
.unwrap()
339+
}
340+
}
341+
342+
#[cfg(feature = "bits")]
343+
#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
344+
impl PrimeFieldBits for Scalar {
345+
#[cfg(target_pointer_width = "32")]
346+
type ReprBits = [u32; 8];
347+
348+
#[cfg(target_pointer_width = "64")]
349+
type ReprBits = [u64; 4];
350+
351+
fn to_le_bits(&self) -> ScalarBits {
352+
self.into()
353+
}
354+
355+
fn char_le_bits() -> ScalarBits {
356+
ORDER.to_uint_array().into()
357+
}
358+
}
359+
360360
impl DefaultIsZeroes for Scalar {}
361361

362362
impl From<u32> for Scalar {

0 commit comments

Comments
 (0)