Skip to content

Commit 13ce847

Browse files
authored
primefield: add PrimeFieldExt trait (#1809)
Adds a trait for specifying the endianness of the serialized representation of a field element as a stopgap until zkcrypto/rfcs#4 is accepted. This uses the `ByteOrder` enum and replaces the previous `FIELD_REPR_IS_BE` flag on `PrimeCurveParams`. It also means `Radix16Decomposition` now "Just Works" and doesn't need an endianness parameter passed to `new`. The `primefield::monty_field_element!` macro now writes impls for this trait, sourcing the endianness information from the `MontyFieldParams`.
1 parent 5dd4afe commit 13ce847

14 files changed

Lines changed: 83 additions & 44 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bignp256/src/arithmetic.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,4 @@ impl PrimeCurveParams for BignP256 {
4949
"936A510418CF291E52F608C4663991785D83D651A3C9E45C9FD616FB3CFCF76B",
5050
),
5151
);
52-
const FIELD_REPR_IS_BE: bool = false;
5352
}

bignp256/src/arithmetic/scalar.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use elliptic_curve::{
1010
scalar::{FromUintUnchecked, IsHigh},
1111
subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, CtOption},
1212
};
13+
use primefield::ByteOrder;
1314

14-
// TODO(tarcieri): remove this when we can use `const _` to silence warnings
1515
cpubits! {
1616
32 => {
1717
#[path = "scalar/bignp256_scalar_32.rs"]
@@ -23,7 +23,7 @@ cpubits! {
2323
clippy::identity_op,
2424
clippy::needless_lifetimes,
2525
clippy::too_many_arguments,
26-
clippy::unnecessary_cast
26+
clippy::unnecessary_cast,
2727
)]
2828
mod scalar_impl;
2929
}
@@ -52,7 +52,7 @@ primefield::monty_field_params! {
5252
name: ScalarParams,
5353
modulus: ORDER_HEX,
5454
uint: U256,
55-
byte_order: primefield::ByteOrder::LittleEndian,
55+
byte_order: ByteOrder::LittleEndian,
5656
multiplicative_generator: 3,
5757
doc: "Montgomery parameters for the bign-curve256v1 scalar modulus"
5858
}

k256/src/arithmetic/mul.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ fn lincomb(
248248
);
249249

250250
digits[i] = (
251-
Radix16Decomposition::<U33>::new(&r1_c, true),
252-
Radix16Decomposition::<U33>::new(&r2_c, true),
251+
Radix16Decomposition::<U33>::new(&r1_c),
252+
Radix16Decomposition::<U33>::new(&r2_c),
253253
)
254254
});
255255

@@ -355,7 +355,7 @@ impl ProjectivePoint {
355355
/// Calculates `k * G`, where `G` is the generator.
356356
#[cfg(feature = "precomputed-tables")]
357357
pub(super) fn mul_by_generator(k: &Scalar) -> ProjectivePoint {
358-
let digits = Radix16Decomposition::<U65>::new(k, true);
358+
let digits = Radix16Decomposition::<U65>::new(k);
359359
let table = *BASEPOINT_TABLE;
360360
let mut acc = table[32].select(digits[64]);
361361
let mut acc2 = ProjectivePoint::IDENTITY;

k256/src/arithmetic/scalar.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use elliptic_curve::{
1919
},
2020
zeroize::DefaultIsZeroes,
2121
};
22+
use primeorder::PrimeFieldExt;
2223

2324
cpubits! {
2425
32 => {
@@ -77,12 +78,6 @@ const FRAC_MODULUS_2: U256 = ORDER.as_ref().shr_vartime(1);
7778
#[derive(Clone, Copy, Debug, Default, PartialOrd, Ord)]
7879
pub struct Scalar(pub(crate) U256);
7980

80-
impl AsRef<Scalar> for Scalar {
81-
fn as_ref(&self) -> &Scalar {
82-
self
83-
}
84-
}
85-
8681
impl Scalar {
8782
/// Zero scalar.
8883
pub const ZERO: Self = Self(U256::ZERO);
@@ -176,6 +171,14 @@ impl Scalar {
176171
}
177172
}
178173

174+
impl AsRef<Scalar> for Scalar {
175+
fn as_ref(&self) -> &Scalar {
176+
self
177+
}
178+
}
179+
180+
impl DefaultIsZeroes for Scalar {}
181+
179182
impl Field for Scalar {
180183
const ZERO: Self = Self::ZERO;
181184
const ONE: Self = Self::ONE;
@@ -308,7 +311,7 @@ impl PrimeField for Scalar {
308311
}
309312
}
310313

311-
impl DefaultIsZeroes for Scalar {}
314+
impl PrimeFieldExt for Scalar {}
312315

313316
impl From<u32> for Scalar {
314317
fn from(k: u32) -> Self {

p256/src/arithmetic/scalar.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use elliptic_curve::{
2121
},
2222
zeroize::DefaultIsZeroes,
2323
};
24+
use primefield::PrimeFieldExt;
2425

2526
cpubits! {
2627
32 => {
@@ -307,6 +308,8 @@ impl PrimeField for Scalar {
307308
}
308309
}
309310

311+
impl PrimeFieldExt for Scalar {}
312+
310313
impl Retrieve for Scalar {
311314
type Output = U256;
312315

primefield/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ mod dev;
1212
mod error;
1313
mod macros;
1414
mod monty;
15+
mod traits;
1516

1617
pub use crate::{
1718
error::{Error, Result},
1819
monty::{MontyFieldBytes, MontyFieldElement, MontyFieldParams, compute_t},
20+
traits::PrimeFieldExt,
1921
};
2022
pub use array::typenum::consts;
2123
pub use bigint;

primefield/src/macros.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ macro_rules! monty_field_element {
314314
}
315315
}
316316

317-
impl PrimeField for $fe {
317+
impl $crate::ff::PrimeField for $fe {
318318
type Repr = $crate::MontyFieldBytes<$params, { <$params>::LIMBS }>;
319319

320320
const MODULUS: &'static str =
@@ -352,6 +352,11 @@ macro_rules! monty_field_element {
352352
}
353353
}
354354

355+
impl $crate::PrimeFieldExt for $fe {
356+
const REPR_ENDIANNESS: $crate::ByteOrder =
357+
<$params as $crate::MontyFieldParams<{ <$params>::LIMBS }>>::BYTE_ORDER;
358+
}
359+
355360
$crate::field_op!($fe, Add, add, add);
356361
$crate::field_op!($fe, Sub, sub, sub);
357362
$crate::field_op!($fe, Mul, mul, multiply);
@@ -794,8 +799,6 @@ macro_rules! monty_field_element_doc {
794799
"- [`PrimeField`] represents elements of prime fields and provides:\n",
795800
" - `from_repr`/`to_repr` for converting field elements from/to big integers.\n",
796801
" - `MULTIPLICATIVE_GENERATOR` and `ROOT_OF_UNITY` constants.\n",
797-
"- [`PrimeFieldBits`] operations over field elements represented as bits ",
798-
" (requires `bits` feature)\n",
799802
"\n",
800803
"Please see the documentation for the relevant traits for more information.\n"
801804
)

primefield/src/traits.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use crate::ByteOrder;
2+
3+
/// Extension trait for [`ff::PrimeField`] which enables specifying the endianness in which
4+
/// [`ff::PrimeField::Repr`] is encoded.
5+
// TODO(tarcieri): remove this if/whenever zkcrypto/rfcs#4 lands. See also: zkcrypto/ff#158
6+
pub trait PrimeFieldExt: ff::PrimeField {
7+
/// Endianness used when encoding [`ff::PrimeField::Repr`].
8+
const REPR_ENDIANNESS: ByteOrder = ByteOrder::BigEndian;
9+
10+
/// Encode `self` using a big endian representation.
11+
fn to_be_repr(&self) -> Self::Repr {
12+
let mut repr = self.to_repr();
13+
14+
if Self::REPR_ENDIANNESS == ByteOrder::LittleEndian {
15+
repr.as_mut().reverse();
16+
}
17+
18+
repr
19+
}
20+
21+
/// Encode `self` using a little endian representation.
22+
fn to_le_repr(&self) -> Self::Repr {
23+
let mut repr = self.to_repr();
24+
25+
if Self::REPR_ENDIANNESS == ByteOrder::BigEndian {
26+
repr.as_mut().reverse();
27+
}
28+
29+
repr
30+
}
31+
}

primeorder/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ rust-version = "1.85"
1919

2020
[dependencies]
2121
elliptic-curve = { version = "0.14.0-rc.34", default-features = false, features = ["arithmetic", "sec1"] }
22+
primefield = "0.14.0-rc.11"
2223

2324
# optional dependencies
2425
once_cell = { version = "1.21", optional = true, default-features = false }

0 commit comments

Comments
 (0)