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
55 changes: 52 additions & 3 deletions k256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ impl FieldElement {
FieldElementImpl::from_bytes(bytes).map(Self)
}

/// Convert a `u64` to a field element.
pub const fn from_u64(w: u64) -> Self {
Self(FieldElementImpl::from_u64(w))
}

/// Returns the SEC1 encoding of this field element.
pub fn to_bytes(self) -> FieldBytes {
self.0.normalize().to_bytes()
Expand Down Expand Up @@ -290,8 +295,8 @@ impl PrimeField for FieldElement {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff,
0xfe, 0x18,
]));
const MULTIPLICATIVE_GENERATOR: Self = Self(FieldElementImpl::from_u64(3));
const S: u32 = 0;
const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(3);
const S: u32 = 1;
const ROOT_OF_UNITY: Self = Self(FieldElementImpl::from_bytes_unchecked(&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
Expand All @@ -302,7 +307,7 @@ impl PrimeField for FieldElement {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
0xfc, 0x2e,
]));
const DELTA: Self = Self(FieldElementImpl::from_u64(9));
const DELTA: Self = Self::from_u64(9);

fn from_repr(repr: Self::Repr) -> CtOption<Self> {
Self::from_bytes(&repr)
Expand Down Expand Up @@ -493,6 +498,7 @@ impl<'a> Product<&'a FieldElement> for FieldElement {

#[cfg(test)]
mod tests {
use elliptic_curve::ff::{Field, PrimeField};
use num_bigint::{BigUint, ToBigUint};
use proptest::prelude::*;

Expand All @@ -516,6 +522,49 @@ mod tests {
}
}

#[test]
fn two_inv_constant() {
assert_eq!(
(FieldElement::from(2u64) * FieldElement::TWO_INV).normalize(),
FieldElement::ONE
);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
FieldElement::ROOT_OF_UNITY
.pow_vartime(&[1u64 << FieldElement::S, 0, 0, 0])
.normalize(),
FieldElement::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
(FieldElement::ROOT_OF_UNITY * FieldElement::ROOT_OF_UNITY_INV).normalize(),
FieldElement::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 4] = [
0xffffffff7ffffe17,
0xffffffffffffffff,
0xffffffffffffffff,
0x7fffffffffffffff,
];

// DELTA^{t} mod m == 1
assert_eq!(
FieldElement::DELTA.pow_vartime(&T).normalize(),
FieldElement::ONE
);
}

#[test]
fn zero_is_additive_identity() {
let zero = FieldElement::ZERO;
Expand Down
39 changes: 37 additions & 2 deletions k256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use core::{
ops::{Add, AddAssign, Mul, MulAssign, Neg, Shr, ShrAssign, Sub, SubAssign},
};
use elliptic_curve::{
bigint::{self, prelude::*, Limb, Word, U256, U512},
bigint::{prelude::*, Limb, Word, U256, U512},
ff::{self, Field, PrimeField},
ops::{Reduce, ReduceNonZero},
rand_core::{CryptoRngCore, RngCore},
Expand All @@ -36,7 +36,7 @@ use num_bigint::{BigUint, ToBigUint};

/// Constant representing the modulus
/// n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
const MODULUS: [Word; bigint::nlimbs!(256)] = ORDER.to_words();
const MODULUS: [Word; U256::LIMBS] = ORDER.to_words();

/// Constant representing the modulus / 2
const FRAC_MODULUS_2: U256 = ORDER.shr_vartime(1);
Expand Down Expand Up @@ -757,6 +757,41 @@ mod tests {
}
}

#[test]
fn two_inv_constant() {
assert_eq!(Scalar::from(2u32) * Scalar::TWO_INV, Scalar::ONE);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
Scalar::ROOT_OF_UNITY.pow_vartime(&[1u64 << Scalar::S, 0, 0, 0]),
Scalar::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
Scalar::ROOT_OF_UNITY * Scalar::ROOT_OF_UNITY_INV,
Scalar::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 4] = [
0xeeff497a3340d905,
0xfaeabb739abd2280,
0xffffffffffffffff,
0x03ffffffffffffff,
];

// DELTA^{t} mod m == 1
assert_eq!(Scalar::DELTA.pow_vartime(&T), Scalar::ONE);
}

#[test]
fn is_high() {
// 0 is not high
Expand Down
47 changes: 42 additions & 5 deletions p256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,10 @@ impl PrimeField for FieldElement {
const TWO_INV: Self = Self::from_u64(2).invert_unchecked();
const MULTIPLICATIVE_GENERATOR: Self = Self::from_u64(6);
const S: u32 = 1;
const ROOT_OF_UNITY: Self = Self(U256::from_be_hex(
"ffffffff00000001000000000000000000000000fffffffffffffffffffffffe",
));
const ROOT_OF_UNITY: Self =
Self::from_hex("ffffffff00000001000000000000000000000000fffffffffffffffffffffffe");
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self::ZERO; // TODO
const DELTA: Self = Self::from_u64(36);

#[inline]
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
Expand All @@ -158,9 +157,47 @@ impl PrimeField for FieldElement {
mod tests {
use super::FieldElement;
use crate::{test_vectors::field::DBL_TEST_VECTORS, FieldBytes};
use elliptic_curve::bigint::U256;
use elliptic_curve::{bigint::U256, ff::PrimeField};
use proptest::{num, prelude::*};

#[test]
fn two_inv_constant() {
assert_eq!(
FieldElement::from(2u32) * FieldElement::TWO_INV,
FieldElement::ONE
);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
FieldElement::ROOT_OF_UNITY.pow_vartime(&[1u64 << FieldElement::S, 0, 0, 0]),
FieldElement::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
FieldElement::ROOT_OF_UNITY * FieldElement::ROOT_OF_UNITY_INV,
FieldElement::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 4] = [
0xffffffffffffffff,
0x000000007fffffff,
0x8000000000000000,
0x7fffffff80000000,
];

// DELTA^{t} mod m == 1
assert_eq!(FieldElement::DELTA.pow_vartime(&T), FieldElement::ONE);
}

#[test]
fn zero_is_additive_identity() {
let zero = FieldElement::ZERO;
Expand Down
39 changes: 37 additions & 2 deletions p256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl Scalar {

/// Exponentiates `self` by `exp`, where `exp` is a little-endian order integer
/// exponent.
pub(crate) const fn pow_vartime(&self, exp: &[u64]) -> Self {
pub const fn pow_vartime(&self, exp: &[u64]) -> Self {
let mut res = Self::ONE;

let mut i = exp.len();
Expand Down Expand Up @@ -299,7 +299,7 @@ impl PrimeField for Scalar {
"ffc97f062a770992ba807ace842a3dfc1546cad004378daf0592d7fbb41e6602",
));
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self::ZERO; // TODO
const DELTA: Self = Self(U256::from_u64(33232930569601));

/// Attempts to parse the given byte array as an SEC1-encoded scalar.
///
Expand Down Expand Up @@ -686,6 +686,41 @@ mod tests {
use crate::{FieldBytes, SecretKey};
use elliptic_curve::group::ff::{Field, PrimeField};

#[test]
fn two_inv_constant() {
assert_eq!(Scalar::from(2u32) * Scalar::TWO_INV, Scalar::ONE);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
Scalar::ROOT_OF_UNITY.pow_vartime(&[1u64 << Scalar::S, 0, 0, 0]),
Scalar::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
Scalar::ROOT_OF_UNITY * Scalar::ROOT_OF_UNITY_INV,
Scalar::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 4] = [
0x4f3b9cac2fc63255,
0xfbce6faada7179e8,
0x0fffffffffffffff,
0x0ffffffff0000000,
];

// DELTA^{t} mod m == 1
assert_eq!(Scalar::DELTA.pow_vartime(&T), Scalar::ONE);
}

#[test]
fn from_to_bytes_roundtrip() {
let k: u64 = 42;
Expand Down
43 changes: 42 additions & 1 deletion p384/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ impl PrimeField for FieldElement {
const S: u32 = 1;
const ROOT_OF_UNITY: Self = Self::from_hex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffe");
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self::ZERO; // TODO
const DELTA: Self = Self::from_u64(49);

#[inline]
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
Expand All @@ -154,6 +154,47 @@ impl PrimeField for FieldElement {
#[cfg(test)]
mod tests {
use super::FieldElement;
use elliptic_curve::ff::PrimeField;

#[test]
fn two_inv_constant() {
assert_eq!(
FieldElement::from(2u32) * FieldElement::TWO_INV,
FieldElement::ONE
);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
FieldElement::ROOT_OF_UNITY.pow_vartime(&[1u64 << FieldElement::S, 0, 0, 0]),
FieldElement::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
FieldElement::ROOT_OF_UNITY * FieldElement::ROOT_OF_UNITY_INV,
FieldElement::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 6] = [
0x000000007fffffff,
0x7fffffff80000000,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0x7fffffffffffffff,
];

// DELTA^{t} mod m == 1
assert_eq!(FieldElement::DELTA.pow_vartime(&T), FieldElement::ONE);
}

/// Basic tests that field inversion works.
#[test]
Expand Down
39 changes: 38 additions & 1 deletion p384/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl PrimeField for Scalar {
const S: u32 = 1;
const ROOT_OF_UNITY: Self = Self::from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52972");
const ROOT_OF_UNITY_INV: Self = Self::ROOT_OF_UNITY.invert_unchecked();
const DELTA: Self = Self::ZERO; // TODO
const DELTA: Self = Self::from_u64(4);

#[inline]
fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
Expand Down Expand Up @@ -356,6 +356,43 @@ mod tests {
use crate::FieldBytes;
use elliptic_curve::ff::PrimeField;

#[test]
fn two_inv_constant() {
assert_eq!(Scalar::from(2u32) * Scalar::TWO_INV, Scalar::ONE);
}

#[test]
fn root_of_unity_constant() {
// ROOT_OF_UNITY^{2^s} mod m == 1
assert_eq!(
Scalar::ROOT_OF_UNITY.pow_vartime(&[1u64 << Scalar::S, 0, 0, 0]),
Scalar::ONE
);
}

#[test]
fn root_of_unity_inv_constant() {
assert_eq!(
Scalar::ROOT_OF_UNITY * Scalar::ROOT_OF_UNITY_INV,
Scalar::ONE
);
}

#[test]
fn delta_constant() {
const T: [u64; 6] = [
0x76760cb5666294b9,
0xac0d06d9245853bd,
0xe3b1a6c0fa1b96ef,
0xffffffffffffffff,
0xffffffffffffffff,
0x7fffffffffffffff,
];

// DELTA^{t} mod m == 1
assert_eq!(Scalar::DELTA.pow_vartime(&T), Scalar::ONE);
}

#[test]
fn from_to_bytes_roundtrip() {
let k: u64 = 42;
Expand Down