From 214ae3c4100a8c73cb6c2c0bb2ef721704da8ddc Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 8 Sep 2020 18:19:21 -0700 Subject: [PATCH] elliptic-curve: add `arithmetic` feature This crate now has a large(r) number of dependencies via the `ff` and `group` crates (notably the recently introduced `bitvec` and its transitive dependencies). This commit adds an `arithmetic` feature and gates related functionality under it, along with the `ff` and `group` crate dependencies. This ensures these dependencies (and their transitive dependencies) can be excluded when the `arithmetic` features of elliptic curve implementations are non-existent or an associated feature disabled. --- .github/workflows/elliptic-curve.yml | 1 + Cargo.lock | 1 + elliptic-curve/Cargo.toml | 10 ++++--- elliptic-curve/src/lib.rs | 39 +++++++++++++++++++++------- elliptic-curve/src/ops.rs | 2 ++ elliptic-curve/src/sec1.rs | 21 +++++++++------ elliptic-curve/src/secret_key.rs | 8 ++++-- 7 files changed, 59 insertions(+), 23 deletions(-) diff --git a/.github/workflows/elliptic-curve.yml b/.github/workflows/elliptic-curve.yml index 5e43712e1..65b73fe51 100644 --- a/.github/workflows/elliptic-curve.yml +++ b/.github/workflows/elliptic-curve.yml @@ -36,6 +36,7 @@ jobs: target: ${{ matrix.target }} override: true - run: cargo build --no-default-features --release --target ${{ matrix.target }} + - run: cargo build --no-default-features --release --target ${{ matrix.target }} --features arithmetic test: runs-on: ubuntu-latest strategy: diff --git a/Cargo.lock b/Cargo.lock index 747877e70..0556b4492 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,7 @@ dependencies = [ name = "elliptic-curve" version = "0.5.0" dependencies = [ + "bitvec", "const-oid", "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ff", diff --git a/elliptic-curve/Cargo.toml b/elliptic-curve/Cargo.toml index da50dd4b0..69cb3301c 100644 --- a/elliptic-curve/Cargo.toml +++ b/elliptic-curve/Cargo.toml @@ -15,9 +15,10 @@ categories = ["cryptography", "no-std"] keywords = ["crypto", "ecc", "elliptic", "weierstrass"] [dependencies] +bitvec = { version = "0.18", optional = true, default-features = false } digest = { version = "0.9", optional = true } -ff = { version = "0.8", default-features = false } -group = { version = "0.8", default-features = false } +ff = { version = "0.8", optional = true, default-features = false } +group = { version = "0.8", optional = true, default-features = false } generic-array = { version = "0.14", default-features = false } oid = { package = "const-oid", version = "0.1", optional = true } rand_core = { version = "0.5", default-features = false } @@ -28,9 +29,10 @@ zeroize = { version = "1", optional = true, default-features = false } hex-literal = "0.2" [features] -default = [] +default = ["arithmetic"] alloc = [] -ecdh = ["zeroize"] +arithmetic = ["bitvec", "ff", "group"] +ecdh = ["arithmetic", "zeroize"] std = ["alloc"] [package.metadata.docs.rs] diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index e1849ddd7..420e6c934 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -28,23 +28,33 @@ extern crate std; pub mod error; pub mod ops; pub mod point; -pub mod scalar; pub mod sec1; pub mod secret_key; pub mod util; pub mod weierstrass; +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +pub mod scalar; + #[cfg(feature = "ecdh")] #[cfg_attr(docsrs, doc(cfg(feature = "ecdh")))] pub mod ecdh; pub use self::{error::Error, secret_key::SecretKey}; -pub use ff; + pub use generic_array::{self, typenum::consts}; -pub use group; pub use rand_core; pub use subtle; +// TODO(tarcieri): source this via ff crate: https://github.com/zkcrypto/ff/pull/40 +#[cfg(feature = "arithmetic")] +pub use bitvec::view::BitView; +#[cfg(feature = "arithmetic")] +pub use ff; +#[cfg(feature = "arithmetic")] +pub use group; + #[cfg(feature = "digest")] pub use digest::{self, Digest}; @@ -54,15 +64,24 @@ pub use oid; #[cfg(feature = "zeroize")] pub use zeroize; -use core::{ - fmt::Debug, - ops::{Add, Mul}, -}; +use core::{fmt::Debug, ops::Add}; use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; use rand_core::{CryptoRng, RngCore}; -use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; +use subtle::{ConditionallySelectable, CtOption}; + +#[cfg(feature = "arithmetic")] +use bitvec::{array::BitArray, order::Lsb0}; +#[cfg(feature = "arithmetic")] +use core::ops::Mul; +#[cfg(feature = "arithmetic")] +use subtle::ConstantTimeEq; + +/// Bit representation of a scalar field element of a given curve. +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] +pub type FieldBits = BitArray::Scalar as ff::PrimeField>::ReprBits>; -/// Byte array containing a serialized scalar value (i.e. an integer) +/// Byte representation of a base/scalar field element of a given curve. pub type ElementBytes = GenericArray::FieldSize>; /// Elliptic curve. @@ -83,6 +102,8 @@ pub trait Curve: Clone + Debug + Default + Eq + Ord + Send + Sync { } /// Elliptic curve with arithmetic implementation. +#[cfg(feature = "arithmetic")] +#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] pub trait Arithmetic: Curve { /// Scalar field element modulo the curve's order. type Scalar: ff::PrimeField diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index 09f811d7e..f499c01de 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -1,5 +1,7 @@ //! Traits for arithmetic operations on elliptic curve field elements +pub use core::ops::{Add, Mul}; + use subtle::CtOption; /// Perform an inversion on a field element (i.e. base field element or scalar) diff --git a/elliptic-curve/src/sec1.rs b/elliptic-curve/src/sec1.rs index 3c58397cb..24e418e30 100644 --- a/elliptic-curve/src/sec1.rs +++ b/elliptic-curve/src/sec1.rs @@ -5,25 +5,26 @@ //! //! -use crate::{ - point::Generator, - scalar::NonZeroScalar, - weierstrass::{point::Decompress, Curve}, - Arithmetic, ElementBytes, Error, FromBytes, SecretKey, -}; +use crate::{weierstrass::Curve, ElementBytes, Error}; use core::{ fmt::{self, Debug}, - ops::{Add, Mul}, + ops::Add, }; use generic_array::{ typenum::{Unsigned, U1}, ArrayLength, GenericArray, }; -use subtle::{Choice, CtOption}; +use subtle::CtOption; #[cfg(feature = "alloc")] use alloc::boxed::Box; +#[cfg(feature = "arithmetic")] +use crate::{ + ops::Mul, point::Generator, scalar::NonZeroScalar, subtle::Choice, + weierstrass::point::Decompress, Arithmetic, FromBytes, SecretKey, +}; + #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -124,6 +125,8 @@ where /// [`SecretKey`]. /// /// The `compress` flag requests point compression. + #[cfg(feature = "arithmetic")] + #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] pub fn from_secret_key(secret_key: &SecretKey, compress: bool) -> Result where C: Arithmetic, @@ -170,6 +173,8 @@ where } /// Decompress this [`EncodedPoint`], returning a new [`EncodedPoint`]. + #[cfg(feature = "arithmetic")] + #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] pub fn decompress(&self) -> CtOption where C: Arithmetic, diff --git a/elliptic-curve/src/secret_key.rs b/elliptic-curve/src/secret_key.rs index 263c0111c..76f57ef18 100644 --- a/elliptic-curve/src/secret_key.rs +++ b/elliptic-curve/src/secret_key.rs @@ -8,12 +8,15 @@ //! zeroing it out of memory securely on drop. use crate::{error::Error, Curve, ElementBytes}; -use crate::{Arithmetic, Generate}; use core::{ convert::{TryFrom, TryInto}, fmt::{self, Debug}, }; use generic_array::{typenum::Unsigned, GenericArray}; + +#[cfg(feature = "arithmetic")] +use crate::{scalar::NonZeroScalar, Arithmetic, Generate}; +#[cfg(feature = "arithmetic")] use rand_core::{CryptoRng, RngCore}; /// Elliptic curve secret keys. @@ -64,6 +67,7 @@ impl Debug for SecretKey { } } +#[cfg(feature = "arithmetic")] impl Generate for SecretKey where C: Curve + Arithmetic, @@ -72,7 +76,7 @@ where /// Generate a new [`SecretKey`] fn generate(rng: impl CryptoRng + RngCore) -> Self { Self { - scalar: C::Scalar::generate(rng).into(), + scalar: NonZeroScalar::::generate(rng).into(), } } }