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
3 changes: 3 additions & 0 deletions k256/src/arithmetic/affine.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down
167 changes: 139 additions & 28 deletions k256/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
@@ -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)]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left all of the current arithmetic borrowing as-is in order to not affect performance as part of this PR, but it's probably worth benchmarking removing these in a followup and seeing if it affects performance

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can fix in a follow up PR. I did this crypto-bigint

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really easy to fix automatically with cargo clippy --fix, but I just want to make sure it doesn't cause a performance regression


use cfg_if::cfg_if;

cfg_if! {
Expand Down Expand Up @@ -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)]
Expand All @@ -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> {
self.invert()
}

fn sqrt(&self) -> CtOption<Self> {
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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
}
}

Expand All @@ -239,27 +285,33 @@ 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<FieldElement> 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 {
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 {
Expand All @@ -268,15 +320,49 @@ impl Add<&FieldElement> for FieldElement {
}

impl AddAssign<FieldElement> 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<FieldElement> 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<FieldElement> 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<FieldElement> for FieldElement {
type Output = FieldElement;

fn mul(self, other: FieldElement) -> FieldElement {
FieldElement(self.0.mul(&(other.0)))
}
}
Expand All @@ -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<FieldElement> 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::*;

Expand Down
8 changes: 5 additions & 3 deletions k256/src/arithmetic/projective.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down Expand Up @@ -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,
}
}

Expand Down
8 changes: 4 additions & 4 deletions p256/src/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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([
Expand Down
6 changes: 4 additions & 2 deletions p256/src/arithmetic/affine.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Affine points

#![allow(clippy::op_ref)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably fix this in a subsequent PR


use super::{FieldElement, ProjectivePoint, CURVE_EQUATION_A, CURVE_EQUATION_B, MODULUS};
use crate::{CompressedPoint, EncodedPoint, FieldBytes, NistP256, Scalar};
use core::ops::{Mul, Neg};
Expand Down Expand Up @@ -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),
}
}
Expand Down
Loading