diff --git a/.github/workflows/curve25519-dalek.yml b/.github/workflows/curve25519-dalek.yml index 3f688b4..3903c0e 100644 --- a/.github/workflows/curve25519-dalek.yml +++ b/.github/workflows/curve25519-dalek.yml @@ -127,7 +127,7 @@ jobs: # This should automatically pick up the simd backend in a x86_64 runner # It should pick AVX2 due to stable toolchain used since AVX512 requires nigthly RUSTFLAGS: '-C target_feature=+avx2' - run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize,group-bits --target x86_64-unknown-linux-gnu + run: cargo test --no-default-features --features alloc,precomputed-tables,zeroize --target x86_64-unknown-linux-gnu msrv: name: Current MSRV is 1.85.0 diff --git a/Cargo.lock b/Cargo.lock index 0626ae7..70ccc52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addchain" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -88,18 +77,6 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "blake2" version = "0.11.0-rc.6" @@ -342,8 +319,6 @@ dependencies = [ "proptest", "rand_core 0.10.0", "rustc_version", - "rustcrypto-ff", - "rustcrypto-group", "serde", "sha2", "subtle", @@ -356,7 +331,7 @@ version = "0.1.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -478,12 +453,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - [[package]] name = "getrandom" version = "0.3.4" @@ -695,26 +664,6 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -812,7 +761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn", ] [[package]] @@ -864,12 +813,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - [[package]] name = "rand" version = "0.9.4" @@ -972,44 +915,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustcrypto-ff" -version = "0.14.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd2a8adb347447693cd2ba0d218c4b66c62da9b0a5672b17b981e4291ec65ff6" -dependencies = [ - "bitvec", - "rand_core 0.10.0", - "rustcrypto-ff_derive", - "subtle", -] - -[[package]] -name = "rustcrypto-ff_derive" -version = "0.14.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cda22ea03582974ab5687fc131eba2dc78e258e7eef4d7e01bcd0522ed79f66" -dependencies = [ - "addchain", - "num-bigint", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rustcrypto-group" -version = "0.14.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369f9b61aa45933c062c9f6b5c3c50ab710687eca83dd3802653b140b43f85ed" -dependencies = [ - "rand_core 0.10.0", - "rustcrypto-ff", - "subtle", -] - [[package]] name = "rustix" version = "1.1.3" @@ -1089,7 +994,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1198,17 +1103,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.114" @@ -1220,12 +1114,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - [[package]] name = "tempfile" version = "3.24.0" @@ -1256,7 +1144,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1401,7 +1289,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn", "wasm-bindgen-shared", ] @@ -1518,7 +1406,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.114", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -1534,7 +1422,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.114", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -1576,15 +1464,6 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - [[package]] name = "x25519-dalek" version = "3.0.0-pre.6" @@ -1615,7 +1494,7 @@ checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1635,7 +1514,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] diff --git a/curve25519-dalek/Cargo.toml b/curve25519-dalek/Cargo.toml index d042210..35a4288 100644 --- a/curve25519-dalek/Cargo.toml +++ b/curve25519-dalek/Cargo.toml @@ -47,8 +47,6 @@ required-features = ["alloc", "rand_core"] [dependencies] cfg-if = "1" -ff = { version = "0.14.0-rc.1", package = "rustcrypto-ff", default-features = false, optional = true } -group = { version = "0.14.0-rc.1", package = "rustcrypto-group", default-features = false, optional = true } rand_core = { version = "0.10", default-features = false, optional = true } digest = { version = "0.11", default-features = false, optional = true, features = ["block-api"] } subtle = { version = "2.6.0", default-features = false, features = [ @@ -70,8 +68,6 @@ default = ["alloc", "precomputed-tables", "zeroize"] alloc = ["zeroize?/alloc"] precomputed-tables = [] legacy_compatibility = [] -group = ["dep:group", "rand_core"] -group-bits = ["group", "ff/bits"] digest = ["dep:digest"] lizard = ["digest"] diff --git a/curve25519-dalek/README.md b/curve25519-dalek/README.md index 2d902dd..f9468b6 100644 --- a/curve25519-dalek/README.md +++ b/curve25519-dalek/README.md @@ -55,8 +55,6 @@ curve25519-dalek = ">= 5.0, < 5.2" | `digest` | | Enables `RistrettoPoint::{from_hash, hash_from_bytes}` and `Scalar::{from_hash, hash_from_bytes}`. Also enables hash-to-curve methods `EdwardsPoint::{encode_to_curve, hash_to_curve}`. This is an optional dependency whose version is not subject to SemVer. See [below](#public-api-semver-exemptions) for more details. | | `serde` | | Enables `serde` serialization/deserialization for all the point and scalar types. | | `legacy_compatibility`| | Enables `Scalar::from_bits`, which allows the user to build unreduced scalars whose arithmetic is broken. Do not use this unless you know what you're doing. | -| `group` | | Enables external `group` and `ff` crate traits. | -| `group-bits` | | Enables `group` and impls `ff::PrimeFieldBits` for `Scalar`. | | `lizard` | | Enables the [Lizard](src/lizard/README.md) bytestring-to-point injection for `RistrettoPoint`. Specifically enables the methods `lizard_encode` and `lizard_decode`. | To disable the default features when using `curve25519-dalek` as a dependency, diff --git a/curve25519-dalek/src/edwards.rs b/curve25519-dalek/src/edwards.rs index 785c473..5d68da7 100644 --- a/curve25519-dalek/src/edwards.rs +++ b/curve25519-dalek/src/edwards.rs @@ -110,13 +110,6 @@ use digest::{ typenum::IsGreater, }; -#[cfg(feature = "group")] -use { - group::{GroupEncoding, cofactor::CofactorGroup, prime::PrimeGroup}, - rand_core::TryRng, - subtle::CtOption, -}; - #[cfg(feature = "rand_core")] use rand_core::Rng; @@ -1451,338 +1444,6 @@ impl Debug for EdwardsPoint { } } -// ------------------------------------------------------------------------ -// group traits -// ------------------------------------------------------------------------ - -// Use the full trait path to avoid Group::identity overlapping Identity::identity in the -// rest of the module (e.g. tests). -#[cfg(feature = "group")] -impl group::Group for EdwardsPoint { - type Scalar = Scalar; - - fn try_from_rng(rng: &mut R) -> Result { - let mut repr = CompressedEdwardsY([0u8; 32]); - loop { - rng.try_fill_bytes(&mut repr.0)?; - if let Some(p) = repr.decompress() { - if !IsIdentity::is_identity(&p) { - break Ok(p); - } - } - } - } - - fn identity() -> Self { - Identity::identity() - } - - fn generator() -> Self { - constants::ED25519_BASEPOINT_POINT - } - - fn is_identity(&self) -> Choice { - self.ct_eq(&Identity::identity()) - } - - fn double(&self) -> Self { - self.double() - } -} - -#[cfg(feature = "group")] -impl GroupEncoding for EdwardsPoint { - type Repr = [u8; 32]; - - fn from_bytes(bytes: &Self::Repr) -> CtOption { - let repr = CompressedEdwardsY(*bytes); - let (is_valid_y_coord, X, Y, Z) = decompress::step_1(&repr); - CtOption::new(decompress::step_2(&repr, X, Y, Z), is_valid_y_coord) - } - - fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { - // Just use the checked API; there are no checks we can skip. - Self::from_bytes(bytes) - } - - fn to_bytes(&self) -> Self::Repr { - self.compress().to_bytes() - } -} - -/// A `SubgroupPoint` represents a point on the Edwards form of Curve25519, that is -/// guaranteed to be in the prime-order subgroup. -#[cfg(feature = "group")] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct SubgroupPoint(EdwardsPoint); - -#[cfg(feature = "group")] -impl From for EdwardsPoint { - fn from(p: SubgroupPoint) -> Self { - p.0 - } -} - -#[cfg(feature = "group")] -impl Neg for SubgroupPoint { - type Output = Self; - - fn neg(self) -> Self::Output { - SubgroupPoint(-self.0) - } -} - -#[cfg(feature = "group")] -impl Add<&SubgroupPoint> for &SubgroupPoint { - type Output = SubgroupPoint; - fn add(self, other: &SubgroupPoint) -> SubgroupPoint { - SubgroupPoint(self.0 + other.0) - } -} - -#[cfg(feature = "group")] -define_add_variants!( - LHS = SubgroupPoint, - RHS = SubgroupPoint, - Output = SubgroupPoint -); - -#[cfg(feature = "group")] -impl Add<&SubgroupPoint> for &EdwardsPoint { - type Output = EdwardsPoint; - fn add(self, other: &SubgroupPoint) -> EdwardsPoint { - self + other.0 - } -} - -#[cfg(feature = "group")] -define_add_variants!( - LHS = EdwardsPoint, - RHS = SubgroupPoint, - Output = EdwardsPoint -); - -#[cfg(feature = "group")] -impl AddAssign<&SubgroupPoint> for SubgroupPoint { - fn add_assign(&mut self, rhs: &SubgroupPoint) { - self.0 += rhs.0 - } -} - -#[cfg(feature = "group")] -define_add_assign_variants!(LHS = SubgroupPoint, RHS = SubgroupPoint); - -#[cfg(feature = "group")] -impl AddAssign<&SubgroupPoint> for EdwardsPoint { - fn add_assign(&mut self, rhs: &SubgroupPoint) { - *self += rhs.0 - } -} - -#[cfg(feature = "group")] -define_add_assign_variants!(LHS = EdwardsPoint, RHS = SubgroupPoint); - -#[cfg(feature = "group")] -impl Sub<&SubgroupPoint> for &SubgroupPoint { - type Output = SubgroupPoint; - fn sub(self, other: &SubgroupPoint) -> SubgroupPoint { - SubgroupPoint(self.0 - other.0) - } -} - -#[cfg(feature = "group")] -define_sub_variants!( - LHS = SubgroupPoint, - RHS = SubgroupPoint, - Output = SubgroupPoint -); - -#[cfg(feature = "group")] -impl Sub<&SubgroupPoint> for &EdwardsPoint { - type Output = EdwardsPoint; - fn sub(self, other: &SubgroupPoint) -> EdwardsPoint { - self - other.0 - } -} - -#[cfg(feature = "group")] -define_sub_variants!( - LHS = EdwardsPoint, - RHS = SubgroupPoint, - Output = EdwardsPoint -); - -#[cfg(feature = "group")] -impl SubAssign<&SubgroupPoint> for SubgroupPoint { - fn sub_assign(&mut self, rhs: &SubgroupPoint) { - self.0 -= rhs.0; - } -} - -#[cfg(feature = "group")] -define_sub_assign_variants!(LHS = SubgroupPoint, RHS = SubgroupPoint); - -#[cfg(feature = "group")] -impl SubAssign<&SubgroupPoint> for EdwardsPoint { - fn sub_assign(&mut self, rhs: &SubgroupPoint) { - *self -= rhs.0; - } -} - -#[cfg(feature = "group")] -define_sub_assign_variants!(LHS = EdwardsPoint, RHS = SubgroupPoint); - -#[cfg(feature = "group")] -impl Sum for SubgroupPoint -where - T: Borrow, -{ - fn sum(iter: I) -> Self - where - I: Iterator, - { - use group::Group; - iter.fold(SubgroupPoint::identity(), |acc, item| acc + item.borrow()) - } -} - -#[cfg(feature = "group")] -impl Mul<&Scalar> for &SubgroupPoint { - type Output = SubgroupPoint; - - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, scalar: &Scalar) -> SubgroupPoint { - SubgroupPoint(self.0 * scalar) - } -} - -#[cfg(feature = "group")] -define_mul_variants!(LHS = Scalar, RHS = SubgroupPoint, Output = SubgroupPoint); - -#[cfg(feature = "group")] -impl Mul<&SubgroupPoint> for &Scalar { - type Output = SubgroupPoint; - - /// Scalar multiplication: compute `scalar * self`. - /// - /// For scalar multiplication of a basepoint, - /// `EdwardsBasepointTable` is approximately 4x faster. - fn mul(self, point: &SubgroupPoint) -> SubgroupPoint { - point * self - } -} - -#[cfg(feature = "group")] -define_mul_variants!(LHS = SubgroupPoint, RHS = Scalar, Output = SubgroupPoint); - -#[cfg(feature = "group")] -impl MulAssign<&Scalar> for SubgroupPoint { - fn mul_assign(&mut self, scalar: &Scalar) { - self.0 *= scalar; - } -} - -#[cfg(feature = "group")] -define_mul_assign_variants!(LHS = SubgroupPoint, RHS = Scalar); - -#[cfg(feature = "group")] -impl ConstantTimeEq for SubgroupPoint { - fn ct_eq(&self, other: &SubgroupPoint) -> Choice { - self.0.ct_eq(&other.0) - } -} - -#[cfg(feature = "group")] -impl ConditionallySelectable for SubgroupPoint { - fn conditional_select(a: &SubgroupPoint, b: &SubgroupPoint, choice: Choice) -> SubgroupPoint { - SubgroupPoint(EdwardsPoint::conditional_select(&a.0, &b.0, choice)) - } -} - -#[cfg(all(feature = "group", feature = "zeroize"))] -impl Zeroize for SubgroupPoint { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - -#[cfg(feature = "group")] -impl group::Group for SubgroupPoint { - type Scalar = Scalar; - - fn try_from_rng(rng: &mut R) -> Result { - use group::ff::Field; - - // This will almost never loop, but `Group::random` is documented as returning a - // non-identity element. - let s = loop { - let s: Scalar = Field::try_from_rng(rng)?; - if !s.is_zero_vartime() { - break s; - } - }; - - // This gives an element of the prime-order subgroup. - Ok(Self::generator() * s) - } - - fn identity() -> Self { - SubgroupPoint(Identity::identity()) - } - - fn generator() -> Self { - SubgroupPoint(EdwardsPoint::generator()) - } - - fn is_identity(&self) -> Choice { - self.0.ct_eq(&Identity::identity()) - } - - fn double(&self) -> Self { - SubgroupPoint(self.0.double()) - } -} - -#[cfg(feature = "group")] -impl GroupEncoding for SubgroupPoint { - type Repr = ::Repr; - - fn from_bytes(bytes: &Self::Repr) -> CtOption { - EdwardsPoint::from_bytes(bytes).and_then(|p| p.into_subgroup()) - } - - fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { - EdwardsPoint::from_bytes_unchecked(bytes).and_then(|p| p.into_subgroup()) - } - - fn to_bytes(&self) -> Self::Repr { - self.0.compress().to_bytes() - } -} - -#[cfg(feature = "group")] -impl PrimeGroup for SubgroupPoint {} - -#[cfg(feature = "group")] -impl CofactorGroup for EdwardsPoint { - type Subgroup = SubgroupPoint; - - fn clear_cofactor(&self) -> Self::Subgroup { - SubgroupPoint(self.mul_by_cofactor()) - } - - fn into_subgroup(self) -> CtOption { - CtOption::new(SubgroupPoint(self), CofactorGroup::is_torsion_free(&self)) - } - - fn is_torsion_free(&self) -> Choice { - (self * constants::BASEPOINT_ORDER).ct_eq(&Self::identity()) - } -} - // ------------------------------------------------------------------------ // Tests // ------------------------------------------------------------------------ diff --git a/curve25519-dalek/src/ristretto.rs b/curve25519-dalek/src/ristretto.rs index c1037f6..a1a90a6 100644 --- a/curve25519-dalek/src/ristretto.rs +++ b/curve25519-dalek/src/ristretto.rs @@ -177,13 +177,6 @@ use digest::array::typenum::U64; use crate::constants; use crate::field::FieldElement; -#[cfg(feature = "group")] -use { - group::{GroupEncoding, cofactor::CofactorGroup, prime::PrimeGroup}, - rand_core::TryRng, - subtle::CtOption, -}; - #[cfg(feature = "rand_core")] use { core::convert::Infallible, @@ -1169,86 +1162,6 @@ impl Debug for RistrettoPoint { } } -// ------------------------------------------------------------------------ -// group traits -// ------------------------------------------------------------------------ - -// Use the full trait path to avoid Group::identity overlapping Identity::identity in the -// rest of the module (e.g. tests). -#[cfg(feature = "group")] -impl group::Group for RistrettoPoint { - type Scalar = Scalar; - - fn try_from_rng(rng: &mut R) -> Result { - // NOTE: this is duplicated due to different `rng` bounds - let mut uniform_bytes = [0u8; 64]; - rng.try_fill_bytes(&mut uniform_bytes)?; - Ok(RistrettoPoint::from_uniform_bytes(&uniform_bytes)) - } - - fn identity() -> Self { - Identity::identity() - } - - fn generator() -> Self { - constants::RISTRETTO_BASEPOINT_POINT - } - - fn is_identity(&self) -> Choice { - self.ct_eq(&Identity::identity()) - } - - fn double(&self) -> Self { - self + self - } -} - -#[cfg(feature = "group")] -impl GroupEncoding for RistrettoPoint { - type Repr = [u8; 32]; - - fn from_bytes(bytes: &Self::Repr) -> CtOption { - let (s_encoding_is_canonical, s_is_negative, s) = - decompress::step_1(&CompressedRistretto(*bytes)); - - let s_is_valid = s_encoding_is_canonical & !s_is_negative; - - let (ok, t_is_negative, y_is_zero, res) = decompress::step_2(s); - - CtOption::new(res, s_is_valid & ok & !t_is_negative & !y_is_zero) - } - - fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption { - // Just use the checked API; the checks we could skip aren't expensive. - Self::from_bytes(bytes) - } - - fn to_bytes(&self) -> Self::Repr { - self.compress().to_bytes() - } -} - -#[cfg(feature = "group")] -impl PrimeGroup for RistrettoPoint {} - -/// Ristretto has a cofactor of 1. -#[cfg(feature = "group")] -impl CofactorGroup for RistrettoPoint { - type Subgroup = Self; - - fn clear_cofactor(&self) -> Self::Subgroup { - *self - } - - fn into_subgroup(self) -> CtOption { - CtOption::new(self, Choice::from(1)) - } - - fn is_torsion_free(&self) -> Choice { - Choice::from(1) - } -} - // ------------------------------------------------------------------------ // Zeroize traits // ------------------------------------------------------------------------ @@ -1277,8 +1190,6 @@ mod test { use crate::edwards::CompressedEdwardsY; #[cfg(feature = "rand_core")] use getrandom::{SysRng, rand_core::UnwrapErr}; - #[cfg(feature = "group")] - use proptest::prelude::*; #[test] #[cfg(feature = "serde")] @@ -1492,57 +1403,6 @@ mod test { } } - #[test] - #[cfg(all(feature = "alloc", feature = "rand_core", feature = "group"))] - fn double_and_compress_1024_random_points() { - use group::Group; - let mut rng = SysRng; - - let mut points: Vec = (0..1024) - .map(|_| RistrettoPoint::try_from_rng(&mut rng).unwrap()) - .collect(); - points[500] = ::identity(); - - let compressed = RistrettoPoint::double_and_compress_batch(&points); - - for (P, P2_compressed) in points.iter().zip(compressed.iter()) { - assert_eq!(*P2_compressed, (P + P).compress()); - } - } - - #[cfg(feature = "group")] - proptest! { - #[test] - fn multiply_double_and_compress_random_points( - p1 in any::<[u8; 64]>(), - p2 in any::<[u8; 64]>(), - s1 in any::<[u8; 32]>(), - s2 in any::<[u8; 32]>(), - ) { - use group::Group; - - let scalars = [ - Scalar::from_bytes_mod_order(s1), - Scalar::ZERO, - Scalar::from_bytes_mod_order(s2), - ]; - - let points = [ - RistrettoPoint::from_uniform_bytes(&p1), - ::identity(), - RistrettoPoint::from_uniform_bytes(&p2), - ]; - - let multiplied_points: [_; 3] = - core::array::from_fn(|i| scalars[i].div_by_2() * points[i]); - let compressed = RistrettoPoint::double_and_compress_batch(&multiplied_points); - - for ((s, P), P2_compressed) in scalars.iter().zip(points).zip(compressed) { - prop_assert_eq!(P2_compressed, (s * P).compress()); - } - } - } - #[test] #[cfg(all(feature = "alloc", feature = "rand_core"))] fn vartime_precomputed_vs_nonprecomputed_multiscalar() { diff --git a/curve25519-dalek/src/scalar.rs b/curve25519-dalek/src/scalar.rs index 89a1745..f27cf9c 100644 --- a/curve25519-dalek/src/scalar.rs +++ b/curve25519-dalek/src/scalar.rs @@ -122,14 +122,6 @@ use core::ops::{Sub, SubAssign}; use cfg_if::cfg_if; -#[cfg(feature = "group")] -use group::ff::{Field, FromUniformBytes, PrimeField}; -#[cfg(feature = "group-bits")] -use group::ff::{FieldBits, PrimeFieldBits}; - -#[cfg(feature = "group")] -use rand_core::TryRng; - #[cfg(feature = "rand_core")] use rand_core::CryptoRng; @@ -1244,141 +1236,6 @@ impl UnpackedScalar { } } -#[cfg(feature = "group")] -impl Field for Scalar { - const ZERO: Self = Self::ZERO; - const ONE: Self = Self::ONE; - - fn try_from_rng(rng: &mut R) -> Result { - // NOTE: this is duplicated due to different `rng` bounds - let mut scalar_bytes = [0u8; 64]; - rng.try_fill_bytes(&mut scalar_bytes)?; - Ok(Self::from_bytes_mod_order_wide(&scalar_bytes)) - } - - fn square(&self) -> Self { - self * self - } - - fn double(&self) -> Self { - self + self - } - - fn invert(&self) -> CtOption { - CtOption::new(self.invert(), !self.is_zero()) - } - - fn sqrt_ratio(num: &Self, div: &Self) -> (Choice, Self) { - #[allow(unused_qualifications)] - group::ff::helpers::sqrt_ratio_generic(num, div) - } - - fn sqrt(&self) -> CtOption { - #[allow(unused_qualifications)] - group::ff::helpers::sqrt_tonelli_shanks( - self, - [ - 0xcb02_4c63_4b9e_ba7d, - 0x029b_df3b_d45e_f39a, - 0x0000_0000_0000_0000, - 0x0200_0000_0000_0000, - ], - ) - } -} - -#[cfg(feature = "group")] -impl PrimeField for Scalar { - type Repr = [u8; 32]; - - fn from_repr(repr: Self::Repr) -> CtOption { - Self::from_canonical_bytes(repr) - } - - fn from_repr_vartime(repr: Self::Repr) -> Option { - // Check that the high bit is not set - if (repr[31] >> 7) != 0u8 { - return None; - } - - let candidate = Scalar { bytes: repr }; - - if candidate == candidate.reduce() { - Some(candidate) - } else { - None - } - } - - fn to_repr(&self) -> Self::Repr { - self.to_bytes() - } - - fn is_odd(&self) -> Choice { - Choice::from(self.as_bytes()[0] & 1) - } - - const MODULUS: &'static str = - "0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"; - const NUM_BITS: u32 = 253; - const CAPACITY: u32 = 252; - - const TWO_INV: Self = Self { - bytes: [ - 0xf7, 0xe9, 0x7a, 0x2e, 0x8d, 0x31, 0x09, 0x2c, 0x6b, 0xce, 0x7b, 0x51, 0xef, 0x7c, - 0x6f, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, - ], - }; - const MULTIPLICATIVE_GENERATOR: Self = Self { - bytes: [ - 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ], - }; - const S: u32 = 2; - const ROOT_OF_UNITY: Self = Self { - bytes: [ - 0xd4, 0x07, 0xbe, 0xeb, 0xdf, 0x75, 0x87, 0xbe, 0xfe, 0x83, 0xce, 0x42, 0x53, 0x56, - 0xf0, 0x0e, 0x7a, 0xc2, 0xc1, 0xab, 0x60, 0x6d, 0x3d, 0x7d, 0xe7, 0x81, 0x79, 0xe0, - 0x10, 0x73, 0x4a, 0x09, - ], - }; - const ROOT_OF_UNITY_INV: Self = Self { - bytes: [ - 0x19, 0xcc, 0x37, 0x71, 0x3a, 0xed, 0x8a, 0x99, 0xd7, 0x18, 0x29, 0x60, 0x8b, 0xa3, - 0xee, 0x05, 0x86, 0x3d, 0x3e, 0x54, 0x9f, 0x92, 0xc2, 0x82, 0x18, 0x7e, 0x86, 0x1f, - 0xef, 0x8c, 0xb5, 0x06, - ], - }; - const DELTA: Self = Self { - bytes: [ - 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ], - }; -} - -#[cfg(feature = "group-bits")] -impl PrimeFieldBits for Scalar { - type ReprBits = [u8; 32]; - - fn to_le_bits(&self) -> FieldBits { - self.to_repr().into() - } - - fn char_le_bits() -> FieldBits { - constants::BASEPOINT_ORDER.to_bytes().into() - } -} - -#[cfg(feature = "group")] -impl FromUniformBytes<64> for Scalar { - fn from_uniform_bytes(bytes: &[u8; 64]) -> Self { - Scalar::from_bytes_mod_order_wide(bytes) - } -} - /// Read one or more u64s stored as little endian bytes. /// /// ## Panics @@ -2031,56 +1888,6 @@ pub(crate) mod test { assert_eq!(sx + s1, Scalar::from(x + 1)); } - #[cfg(feature = "group")] - #[test] - fn ff_constants() { - assert_eq!(Scalar::from(2u64) * Scalar::TWO_INV, Scalar::ONE); - - assert_eq!( - Scalar::ROOT_OF_UNITY * Scalar::ROOT_OF_UNITY_INV, - Scalar::ONE, - ); - - // ROOT_OF_UNITY^{2^s} mod m == 1 - assert_eq!( - Scalar::ROOT_OF_UNITY.pow(&[1u64 << Scalar::S, 0, 0, 0]), - Scalar::ONE, - ); - - // DELTA^{t} mod m == 1 - assert_eq!( - Scalar::DELTA.pow(&[ - 0x9604_98c6_973d_74fb, - 0x0537_be77_a8bd_e735, - 0x0000_0000_0000_0000, - 0x0400_0000_0000_0000, - ]), - Scalar::ONE, - ); - } - - #[cfg(feature = "group")] - #[test] - fn ff_impls() { - assert!(bool::from(Scalar::ZERO.is_even())); - assert!(bool::from(Scalar::ONE.is_odd())); - assert!(bool::from(Scalar::from(2u64).is_even())); - assert!(bool::from(Scalar::DELTA.is_even())); - - assert!(bool::from(Field::invert(&Scalar::ZERO).is_none())); - assert_eq!(Field::invert(&X).unwrap(), XINV); - - let x_sq = X.square(); - // We should get back either the positive or negative root. - assert!([X, -X].contains(&x_sq.sqrt().unwrap())); - - assert_eq!(Scalar::from_repr_vartime(X.to_repr()), Some(X)); - assert_eq!(Scalar::from_repr_vartime([0xff; 32]), None); - - assert_eq!(Scalar::from_repr(X.to_repr()).unwrap(), X); - assert!(bool::from(Scalar::from_repr([0xff; 32]).is_none())); - } - #[test] #[should_panic] fn test_read_le_u64_into_should_panic_on_bad_input() {