Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion bignp256/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,4 @@ impl PrimeCurveParams for BignP256 {
"936A510418CF291E52F608C4663991785D83D651A3C9E45C9FD616FB3CFCF76B",
),
);
const FIELD_REPR_IS_BE: bool = false;
}
6 changes: 3 additions & 3 deletions bignp256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use elliptic_curve::{
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConstantTimeEq, ConstantTimeGreater, CtOption},
};
use primefield::ByteOrder;

// TODO(tarcieri): remove this when we can use `const _` to silence warnings
cpubits! {
32 => {
#[path = "scalar/bignp256_scalar_32.rs"]
Expand All @@ -23,7 +23,7 @@ cpubits! {
clippy::identity_op,
clippy::needless_lifetimes,
clippy::too_many_arguments,
clippy::unnecessary_cast
clippy::unnecessary_cast,
)]
mod scalar_impl;
}
Expand Down Expand Up @@ -52,7 +52,7 @@ primefield::monty_field_params! {
name: ScalarParams,
modulus: ORDER_HEX,
uint: U256,
byte_order: primefield::ByteOrder::LittleEndian,
byte_order: ByteOrder::LittleEndian,
multiplicative_generator: 3,
doc: "Montgomery parameters for the bign-curve256v1 scalar modulus"
}
Expand Down
6 changes: 3 additions & 3 deletions k256/src/arithmetic/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ fn lincomb(
);

digits[i] = (
Radix16Decomposition::<U33>::new(&r1_c, true),
Radix16Decomposition::<U33>::new(&r2_c, true),
Radix16Decomposition::<U33>::new(&r1_c),
Radix16Decomposition::<U33>::new(&r2_c),
)
});

Expand Down Expand Up @@ -355,7 +355,7 @@ impl ProjectivePoint {
/// Calculates `k * G`, where `G` is the generator.
#[cfg(feature = "precomputed-tables")]
pub(super) fn mul_by_generator(k: &Scalar) -> ProjectivePoint {
let digits = Radix16Decomposition::<U65>::new(k, true);
let digits = Radix16Decomposition::<U65>::new(k);
let table = *BASEPOINT_TABLE;
let mut acc = table[32].select(digits[64]);
let mut acc2 = ProjectivePoint::IDENTITY;
Expand Down
17 changes: 10 additions & 7 deletions k256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use elliptic_curve::{
},
zeroize::DefaultIsZeroes,
};
use primeorder::PrimeFieldExt;

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

impl AsRef<Scalar> for Scalar {
fn as_ref(&self) -> &Scalar {
self
}
}

impl Scalar {
/// Zero scalar.
pub const ZERO: Self = Self(U256::ZERO);
Expand Down Expand Up @@ -176,6 +171,14 @@ impl Scalar {
}
}

impl AsRef<Scalar> for Scalar {
fn as_ref(&self) -> &Scalar {
self
}
}

impl DefaultIsZeroes for Scalar {}

impl Field for Scalar {
const ZERO: Self = Self::ZERO;
const ONE: Self = Self::ONE;
Expand Down Expand Up @@ -308,7 +311,7 @@ impl PrimeField for Scalar {
}
}

impl DefaultIsZeroes for Scalar {}
impl PrimeFieldExt for Scalar {}

impl From<u32> for Scalar {
fn from(k: u32) -> Self {
Expand Down
3 changes: 3 additions & 0 deletions p256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use elliptic_curve::{
},
zeroize::DefaultIsZeroes,
};
use primefield::PrimeFieldExt;

cpubits! {
32 => {
Expand Down Expand Up @@ -307,6 +308,8 @@ impl PrimeField for Scalar {
}
}

impl PrimeFieldExt for Scalar {}

impl Retrieve for Scalar {
type Output = U256;

Expand Down
2 changes: 2 additions & 0 deletions primefield/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ mod dev;
mod error;
mod macros;
mod monty;
mod traits;

pub use crate::{
error::{Error, Result},
monty::{MontyFieldBytes, MontyFieldElement, MontyFieldParams, compute_t},
traits::PrimeFieldExt,
};
pub use array::typenum::consts;
pub use bigint;
Expand Down
9 changes: 6 additions & 3 deletions primefield/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ macro_rules! monty_field_element {
}
}

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

const MODULUS: &'static str =
Expand Down Expand Up @@ -352,6 +352,11 @@ macro_rules! monty_field_element {
}
}

impl $crate::PrimeFieldExt for $fe {
const REPR_ENDIANNESS: $crate::ByteOrder =
<$params as $crate::MontyFieldParams<{ <$params>::LIMBS }>>::BYTE_ORDER;
}

$crate::field_op!($fe, Add, add, add);
$crate::field_op!($fe, Sub, sub, sub);
$crate::field_op!($fe, Mul, mul, multiply);
Expand Down Expand Up @@ -794,8 +799,6 @@ macro_rules! monty_field_element_doc {
"- [`PrimeField`] represents elements of prime fields and provides:\n",
" - `from_repr`/`to_repr` for converting field elements from/to big integers.\n",
" - `MULTIPLICATIVE_GENERATOR` and `ROOT_OF_UNITY` constants.\n",
"- [`PrimeFieldBits`] operations over field elements represented as bits ",
" (requires `bits` feature)\n",
"\n",
"Please see the documentation for the relevant traits for more information.\n"
)
Expand Down
31 changes: 31 additions & 0 deletions primefield/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::ByteOrder;

/// Extension trait for [`ff::PrimeField`] which enables specifying the endianness in which
/// [`ff::PrimeField::Repr`] is encoded.
// TODO(tarcieri): remove this if/whenever zkcrypto/rfcs#4 lands. See also: zkcrypto/ff#158
pub trait PrimeFieldExt: ff::PrimeField {
/// Endianness used when encoding [`ff::PrimeField::Repr`].
const REPR_ENDIANNESS: ByteOrder = ByteOrder::BigEndian;

/// Encode `self` using a big endian representation.
fn to_be_repr(&self) -> Self::Repr {
let mut repr = self.to_repr();

if Self::REPR_ENDIANNESS == ByteOrder::LittleEndian {
repr.as_mut().reverse();
}

repr
}

/// Encode `self` using a little endian representation.
fn to_le_repr(&self) -> Self::Repr {
let mut repr = self.to_repr();

if Self::REPR_ENDIANNESS == ByteOrder::BigEndian {
repr.as_mut().reverse();
}

repr
}
}
1 change: 1 addition & 0 deletions primeorder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rust-version = "1.85"

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

# optional dependencies
once_cell = { version = "1.21", optional = true, default-features = false }
Expand Down
17 changes: 9 additions & 8 deletions primeorder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,26 @@ pub use crate::{
pub use elliptic_curve::{
self, Field, FieldBytes, PrimeCurve, PrimeField, Scalar,
array::{self, ArraySize, sizes::U1},
bigint::modular::Retrieve,
bigint::{ByteOrder, modular::Retrieve},
point::Double,
};
pub use primefield::PrimeFieldExt;

use elliptic_curve::{Curve, CurveArithmetic, Generate, ops::Invert, sec1, subtle::CtOption};

#[cfg(feature = "basepoint-table")]
pub use crate::tables::BasepointTable;

/// Parameters for elliptic curves of prime order which can be described by the short
/// Weierstrass equation.
/// Parameters for elliptic curves of prime order which can be described by the short Weierstrass
/// equation.
pub trait PrimeCurveParams:
Curve<FieldBytesSize: sec1::ModulusSize>
+ PrimeCurve
+ CurveArithmetic<AffinePoint = AffinePoint<Self>, ProjectivePoint = ProjectivePoint<Self>>
+ CurveArithmetic<
AffinePoint = AffinePoint<Self>,
ProjectivePoint = ProjectivePoint<Self>,
Scalar: PrimeFieldExt,
>
{
/// Base field element type.
type FieldElement: Generate
Expand All @@ -70,10 +75,6 @@ pub trait PrimeCurveParams:

/// Generator point's affine coordinates: (x, y).
const GENERATOR: (Self::FieldElement, Self::FieldElement);

/// Are field element serializations for this curve big endian?
// TODO(tarcieri): make this a property of the scalar type, e.g. zkcrypto/ff#158
const FIELD_REPR_IS_BE: bool = true;
}

/// Trait for specifying a constant-time basepoint table for a given curve.
Expand Down
18 changes: 8 additions & 10 deletions primeorder/src/projective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ where
Self: Double,
{
let table = LookupTable::new(*self);
let digits = Radix16Decomposition::new(k, C::FIELD_REPR_IS_BE);
let digits = Radix16Decomposition::new(k);
lincomb::<C>(&[table], &[digits])
}

Expand All @@ -118,7 +118,7 @@ where
Self: Double,
{
let table = LookupTable::new(*self);
let digits = Radix16Decomposition::new(k, C::FIELD_REPR_IS_BE);
let digits = Radix16Decomposition::new(k);
lincomb_vartime::<C>(&[table], &[digits])
}
}
Expand Down Expand Up @@ -448,7 +448,7 @@ where
.collect();
let digits: Vec<_> = points_and_scalars
.iter()
.map(|(_, scalar)| Radix16Decomposition::new(scalar, C::FIELD_REPR_IS_BE))
.map(|(_, scalar)| Radix16Decomposition::new(scalar))
.collect();

lincomb::<C>(&tables, &digits)
Expand All @@ -462,7 +462,7 @@ where
.collect();
let digits: Vec<_> = points_and_scalars
.iter()
.map(|(_, scalar)| Radix16Decomposition::new(scalar, C::FIELD_REPR_IS_BE))
.map(|(_, scalar)| Radix16Decomposition::new(scalar))
.collect();

lincomb_vartime::<C>(&tables, &digits)
Expand All @@ -475,18 +475,16 @@ where
{
fn lincomb(points_and_scalars: &[(Self, Scalar<C>); N]) -> Self {
let tables: [_; N] = array::from_fn(|index| LookupTable::new(points_and_scalars[index].0));
let digits: [_; N] = array::from_fn(|index| {
Radix16Decomposition::new(&points_and_scalars[index].1, C::FIELD_REPR_IS_BE)
});
let digits: [_; N] =
array::from_fn(|index| Radix16Decomposition::new(&points_and_scalars[index].1));

lincomb::<C>(&tables, &digits)
}

fn lincomb_vartime(points_and_scalars: &[(Self, Scalar<C>); N]) -> Self {
let tables: [_; N] = array::from_fn(|index| LookupTable::new(points_and_scalars[index].0));
let digits: [_; N] = array::from_fn(|index| {
Radix16Decomposition::new(&points_and_scalars[index].1, C::FIELD_REPR_IS_BE)
});
let digits: [_; N] =
array::from_fn(|index| Radix16Decomposition::new(&points_and_scalars[index].1));

lincomb_vartime::<C>(&tables, &digits)
}
Expand Down
4 changes: 2 additions & 2 deletions primeorder/src/tables/basepoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<C: PrimeCurveParams, const WINDOW_SIZE: usize>
/// Multiply `Point::generator` by the given scalar in constant-time, using the precomputed
/// basepoint table to accelerate the scalar multiplication.
pub fn mul(&self, k: &Scalar<C>) -> ProjectivePoint<C> {
let digits = Radix16Decomposition::<Radix16Digits<C>>::new(k, true);
let digits = Radix16Decomposition::<Radix16Digits<C>>::new(k);
let len = FieldBytesSize::<C>::USIZE;
let mut acc = self[len].select(digits[len * 2]);
let mut acc2 = ProjectivePoint::<C>::IDENTITY;
Expand All @@ -107,7 +107,7 @@ impl<C: PrimeCurveParams, const WINDOW_SIZE: usize>
/// used with them.
/// </div>
pub fn mul_vartime(&self, k: &Scalar<C>) -> ProjectivePoint<C> {
let digits = Radix16Decomposition::<Radix16Digits<C>>::new(k, true);
let digits = Radix16Decomposition::<Radix16Digits<C>>::new(k);
let len = FieldBytesSize::<C>::USIZE;
let mut acc = self[len].select_vartime(digits[len * 2]);
let mut acc2 = ProjectivePoint::<C>::IDENTITY;
Expand Down
11 changes: 4 additions & 7 deletions primeorder/src/tables/radix16.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Radix-16 signed-digit decomposition for constant-time scalar multiplication.

use crate::PrimeFieldExt;
use core::ops::{Add, Index};
use elliptic_curve::{
FieldBytesSize, PrimeField,
FieldBytesSize,
array::{Array, ArraySize, sizes::U1},
};

Expand All @@ -27,17 +28,13 @@ impl<Digits: ArraySize> Radix16Decomposition<Digits> {
/// decomposition can be negative, so we need an additional byte to store it.
///
/// Assumes `x < 2^(4*(digits-1))`.
// TODO(tarcieri): get rid of `is_be` flag w\ e.g. zkcrypto/ff#158
pub fn new<Scalar: PrimeField>(scalar: &Scalar, is_be: bool) -> Self {
pub fn new<Scalar: PrimeFieldExt>(scalar: &Scalar) -> Self {
// TODO(tarcieri): `debug_assert!` that `scalar < 2^(4*(digits-1))`
let mut ret = Self::default();

// Step 1: change radix.
// Convert from big endian radix-256 (bytes) to radix-16 (nibbles).
let mut repr = scalar.to_repr();
if !is_be {
repr.as_mut().reverse();
}
let repr = scalar.to_be_repr();
let bytes = repr.as_ref();

for i in 0..(Digits::USIZE - 1) / 2 {
Expand Down
Loading