Skip to content

Commit 0e533d9

Browse files
committed
[WIP] primefield: generic MontyFieldElement type
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 bcc2f0b commit 0e533d9

File tree

5 files changed

+488
-1
lines changed

5 files changed

+488
-1
lines changed

p256/src/arithmetic/field.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::ops::Mul;
1111
use elliptic_curve::{
1212
FieldBytesEncoding,
1313
bigint::U256,
14+
consts::U32,
1415
ff::PrimeField,
1516
subtle::{Choice, ConstantTimeEq, CtOption},
1617
};
@@ -26,6 +27,19 @@ const R2: FieldElement = FieldElement(U256::from_be_hex(
2627
"00000004fffffffdfffffffffffffffefffffffbffffffff0000000000000003",
2728
));
2829

30+
primefield::monty_field_params!(
31+
MontyFieldParams,
32+
MODULUS_HEX,
33+
U256,
34+
U32,
35+
primefield::ByteOrder::BigEndian,
36+
"P-256 field modulus"
37+
);
38+
39+
/// An element in the finite field modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1.
40+
#[allow(dead_code)]
41+
pub type MontyFieldElement = primefield::MontyFieldElement<MontyFieldParams, { U256::LIMBS }>;
42+
2943
/// An element in the finite field modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1.
3044
///
3145
/// The internal representation is in little-endian order. Elements are always in

p256/src/arithmetic/scalar.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use core::{
1414
use elliptic_curve::{
1515
Curve,
1616
bigint::{Limb, U256, prelude::*},
17+
consts::U32,
1718
group::ff::{self, Field, PrimeField},
1819
ops::{Invert, Reduce, ReduceNonZero},
1920
rand_core::TryRngCore,
@@ -41,6 +42,19 @@ pub(crate) const MODULUS: U256 = NistP256::ORDER;
4142
/// `MODULUS / 2`
4243
const FRAC_MODULUS_2: Scalar = Scalar(MODULUS.shr_vartime(1));
4344

45+
primefield::monty_field_params!(
46+
MontyScalarParams,
47+
ORDER_HEX,
48+
U256,
49+
U32,
50+
primefield::ByteOrder::BigEndian,
51+
"P-256 scalar modulus"
52+
);
53+
54+
/// Scalars are elements in the finite field modulo n.
55+
#[allow(dead_code)]
56+
pub type MontyScalar = primefield::MontyFieldElement<MontyScalarParams, { U256::LIMBS }>;
57+
4458
/// Scalars are elements in the finite field modulo n.
4559
///
4660
/// # Trait impls

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/lib.rs

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

11+
pub use array::typenum::consts;
1112
pub use bigint;
13+
pub use bigint::hybrid_array as array;
1214
pub use ff;
1315
pub use rand_core;
1416
pub use subtle;
1517
pub use zeroize;
1618

19+
pub use crate::monty::{MontyFieldElement, MontyFieldParams};
20+
1721
mod fiat;
22+
mod monty;
23+
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+
}
1833

1934
/// Implements a field element type whose internal representation is in
2035
/// Montgomery form, providing a combination of trait impls and inherent impls

0 commit comments

Comments
 (0)