diff --git a/k256/src/arithmetic/affine.rs b/k256/src/arithmetic/affine.rs index 09031a14..c51b6dc2 100644 --- a/k256/src/arithmetic/affine.rs +++ b/k256/src/arithmetic/affine.rs @@ -1,9 +1,12 @@ //! Affine points +#![allow(clippy::op_ref)] + use super::{FieldElement, ProjectivePoint, CURVE_EQUATION_B}; use crate::{CompressedPoint, EncodedPoint, FieldBytes, Scalar, Secp256k1}; use core::ops::{Mul, Neg}; use elliptic_curve::{ + ff::Field, generic_array::arr, group::{prime::PrimeCurveAffine, GroupEncoding}, sec1::{self, FromEncodedPoint, ToEncodedPoint}, diff --git a/k256/src/arithmetic/field.rs b/k256/src/arithmetic/field.rs index f3cd6ec8..c2ebc87e 100644 --- a/k256/src/arithmetic/field.rs +++ b/k256/src/arithmetic/field.rs @@ -1,5 +1,7 @@ //! Field arithmetic modulo p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1 +#![allow(clippy::assign_op_pattern, clippy::op_ref)] + use cfg_if::cfg_if; cfg_if! { @@ -30,10 +32,12 @@ cfg_if! { } use crate::FieldBytes; -use core::ops::{Add, AddAssign, Mul, MulAssign}; +use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use elliptic_curve::{ + ff::Field, + rand_core::RngCore, subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}, - zeroize::Zeroize, + zeroize::DefaultIsZeroes, }; #[cfg(test)] @@ -43,17 +47,52 @@ use num_bigint::{BigUint, ToBigUint}; #[derive(Clone, Copy, Debug)] pub struct FieldElement(FieldElementImpl); -impl FieldElement { - /// Returns the zero element. - pub const fn zero() -> Self { - Self(FieldElementImpl::zero()) +impl Field for FieldElement { + fn random(mut rng: impl RngCore) -> Self { + let mut bytes = FieldBytes::default(); + + loop { + rng.fill_bytes(&mut bytes); + if let Some(fe) = Self::from_bytes(&bytes).into() { + return fe; + } + } + } + + fn zero() -> Self { + Self::ZERO + } + + fn one() -> Self { + Self::ONE } - /// Returns the multiplicative identity. - pub const fn one() -> Self { - Self(FieldElementImpl::one()) + #[must_use] + fn square(&self) -> Self { + self.square() } + #[must_use] + fn double(&self) -> Self { + self.double() + } + + fn invert(&self) -> CtOption { + self.invert() + } + + fn sqrt(&self) -> CtOption { + self.sqrt() + } +} + +impl FieldElement { + /// Zero element. + pub const ZERO: Self = Self(FieldElementImpl::zero()); + + /// Multiplicative identity. + pub const ONE: Self = Self(FieldElementImpl::one()); + /// Determine if this `FieldElement` is zero. /// /// # Returns @@ -133,7 +172,8 @@ impl FieldElement { Self(self.0.mul(&(rhs.0))) } - /// Returns self * self + /// Returns self * self. + /// /// Brings the magnitude to 1 (but doesn't normalize the result). /// The magnitudes of arguments should be <= 8. pub fn square(&self) -> Self { @@ -227,9 +267,15 @@ impl FieldElement { } } -impl PartialEq for FieldElement { - fn eq(&self, other: &Self) -> bool { - self.0.ct_eq(&(other.0)).into() +impl ConditionallySelectable for FieldElement { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Self(FieldElementImpl::conditional_select(&(a.0), &(b.0), choice)) + } +} + +impl ConstantTimeEq for FieldElement { + fn ct_eq(&self, other: &Self) -> Choice { + self.0.ct_eq(&(other.0)) } } @@ -239,19 +285,25 @@ impl Default for FieldElement { } } -impl ConditionallySelectable for FieldElement { - fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { - Self(FieldElementImpl::conditional_select(&(a.0), &(b.0), choice)) +impl DefaultIsZeroes for FieldElement {} + +impl Eq for FieldElement {} + +impl PartialEq for FieldElement { + fn eq(&self, other: &Self) -> bool { + self.0.ct_eq(&(other.0)).into() } } -impl ConstantTimeEq for FieldElement { - fn ct_eq(&self, other: &Self) -> Choice { - self.0.ct_eq(&(other.0)) +impl Add for FieldElement { + type Output = FieldElement; + + fn add(self, other: FieldElement) -> FieldElement { + FieldElement(self.0.add(&(other.0))) } } -impl Add<&FieldElement> for &FieldElement { +impl Add<&FieldElement> for FieldElement { type Output = FieldElement; fn add(self, other: &FieldElement) -> FieldElement { @@ -259,7 +311,7 @@ impl Add<&FieldElement> for &FieldElement { } } -impl Add<&FieldElement> for FieldElement { +impl Add<&FieldElement> for &FieldElement { type Output = FieldElement; fn add(self, other: &FieldElement) -> FieldElement { @@ -268,15 +320,49 @@ impl Add<&FieldElement> for FieldElement { } impl AddAssign for FieldElement { - fn add_assign(&mut self, rhs: FieldElement) { - *self = *self + &rhs; + fn add_assign(&mut self, other: FieldElement) { + *self = *self + &other; } } -impl Mul<&FieldElement> for &FieldElement { +impl AddAssign<&FieldElement> for FieldElement { + fn add_assign(&mut self, other: &FieldElement) { + *self = *self + other; + } +} + +impl Sub for FieldElement { type Output = FieldElement; - fn mul(self, other: &FieldElement) -> FieldElement { + fn sub(self, other: FieldElement) -> FieldElement { + self + -other + } +} + +impl Sub<&FieldElement> for FieldElement { + type Output = FieldElement; + + fn sub(self, other: &FieldElement) -> FieldElement { + self + -other + } +} + +impl SubAssign for FieldElement { + fn sub_assign(&mut self, other: FieldElement) { + *self = *self + -other; + } +} + +impl SubAssign<&FieldElement> for FieldElement { + fn sub_assign(&mut self, other: &FieldElement) { + *self = *self + -other; + } +} + +impl Mul for FieldElement { + type Output = FieldElement; + + fn mul(self, other: FieldElement) -> FieldElement { FieldElement(self.0.mul(&(other.0))) } } @@ -289,20 +375,45 @@ impl Mul<&FieldElement> for FieldElement { } } +impl Mul<&FieldElement> for &FieldElement { + type Output = FieldElement; + + fn mul(self, other: &FieldElement) -> FieldElement { + FieldElement(self.0.mul(&(other.0))) + } +} + impl MulAssign for FieldElement { fn mul_assign(&mut self, rhs: FieldElement) { *self = *self * &rhs; } } -impl Zeroize for FieldElement { - fn zeroize(&mut self) { - self.0.zeroize(); +impl MulAssign<&FieldElement> for FieldElement { + fn mul_assign(&mut self, rhs: &FieldElement) { + *self = *self * rhs; + } +} + +impl Neg for FieldElement { + type Output = FieldElement; + + fn neg(self) -> FieldElement { + self.negate(1) + } +} + +impl Neg for &FieldElement { + type Output = FieldElement; + + fn neg(self) -> FieldElement { + self.negate(1) } } #[cfg(test)] mod tests { + use elliptic_curve::ff::Field; use num_bigint::{BigUint, ToBigUint}; use proptest::prelude::*; diff --git a/k256/src/arithmetic/projective.rs b/k256/src/arithmetic/projective.rs index 2d242975..99aebe58 100644 --- a/k256/src/arithmetic/projective.rs +++ b/k256/src/arithmetic/projective.rs @@ -1,5 +1,7 @@ //! Projective points +#![allow(clippy::op_ref)] + use super::{AffinePoint, FieldElement, Scalar, CURVE_EQUATION_B_SINGLE}; use crate::{CompressedPoint, EncodedPoint, Secp256k1}; use core::{ @@ -102,9 +104,9 @@ impl ProjectivePoint { /// "point at infinity". pub const fn identity() -> ProjectivePoint { ProjectivePoint { - x: FieldElement::zero(), - y: FieldElement::one(), - z: FieldElement::zero(), + x: FieldElement::ZERO, + y: FieldElement::ONE, + z: FieldElement::ZERO, } } diff --git a/p256/src/arithmetic.rs b/p256/src/arithmetic.rs index 9a89d08b..98f95869 100644 --- a/p256/src/arithmetic.rs +++ b/p256/src/arithmetic.rs @@ -12,10 +12,10 @@ use projective::ProjectivePoint; use scalar::Scalar; /// a = -3 -const CURVE_EQUATION_A: FieldElement = FieldElement::zero() - .subtract(&FieldElement::one()) - .subtract(&FieldElement::one()) - .subtract(&FieldElement::one()); +const CURVE_EQUATION_A: FieldElement = FieldElement::ZERO + .subtract(&FieldElement::ONE) + .subtract(&FieldElement::ONE) + .subtract(&FieldElement::ONE); /// b = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B const CURVE_EQUATION_B: FieldElement = FieldElement([ diff --git a/p256/src/arithmetic/affine.rs b/p256/src/arithmetic/affine.rs index 6a2e0caa..67cce660 100644 --- a/p256/src/arithmetic/affine.rs +++ b/p256/src/arithmetic/affine.rs @@ -1,5 +1,7 @@ //! Affine points +#![allow(clippy::op_ref)] + use super::{FieldElement, ProjectivePoint, CURVE_EQUATION_A, CURVE_EQUATION_B, MODULUS}; use crate::{CompressedPoint, EncodedPoint, FieldBytes, NistP256, Scalar}; use core::ops::{Mul, Neg}; @@ -49,8 +51,8 @@ impl PrimeCurveAffine for AffinePoint { /// Returns the identity of the group: the point at infinity. fn identity() -> AffinePoint { Self { - x: FieldElement::zero(), - y: FieldElement::zero(), + x: FieldElement::ZERO, + y: FieldElement::ZERO, infinity: Choice::from(1), } } diff --git a/p256/src/arithmetic/field.rs b/p256/src/arithmetic/field.rs index 1de13590..25a18cb4 100644 --- a/p256/src/arithmetic/field.rs +++ b/p256/src/arithmetic/field.rs @@ -1,12 +1,15 @@ //! Field arithmetic modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1 +#![allow(clippy::assign_op_pattern, clippy::op_ref)] + use crate::{ arithmetic::util::{adc, mac, sbb}, FieldBytes, }; use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use elliptic_curve::{ - rand_core::{CryptoRng, RngCore}, + ff::Field, + rand_core::RngCore, subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}, zeroize::DefaultIsZeroes, }; @@ -40,11 +43,48 @@ const R2: FieldElement = FieldElement([ ]); /// An element in the finite field modulo p = 2^{224}(2^{32} − 1) + 2^{192} + 2^{96} − 1. -// The internal representation is in little-endian order. Elements are always in -// Montgomery form; i.e., FieldElement(a) = aR mod p, with R = 2^256. +/// +/// The internal representation is in little-endian order. Elements are always in +/// Montgomery form; i.e., FieldElement(a) = aR mod p, with R = 2^256. #[derive(Clone, Copy, Debug)] pub struct FieldElement(pub(crate) [u64; LIMBS]); +impl Field for FieldElement { + fn random(mut rng: impl RngCore) -> Self { + // We reduce a random 512-bit value into a 256-bit field, which results in a + // negligible bias from the uniform distribution. + let mut buf = [0; 64]; + rng.fill_bytes(&mut buf); + FieldElement::from_bytes_wide(buf) + } + + fn zero() -> Self { + Self::ZERO + } + + fn one() -> Self { + Self::ONE + } + + #[must_use] + fn square(&self) -> Self { + self.square() + } + + #[must_use] + fn double(&self) -> Self { + self.double() + } + + fn invert(&self) -> CtOption { + self.invert() + } + + fn sqrt(&self) -> CtOption { + self.sqrt() + } +} + impl ConditionallySelectable for FieldElement { fn conditional_select(a: &FieldElement, b: &FieldElement, choice: Choice) -> FieldElement { FieldElement([ @@ -65,12 +105,6 @@ impl ConstantTimeEq for FieldElement { } } -impl PartialEq for FieldElement { - fn eq(&self, other: &Self) -> bool { - self.ct_eq(other).into() - } -} - impl Default for FieldElement { fn default() -> Self { FieldElement::zero() @@ -79,25 +113,20 @@ impl Default for FieldElement { impl DefaultIsZeroes for FieldElement {} -impl FieldElement { - /// Returns the zero element. - pub const fn zero() -> FieldElement { - FieldElement([0, 0, 0, 0]) - } +impl Eq for FieldElement {} - /// Returns the multiplicative identity. - pub const fn one() -> FieldElement { - R +impl PartialEq for FieldElement { + fn eq(&self, other: &Self) -> bool { + self.ct_eq(other).into() } +} - /// Returns a uniformly-random element within the field. - pub fn generate(mut rng: impl CryptoRng + RngCore) -> Self { - // We reduce a random 512-bit value into a 256-bit field, which results in a - // negligible bias from the uniform distribution. - let mut buf = [0; 64]; - rng.fill_bytes(&mut buf); - FieldElement::from_bytes_wide(buf) - } +impl FieldElement { + /// Zero element. + pub const ZERO: Self = FieldElement([0, 0, 0, 0]); + + /// Multiplicative identity. + pub const ONE: Self = R; fn from_bytes_wide(bytes: [u8; 64]) -> Self { FieldElement::montgomery_reduce( @@ -439,11 +468,11 @@ impl FieldElement { } } -impl Add<&FieldElement> for &FieldElement { +impl Add for FieldElement { type Output = FieldElement; - fn add(self, other: &FieldElement) -> FieldElement { - FieldElement::add(self, other) + fn add(self, other: FieldElement) -> FieldElement { + FieldElement::add(&self, &other) } } @@ -455,17 +484,31 @@ impl Add<&FieldElement> for FieldElement { } } +impl Add<&FieldElement> for &FieldElement { + type Output = FieldElement; + + fn add(self, other: &FieldElement) -> FieldElement { + FieldElement::add(self, other) + } +} + impl AddAssign for FieldElement { - fn add_assign(&mut self, rhs: FieldElement) { - *self = FieldElement::add(self, &rhs); + fn add_assign(&mut self, other: FieldElement) { + *self = FieldElement::add(self, &other); } } -impl Sub<&FieldElement> for &FieldElement { +impl AddAssign<&FieldElement> for FieldElement { + fn add_assign(&mut self, other: &FieldElement) { + *self = FieldElement::add(self, other); + } +} + +impl Sub for FieldElement { type Output = FieldElement; - fn sub(self, other: &FieldElement) -> FieldElement { - FieldElement::subtract(self, other) + fn sub(self, other: FieldElement) -> FieldElement { + FieldElement::subtract(&self, &other) } } @@ -477,17 +520,31 @@ impl Sub<&FieldElement> for FieldElement { } } +impl Sub<&FieldElement> for &FieldElement { + type Output = FieldElement; + + fn sub(self, other: &FieldElement) -> FieldElement { + FieldElement::subtract(self, other) + } +} + impl SubAssign for FieldElement { - fn sub_assign(&mut self, rhs: FieldElement) { - *self = FieldElement::subtract(self, &rhs); + fn sub_assign(&mut self, other: FieldElement) { + *self = FieldElement::subtract(self, &other); } } -impl Mul<&FieldElement> for &FieldElement { +impl SubAssign<&FieldElement> for FieldElement { + fn sub_assign(&mut self, other: &FieldElement) { + *self = FieldElement::subtract(self, other); + } +} + +impl Mul for FieldElement { type Output = FieldElement; - fn mul(self, other: &FieldElement) -> FieldElement { - FieldElement::mul(self, other) + fn mul(self, other: FieldElement) -> FieldElement { + FieldElement::mul(&self, &other) } } @@ -499,9 +556,23 @@ impl Mul<&FieldElement> for FieldElement { } } +impl Mul<&FieldElement> for &FieldElement { + type Output = FieldElement; + + fn mul(self, other: &FieldElement) -> FieldElement { + FieldElement::mul(self, other) + } +} + impl MulAssign for FieldElement { - fn mul_assign(&mut self, rhs: FieldElement) { - *self = FieldElement::mul(self, &rhs); + fn mul_assign(&mut self, other: FieldElement) { + *self = FieldElement::mul(self, &other); + } +} + +impl MulAssign<&FieldElement> for FieldElement { + fn mul_assign(&mut self, other: &FieldElement) { + *self = FieldElement::mul(self, other); } } @@ -513,7 +584,7 @@ impl Neg for FieldElement { } } -impl<'a> Neg for &'a FieldElement { +impl Neg for &FieldElement { type Output = FieldElement; fn neg(self) -> FieldElement { @@ -525,6 +596,7 @@ impl<'a> Neg for &'a FieldElement { mod tests { use super::FieldElement; use crate::{test_vectors::field::DBL_TEST_VECTORS, FieldBytes}; + use elliptic_curve::ff::Field; use proptest::{num::u64::ANY, prelude::*}; #[test] diff --git a/p256/src/arithmetic/projective.rs b/p256/src/arithmetic/projective.rs index 6ab5a3b7..1b8ec7f5 100644 --- a/p256/src/arithmetic/projective.rs +++ b/p256/src/arithmetic/projective.rs @@ -1,5 +1,7 @@ //! Projective points +#![allow(clippy::op_ref)] + use super::{AffinePoint, FieldElement, Scalar, CURVE_EQUATION_B}; use crate::{CompressedPoint, EncodedPoint, NistP256}; use core::{ @@ -156,9 +158,9 @@ impl ProjectivePoint { /// "point at infinity". pub const fn identity() -> ProjectivePoint { ProjectivePoint { - x: FieldElement::zero(), - y: FieldElement::one(), - z: FieldElement::zero(), + x: FieldElement::ZERO, + y: FieldElement::ONE, + z: FieldElement::ZERO, } }