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
8 changes: 4 additions & 4 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ opt-level = 2

[patch.crates-io]
ecdsa = { git = "https://github.com/RustCrypto/signatures.git" }
elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" }
elliptic-curve = { git = "https://github.com/RustCrypto/traits.git" }
2 changes: 1 addition & 1 deletion bp256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }

# optional dependencies
ecdsa = { version = "=0.16.0-pre.0", optional = true, default-features = false, features = ["der"] }
Expand Down
2 changes: 1 addition & 1 deletion bp384/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }

# optional dependencies
ecdsa = { version = "=0.16.0-pre.0", optional = true, default-features = false, features = ["der"] }
Expand Down
2 changes: 1 addition & 1 deletion k256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ rust-version = "1.61"

[dependencies]
cfg-if = "1.0"
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }

# optional dependencies
once_cell = { version = "1.16", optional = true, default-features = false }
Expand Down
10 changes: 9 additions & 1 deletion k256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use core::{
use elliptic_curve::{
bigint::{prelude::*, Limb, Word, U256, U512},
ff::{self, Field, PrimeField},
ops::{Reduce, ReduceNonZero},
ops::{Invert, Reduce, ReduceNonZero},
rand_core::{CryptoRngCore, RngCore},
scalar::{FromUintUnchecked, IsHigh},
subtle::{
Expand Down Expand Up @@ -412,6 +412,14 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
self.0.ct_gt(&FRAC_MODULUS_2)
Expand Down
2 changes: 1 addition & 1 deletion p224/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }

[features]
default = ["pem", "std"]
Expand Down
2 changes: 1 addition & 1 deletion p256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }
primeorder = { version = "=0.13.0-pre", path = "../primeorder" }

# optional dependencies
Expand Down
74 changes: 67 additions & 7 deletions p256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use core::{
use elliptic_curve::{
bigint::{prelude::*, Limb, U256},
group::ff::{self, Field, PrimeField},
ops::{Reduce, ReduceNonZero},
ops::{Invert, Reduce, ReduceNonZero},
rand_core::RngCore,
scalar::{FromUintUnchecked, IsHigh},
subtle::{
Expand Down Expand Up @@ -178,12 +178,6 @@ impl Scalar {
res
}

/// Faster inversion using Stein's algorithm
#[allow(non_snake_case)]
pub fn invert_vartime(&self) -> CtOption<Self> {
elliptic_curve::scalar::invert_vartime::<NistP256>(self)
}

/// Is integer representing equivalence class odd?
pub fn is_odd(&self) -> Choice {
self.0.is_odd()
Expand Down Expand Up @@ -348,6 +342,72 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}

/// Fast variable-time inversion using Stein's algorithm.
///
/// Returns none if the scalar is zero.
///
/// <https://link.springer.com/article/10.1007/s13389-016-0135-4>
///
/// ⚠️ WARNING!
///
/// This method should not be used with (unblinded) secret scalars, as its
/// variable-time operation can potentially leak secrets through
/// sidechannels.
#[allow(non_snake_case)]
fn invert_vartime(&self) -> CtOption<Self> {
Copy link
Member Author

Choose a reason for hiding this comment

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

@fjarri FYI, there's now a dedicated method for variable-time inversions which is used by the generic ECDSA implementation.

This can probably be adapted to work with k256? I had previously tried to make it fully generic, but due to the use of Self(MODULUS) below it's relying on support in the underlying field implementation.

I tried porting it to k256 and it seemed to work, although ECDSA verification performance was only up by ~3%.

let mut u = *self;
let mut v = Self(MODULUS);
let mut A = Self::ONE;
let mut C = Self::ZERO;

while !bool::from(u.is_zero()) {
// u-loop
while bool::from(u.is_even()) {
u >>= 1;

let was_odd: bool = A.is_odd().into();
A >>= 1;

if was_odd {
A += FRAC_MODULUS_2;
A += Self::ONE;
}
}

// v-loop
while bool::from(v.is_even()) {
v >>= 1;

let was_odd: bool = C.is_odd().into();
C >>= 1;

if was_odd {
C += FRAC_MODULUS_2;
C += Self::ONE;
}
}

// sub-step
if u >= v {
u -= &v;
A -= &C;
} else {
v -= &u;
C -= &A;
}
}

CtOption::new(C, !self.is_zero())
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
self.0.ct_gt(&FRAC_MODULUS_2.0)
Expand Down
22 changes: 22 additions & 0 deletions p256/tests/scalar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Scalar arithmetic tests.

#![cfg(feature = "arithmetic")]

use elliptic_curve::ops::{Invert, Reduce};
use p256::{Scalar, U256};
use proptest::prelude::*;

prop_compose! {
fn scalar()(bytes in any::<[u8; 32]>()) -> Scalar {
<Scalar as Reduce<U256>>::reduce_bytes(&bytes.into())
}
}

proptest! {
#[test]
fn invert_and_invert_vartime_are_equivalent(w in scalar()) {
let inv: Option<Scalar> = w.invert().into();
let inv_vartime: Option<Scalar> = w.invert_vartime().into();
prop_assert_eq!(inv, inv_vartime);
}
}
2 changes: 1 addition & 1 deletion p384/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }
primeorder = { version = "=0.13.0-pre", path = "../primeorder" }

# optional dependencies
Expand Down
10 changes: 9 additions & 1 deletion p384/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use core::{
use elliptic_curve::{
bigint::{self, ArrayEncoding, Limb},
ff::PrimeField,
ops::Reduce,
ops::{Invert, Reduce},
scalar::{FromUintUnchecked, IsHigh},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, CtOption},
Curve as _, Error, Result, ScalarPrimitive,
Expand Down Expand Up @@ -182,6 +182,14 @@ impl FromUintUnchecked for Scalar {
}
}

impl Invert for Scalar {
type Output = CtOption<Self>;

fn invert(&self) -> CtOption<Self> {
self.invert()
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
const MODULUS_SHR1: U384 = NistP384::ORDER.shr_vartime(1);
Expand Down
2 changes: 1 addition & 1 deletion p521/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["hazmat", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["hazmat", "sec1"] }

[features]
default = ["pem", "std"]
Expand Down
2 changes: 1 addition & 1 deletion primeorder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ edition = "2021"
rust-version = "1.61"

[dependencies]
elliptic-curve = { version = "=0.13.0-pre.3", default-features = false, features = ["arithmetic", "sec1"] }
elliptic-curve = { version = "=0.13.0-pre.4", default-features = false, features = ["arithmetic", "sec1"] }

# optional dependencies
serdect = { version = "0.1", optional = true, default-features = false }
Expand Down