Skip to content

Commit 20eeeff

Browse files
authored
primefield: generic MontyFieldElement type (#1311)
The previous implementation was written entirely in terms of macros. Leveraging types from `crypto-bigint`, this provides a generic field element type with an internal Montgomery form representation.
1 parent 37fbeea commit 20eeeff

File tree

6 files changed

+850
-25
lines changed

6 files changed

+850
-25
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ members = [
2121
opt-level = 2
2222

2323
[patch.crates-io]
24+
crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint" }
2425
elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" }
26+
2527
hash2curve = { path = "hash2curve" }
2628
primefield = { path = "primefield" }
2729
primeorder = { path = "primeorder" }

primefield/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ edition = "2024"
1414
rust-version = "1.85"
1515

1616
[dependencies]
17-
bigint = { package = "crypto-bigint", version = "=0.7.0-pre.7", default-features = false }
17+
bigint = { package = "crypto-bigint", version = "=0.7.0-pre.7", default-features = false, features = ["hybrid-array"] }
1818
ff = { version = "=0.14.0-pre.0", default-features = false }
1919
subtle = { version = "2.6", default-features = false }
2020
rand_core = { version = "0.9", default-features = false }

primefield/src/dev.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,11 @@ macro_rules! test_primefield_constants {
1616
use $crate::ff::PrimeField as _;
1717

1818
/// t = (modulus - 1) >> S
19-
const T: $uint = $uint::from_be_hex($fe::MODULUS)
20-
.wrapping_sub(&$uint::ONE)
21-
.wrapping_shr($fe::S);
22-
23-
/// Helper function to compute the args to `pow_vartime`.
2419
#[cfg(target_pointer_width = "32")]
25-
fn pow_args(n: &$uint) -> [u64; $uint::LIMBS.div_ceil(2)] {
26-
let words = n.as_words();
27-
core::array::from_fn(|i| {
28-
let hi = words.get((2 * i) + 1).copied().unwrap_or_default();
29-
let lo = words[2 * i];
30-
(hi as u64) << 32 | (lo as u64)
31-
})
32-
}
20+
const T: [u64; $uint::LIMBS.div_ceil(2)] =
21+
$crate::compute_t(&$uint::from_be_hex($fe::MODULUS));
3322
#[cfg(target_pointer_width = "64")]
34-
fn pow_args(n: &$uint) -> [u64; $uint::LIMBS] {
35-
*n.as_words()
36-
}
23+
const T: [u64; $uint::LIMBS] = $crate::compute_t(&$uint::from_be_hex($fe::MODULUS));
3724

3825
#[test]
3926
fn two_inv_constant() {
@@ -58,7 +45,7 @@ macro_rules! test_primefield_constants {
5845

5946
// MULTIPLICATIVE_GENERATOR^{t} mod m == ROOT_OF_UNITY
6047
assert_eq!(
61-
$fe::MULTIPLICATIVE_GENERATOR.pow_vartime(&pow_args(&T)),
48+
$fe::MULTIPLICATIVE_GENERATOR.pow_vartime(&T),
6249
$fe::ROOT_OF_UNITY
6350
)
6451
}
@@ -71,7 +58,7 @@ macro_rules! test_primefield_constants {
7158
#[test]
7259
fn delta_constant() {
7360
// DELTA^{t} mod m == 1
74-
assert_eq!($fe::DELTA.pow_vartime(&pow_args(&T)), $fe::ONE);
61+
assert_eq!($fe::DELTA.pow_vartime(&T), $fe::ONE);
7562
}
7663
};
7764
}

primefield/src/lib.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,28 @@
88
#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
99
#![doc = include_str!("../README.md")]
1010

11+
mod dev;
12+
mod fiat;
13+
mod monty;
14+
15+
pub use crate::monty::{MontyFieldElement, MontyFieldParams, compute_t};
16+
pub use array::typenum::consts;
1117
pub use bigint;
18+
pub use bigint::hybrid_array as array;
1219
pub use ff;
1320
pub use rand_core;
1421
pub use subtle;
1522
pub use zeroize;
1623

17-
mod dev;
18-
mod fiat;
24+
/// Byte order used when encoding/decoding field elements as bytestrings.
25+
#[derive(Debug)]
26+
pub enum ByteOrder {
27+
/// Big endian.
28+
BigEndian,
29+
30+
/// Little endian.
31+
LittleEndian,
32+
}
1933

2034
/// Implements a field element type whose internal representation is in
2135
/// Montgomery form, providing a combination of trait impls and inherent impls
@@ -221,12 +235,10 @@ macro_rules! field_element_type {
221235
Self::ZERO.ct_eq(self)
222236
}
223237

224-
#[must_use]
225238
fn square(&self) -> Self {
226239
self.square()
227240
}
228241

229-
#[must_use]
230242
fn double(&self) -> Self {
231243
self.double()
232244
}

0 commit comments

Comments
 (0)