From 00ffb78923789e979b2c5f913f72978368fc8286 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 23 Apr 2023 20:26:00 +0300 Subject: [PATCH 01/11] Defined AsNaturalNumber and AsFiniteFieldElement traits + sample implementation of encrypt/decrypt --- Cargo.toml | 1 + src/ff_natural.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 77 insertions(+) create mode 100644 src/ff_natural.rs diff --git a/Cargo.toml b/Cargo.toml index d8719198a..fe67daf0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ rand_core = { version = "0.6.4", optional = true } rlp = { version = "0.5", optional = true, default-features = false } serdect = { version = "0.2", optional = true, default-features = false } zeroize = { version = "1", optional = true, default-features = false } +num-traits = "0.2" [dev-dependencies] bincode = "1" diff --git a/src/ff_natural.rs b/src/ff_natural.rs new file mode 100644 index 000000000..4bba5b781 --- /dev/null +++ b/src/ff_natural.rs @@ -0,0 +1,75 @@ +use core::num::Wrapping; +use num_traits::{Num, Pow}; +use crate::modular::runtime_mod::{DynResidue, DynResidueParams}; +use crate::{Uint}; + +//// traits +// TODO: should I use crate::Pow or num_traits::Pow? +// I went with num_traits::Pow for consistency (because we also implement Num) +pub trait AsNaturalNumber { + fn as_natural_number(&self) -> N; + // TODO: maybe can return AsFiniteFieldElement, so that we can transition 2048->4096 here and do wide mul? + // Or: we can have Mul return Output instead? +} + +pub trait AsFiniteFieldElement + Clone> { + fn as_finite_field_element(&self, p: &Self) -> F; +} + +//// Impl +// impl AsNaturalNumber>> for DynResidue { +// fn as_natural_number(&self) -> Wrapping> { +// Wrapping(self.retrieve()) +// } +// } +// +// impl AsFiniteFieldElement> for Wrapping> { +// fn as_finite_field_element(&self, p: &Self) -> DynResidue { +// let ff_params = DynResidueParams::new(&p.0); +// DynResidue::new(&self.0, ff_params) +// } +// } +// +// impl AsNaturalNumber> for DynResidue { +// fn as_natural_number(&self) -> Uint { +// self.retrieve() +// } +// } +// +// impl AsFiniteFieldElement> for Uint { +// fn as_finite_field_element(&self, p: &Self) -> DynResidue { +// let ff_params = DynResidueParams::new(p); +// DynResidue::new(self, ff_params) +// } +// } + +pub fn encrypt(encryption_key: &N, plaintext: &N, randomness: &N) -> N +where + N: AsFiniteFieldElement + Clone, + F: AsNaturalNumber + Pow + Clone +{ + let n: N = encryption_key.clone(); + let n2 = n.clone() * n; // wrapping mul (N should be < 2048, T should be U4096); + let n = encryption_key.as_finite_field_element(&n2); + let m = plaintext.as_finite_field_element(&n2); + let r = randomness.as_finite_field_element(&n2); + let one = N::one().as_finite_field_element(&n2); + + ((m * n.clone() + one) * (r.pow(n))).as_natural_number() +} + +pub fn decrypt(decryption_key: &N, encryption_key: &N, ciphertext: &N) -> N +where + N: AsFiniteFieldElement + Clone, + F: AsNaturalNumber + Pow + Clone +{ + let n: N = encryption_key.clone(); + let n2 = n.clone() * n.clone(); // wrapping mul (N should be < 2048, T should be U4096); + let d = decryption_key.as_finite_field_element(&n2); + let c = ciphertext.as_finite_field_element(&n2); + let one = N::one().as_finite_field_element(&n2); + + ((c.pow(d) - one).as_natural_number() // $ c^d - 1 mod N^2 $ + / n.clone()) // (c^d - 1 mod N^2) / n (division in N [Naturals]) + % n // Take mod N +} diff --git a/src/lib.rs b/src/lib.rs index 0a790c8dc..5696f080d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,6 +166,7 @@ mod non_zero; mod traits; mod uint; mod wrapping; +mod ff_natural; pub use crate::{ checked::Checked, From 629c7c1a339bdbdb22fe8bd338a4112b2f060a50 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 19:13:07 +0300 Subject: [PATCH 02/11] Implemented num-traits and AsNatrualNumber and AsRingElement (partial implementation for sketch and discussion only) --- rust-toolchain | 1 + src/ff_natural.rs | 75 ------------------------------- src/lib.rs | 1 - src/traits.rs | 8 ++++ src/uint.rs | 2 + src/uint/num.rs | 96 ++++++++++++++++++++++++++++++++++++++++ src/uint/ring_natural.rs | 56 +++++++++++++++++++++++ src/wrapping.rs | 2 + 8 files changed, 165 insertions(+), 76 deletions(-) create mode 100644 rust-toolchain delete mode 100644 src/ff_natural.rs create mode 100644 src/uint/num.rs create mode 100644 src/uint/ring_natural.rs diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..07ade694b --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly \ No newline at end of file diff --git a/src/ff_natural.rs b/src/ff_natural.rs deleted file mode 100644 index 4bba5b781..000000000 --- a/src/ff_natural.rs +++ /dev/null @@ -1,75 +0,0 @@ -use core::num::Wrapping; -use num_traits::{Num, Pow}; -use crate::modular::runtime_mod::{DynResidue, DynResidueParams}; -use crate::{Uint}; - -//// traits -// TODO: should I use crate::Pow or num_traits::Pow? -// I went with num_traits::Pow for consistency (because we also implement Num) -pub trait AsNaturalNumber { - fn as_natural_number(&self) -> N; - // TODO: maybe can return AsFiniteFieldElement, so that we can transition 2048->4096 here and do wide mul? - // Or: we can have Mul return Output instead? -} - -pub trait AsFiniteFieldElement + Clone> { - fn as_finite_field_element(&self, p: &Self) -> F; -} - -//// Impl -// impl AsNaturalNumber>> for DynResidue { -// fn as_natural_number(&self) -> Wrapping> { -// Wrapping(self.retrieve()) -// } -// } -// -// impl AsFiniteFieldElement> for Wrapping> { -// fn as_finite_field_element(&self, p: &Self) -> DynResidue { -// let ff_params = DynResidueParams::new(&p.0); -// DynResidue::new(&self.0, ff_params) -// } -// } -// -// impl AsNaturalNumber> for DynResidue { -// fn as_natural_number(&self) -> Uint { -// self.retrieve() -// } -// } -// -// impl AsFiniteFieldElement> for Uint { -// fn as_finite_field_element(&self, p: &Self) -> DynResidue { -// let ff_params = DynResidueParams::new(p); -// DynResidue::new(self, ff_params) -// } -// } - -pub fn encrypt(encryption_key: &N, plaintext: &N, randomness: &N) -> N -where - N: AsFiniteFieldElement + Clone, - F: AsNaturalNumber + Pow + Clone -{ - let n: N = encryption_key.clone(); - let n2 = n.clone() * n; // wrapping mul (N should be < 2048, T should be U4096); - let n = encryption_key.as_finite_field_element(&n2); - let m = plaintext.as_finite_field_element(&n2); - let r = randomness.as_finite_field_element(&n2); - let one = N::one().as_finite_field_element(&n2); - - ((m * n.clone() + one) * (r.pow(n))).as_natural_number() -} - -pub fn decrypt(decryption_key: &N, encryption_key: &N, ciphertext: &N) -> N -where - N: AsFiniteFieldElement + Clone, - F: AsNaturalNumber + Pow + Clone -{ - let n: N = encryption_key.clone(); - let n2 = n.clone() * n.clone(); // wrapping mul (N should be < 2048, T should be U4096); - let d = decryption_key.as_finite_field_element(&n2); - let c = ciphertext.as_finite_field_element(&n2); - let one = N::one().as_finite_field_element(&n2); - - ((c.pow(d) - one).as_natural_number() // $ c^d - 1 mod N^2 $ - / n.clone()) // (c^d - 1 mod N^2) / n (division in N [Naturals]) - % n // Take mod N -} diff --git a/src/lib.rs b/src/lib.rs index 5696f080d..0a790c8dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -166,7 +166,6 @@ mod non_zero; mod traits; mod uint; mod wrapping; -mod ff_natural; pub use crate::{ checked::Checked, diff --git a/src/traits.rs b/src/traits.rs index da9b9b646..e7e95987f 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -88,6 +88,14 @@ pub trait Zero: ConstantTimeEq + Sized { } } +pub trait AsNaturalNumber { + fn as_natural_number(&self) -> N; +} + +pub trait AsRingElement + Clone> { + fn as_ring_element(&self, p: &Self) -> F; +} + /// Random number generation support. #[cfg(feature = "rand_core")] pub trait Random: Sized { diff --git a/src/uint.rs b/src/uint.rs index 4dd22fa61..b871483e5 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -43,6 +43,8 @@ mod array; #[cfg(feature = "rand_core")] mod rand; +mod num; +mod ring_natural; use crate::{Bounded, Concat, Encoding, Integer, Limb, Split, Word, Zero}; use core::fmt; diff --git a/src/uint/num.rs b/src/uint/num.rs new file mode 100644 index 000000000..b45648cde --- /dev/null +++ b/src/uint/num.rs @@ -0,0 +1,96 @@ +use crate::{NonZero, Uint, Wrapping, Zero}; +use num_traits::{Num, NumOps}; +use core::ops::{Add, Div, Mul, Rem, Sub}; +use crate::modular::runtime_mod::DynResidue; + +/* Wrapping> */ +impl num_traits::Zero for Wrapping> { + fn zero() -> Self { + Self::ZERO + } + + // TODO: if I perform this equality in this manner, do I lose constant-timeness? Can I do it another way? + fn is_zero(&self) -> bool { + self == &Self::ZERO + } +} + +impl num_traits::One for Wrapping> { + fn one() -> Self { + Wrapping(Uint::::ONE) + } +} + +impl Div>> for Wrapping> { + type Output = Wrapping>; + + // TODO: this panics in case of division by zero, is this the intended behavior? (can't see any other option that would comply with the trait) + fn div(self, rhs: Wrapping>) -> Self::Output { + self / NonZero::new(rhs.0).unwrap() + } +} + +impl Rem>> for Wrapping> { + type Output = Wrapping>; + + // TODO: this panics in case of division by zero, is this the intended behavior? (can't see any other option that would comply with the trait) + fn rem(self, rhs: Wrapping>) -> Self::Output { + self % NonZero::new(rhs.0).unwrap() + } +} + +impl Num for Wrapping> { + type FromStrRadixErr = (); + + fn from_str_radix(str: &str, radix: u32) -> Result { + todo!() + } +} + +/* DynResidue */ +impl num_traits::Zero for DynResidue { + // TODO: I don't have access to self here, and thus no access to params(). + // So how can I know the modulo, so to construct a valid zero value for? + fn zero() -> Self { + todo!() + } + + // TODO: if I perform this equality in this manner, do I lose constant-timeness? Can I do it another way? + fn is_zero(&self) -> bool { + todo!() + } +} + +impl num_traits::One for DynResidue { + // TODO: I don't have access to self here, and thus no access to params(). + // So how can I know the modulo, so to construct a valid one value for? + fn one() -> Self { + todo!() + } +} + +impl Div> for DynResidue { + type Output = DynResidue; + + // TODO: how to handle the case in which the element is non-invertible? + fn div(self, rhs: DynResidue) -> Self::Output { + self * (rhs.invert().0) + } +} + +impl Rem> for DynResidue { + type Output = DynResidue; + + // TODO: I'm not sure what it means to perform Rem for a ring element.. + fn rem(self, rhs: DynResidue) -> Self::Output { + todo!() + } +} + +impl Num for DynResidue { + type FromStrRadixErr = (); + + fn from_str_radix(str: &str, radix: u32) -> Result { + todo!() + } +} diff --git a/src/uint/ring_natural.rs b/src/uint/ring_natural.rs new file mode 100644 index 000000000..a7bc28afc --- /dev/null +++ b/src/uint/ring_natural.rs @@ -0,0 +1,56 @@ +use crate::Wrapping; +use crate::modular::runtime_mod::{DynResidue, DynResidueParams}; +use crate::{AsNaturalNumber, AsRingElement, Uint}; + +impl num_traits::Pow> for DynResidue{ + type Output = DynResidue; + + fn pow(self, rhs: DynResidue) -> Self::Output { + // self.pow(&rhs.retrieve()) // TODO: can't, because these are the same name + self.pow_bounded_exp(&rhs.retrieve(), Uint::::BITS) + } +} + +impl AsNaturalNumber>> for DynResidue { + fn as_natural_number(&self) -> Wrapping> { + Wrapping(self.retrieve()) + } +} + +impl AsRingElement> for Wrapping> { + fn as_ring_element(&self, p: &Self) -> DynResidue { + let ring_params = DynResidueParams::new(&p.0); + DynResidue::new(&self.0, ring_params) + } +} + +pub fn encrypt(encryption_key: &N, plaintext: &N, randomness: &N) -> N + where + N: AsRingElement + Clone, + F: AsNaturalNumber + num_traits::Pow + Clone +{ + let n: N = encryption_key.clone(); + let n2 = n.clone() * n; // wrapping mul (N should be < 2048, T should be U4096); + let n = encryption_key.as_ring_element(&n2); + let m = plaintext.as_ring_element(&n2); + let r = randomness.as_ring_element(&n2); + let one = N::one().as_ring_element(&n2); + + ((m * n.clone() + one) * (r.pow(n))).as_natural_number() +} + +pub fn decrypt(decryption_key: &N, encryption_key: &N, ciphertext: &N) -> N + where + N: AsRingElement + Clone, + F: AsNaturalNumber + num_traits::Pow + Clone +{ + let n: N = encryption_key.clone(); + let n2 = n.clone() * n.clone(); // wrapping mul (N should be < 2048, T should be U4096); + let d = decryption_key.as_ring_element(&n2); + let c = ciphertext.as_ring_element(&n2); + let one = N::one().as_ring_element(&n2); + + ((c.pow(d) - one).as_natural_number() // $ c^d - 1 mod N^2 $ + / n.clone()) // (c^d - 1 mod N^2) / n (division in N [Naturals]) + % n // Take mod N +} diff --git a/src/wrapping.rs b/src/wrapping.rs index 77e1b78f8..5ce26b4b6 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -2,7 +2,9 @@ use crate::Zero; use core::fmt; +use core::ops::{Add, Div, Mul, Rem, Sub}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; +use num_traits::{Num, NumOps, One}; #[cfg(feature = "rand_core")] use {crate::Random, rand_core::CryptoRngCore}; From 164ae460cc09d394c5c7c49b4b2dbc5492c506d3 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 19:13:55 +0300 Subject: [PATCH 03/11] question --- src/uint/num.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/uint/num.rs b/src/uint/num.rs index b45648cde..8cc54b75d 100644 --- a/src/uint/num.rs +++ b/src/uint/num.rs @@ -42,6 +42,7 @@ impl Rem>> for Wrapping> { impl Num for Wrapping> { type FromStrRadixErr = (); + // TODO: what's the best way to do this? fn from_str_radix(str: &str, radix: u32) -> Result { todo!() } @@ -90,6 +91,7 @@ impl Rem> for DynResidue { impl Num for DynResidue { type FromStrRadixErr = (); + // TODO: what's the best way to do this? fn from_str_radix(str: &str, radix: u32) -> Result { todo!() } From 57cab5c5420bfa3b26d3c640900152768f7835e6 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 19:25:15 +0300 Subject: [PATCH 04/11] undo changes --- src/wrapping.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wrapping.rs b/src/wrapping.rs index 5ce26b4b6..77e1b78f8 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -2,9 +2,7 @@ use crate::Zero; use core::fmt; -use core::ops::{Add, Div, Mul, Rem, Sub}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; -use num_traits::{Num, NumOps, One}; #[cfg(feature = "rand_core")] use {crate::Random, rand_core::CryptoRngCore}; From 43e079f1b883f12b6b46c9b0f9acfe440baecff7 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 19:43:32 +0300 Subject: [PATCH 05/11] undo changes --- src/uint/ring_natural.rs | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/uint/ring_natural.rs b/src/uint/ring_natural.rs index a7bc28afc..2c44b7aaf 100644 --- a/src/uint/ring_natural.rs +++ b/src/uint/ring_natural.rs @@ -23,34 +23,3 @@ impl AsRingElement> for Wrapping(encryption_key: &N, plaintext: &N, randomness: &N) -> N - where - N: AsRingElement + Clone, - F: AsNaturalNumber + num_traits::Pow + Clone -{ - let n: N = encryption_key.clone(); - let n2 = n.clone() * n; // wrapping mul (N should be < 2048, T should be U4096); - let n = encryption_key.as_ring_element(&n2); - let m = plaintext.as_ring_element(&n2); - let r = randomness.as_ring_element(&n2); - let one = N::one().as_ring_element(&n2); - - ((m * n.clone() + one) * (r.pow(n))).as_natural_number() -} - -pub fn decrypt(decryption_key: &N, encryption_key: &N, ciphertext: &N) -> N - where - N: AsRingElement + Clone, - F: AsNaturalNumber + num_traits::Pow + Clone -{ - let n: N = encryption_key.clone(); - let n2 = n.clone() * n.clone(); // wrapping mul (N should be < 2048, T should be U4096); - let d = decryption_key.as_ring_element(&n2); - let c = ciphertext.as_ring_element(&n2); - let one = N::one().as_ring_element(&n2); - - ((c.pow(d) - one).as_natural_number() // $ c^d - 1 mod N^2 $ - / n.clone()) // (c^d - 1 mod N^2) / n (division in N [Naturals]) - % n // Take mod N -} From fcfe2812e3f0d45e580a9cc020d6eb2ca2afb860 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 22:49:29 +0300 Subject: [PATCH 06/11] Update Cargo.toml Co-authored-by: Tony Arcieri --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fe67daf0b..56105c9cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ rand_core = { version = "0.6.4", optional = true } rlp = { version = "0.5", optional = true, default-features = false } serdect = { version = "0.2", optional = true, default-features = false } zeroize = { version = "1", optional = true, default-features = false } -num-traits = "0.2" +num-traits = { version = "0.2", optional = true } [dev-dependencies] bincode = "1" From cae3a2973cbbbcb7ce9b586910665436f30ae463 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Mon, 24 Apr 2023 22:52:59 +0300 Subject: [PATCH 07/11] Delete rust-toolchain --- rust-toolchain | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rust-toolchain diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 07ade694b..000000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly \ No newline at end of file From 629356f5c1a2590da687e5f40a14ab50359e0925 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 30 Apr 2023 11:33:40 +0300 Subject: [PATCH 08/11] removed non-num changes --- src/traits.rs | 8 -------- src/uint.rs | 1 - src/uint/ring_natural.rs | 25 ------------------------- 3 files changed, 34 deletions(-) delete mode 100644 src/uint/ring_natural.rs diff --git a/src/traits.rs b/src/traits.rs index e7e95987f..da9b9b646 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -88,14 +88,6 @@ pub trait Zero: ConstantTimeEq + Sized { } } -pub trait AsNaturalNumber { - fn as_natural_number(&self) -> N; -} - -pub trait AsRingElement + Clone> { - fn as_ring_element(&self, p: &Self) -> F; -} - /// Random number generation support. #[cfg(feature = "rand_core")] pub trait Random: Sized { diff --git a/src/uint.rs b/src/uint.rs index b871483e5..ac11226a5 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -44,7 +44,6 @@ mod array; #[cfg(feature = "rand_core")] mod rand; mod num; -mod ring_natural; use crate::{Bounded, Concat, Encoding, Integer, Limb, Split, Word, Zero}; use core::fmt; diff --git a/src/uint/ring_natural.rs b/src/uint/ring_natural.rs deleted file mode 100644 index 2c44b7aaf..000000000 --- a/src/uint/ring_natural.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::Wrapping; -use crate::modular::runtime_mod::{DynResidue, DynResidueParams}; -use crate::{AsNaturalNumber, AsRingElement, Uint}; - -impl num_traits::Pow> for DynResidue{ - type Output = DynResidue; - - fn pow(self, rhs: DynResidue) -> Self::Output { - // self.pow(&rhs.retrieve()) // TODO: can't, because these are the same name - self.pow_bounded_exp(&rhs.retrieve(), Uint::::BITS) - } -} - -impl AsNaturalNumber>> for DynResidue { - fn as_natural_number(&self) -> Wrapping> { - Wrapping(self.retrieve()) - } -} - -impl AsRingElement> for Wrapping> { - fn as_ring_element(&self, p: &Self) -> DynResidue { - let ring_params = DynResidueParams::new(&p.0); - DynResidue::new(&self.0, ring_params) - } -} From cc6278445b61672510e7bc67a851b64c332c69b2 Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 30 Apr 2023 12:47:32 +0300 Subject: [PATCH 09/11] All implemented except for from_str_radix --- rust-toolchain | 1 + src/uint.rs | 1 - src/uint/num.rs | 98 ------------------------------------------------- src/wrapping.rs | 87 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 99 deletions(-) create mode 100644 rust-toolchain delete mode 100644 src/uint/num.rs diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..07ade694b --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly \ No newline at end of file diff --git a/src/uint.rs b/src/uint.rs index ac11226a5..4dd22fa61 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -43,7 +43,6 @@ mod array; #[cfg(feature = "rand_core")] mod rand; -mod num; use crate::{Bounded, Concat, Encoding, Integer, Limb, Split, Word, Zero}; use core::fmt; diff --git a/src/uint/num.rs b/src/uint/num.rs deleted file mode 100644 index 8cc54b75d..000000000 --- a/src/uint/num.rs +++ /dev/null @@ -1,98 +0,0 @@ -use crate::{NonZero, Uint, Wrapping, Zero}; -use num_traits::{Num, NumOps}; -use core::ops::{Add, Div, Mul, Rem, Sub}; -use crate::modular::runtime_mod::DynResidue; - -/* Wrapping> */ -impl num_traits::Zero for Wrapping> { - fn zero() -> Self { - Self::ZERO - } - - // TODO: if I perform this equality in this manner, do I lose constant-timeness? Can I do it another way? - fn is_zero(&self) -> bool { - self == &Self::ZERO - } -} - -impl num_traits::One for Wrapping> { - fn one() -> Self { - Wrapping(Uint::::ONE) - } -} - -impl Div>> for Wrapping> { - type Output = Wrapping>; - - // TODO: this panics in case of division by zero, is this the intended behavior? (can't see any other option that would comply with the trait) - fn div(self, rhs: Wrapping>) -> Self::Output { - self / NonZero::new(rhs.0).unwrap() - } -} - -impl Rem>> for Wrapping> { - type Output = Wrapping>; - - // TODO: this panics in case of division by zero, is this the intended behavior? (can't see any other option that would comply with the trait) - fn rem(self, rhs: Wrapping>) -> Self::Output { - self % NonZero::new(rhs.0).unwrap() - } -} - -impl Num for Wrapping> { - type FromStrRadixErr = (); - - // TODO: what's the best way to do this? - fn from_str_radix(str: &str, radix: u32) -> Result { - todo!() - } -} - -/* DynResidue */ -impl num_traits::Zero for DynResidue { - // TODO: I don't have access to self here, and thus no access to params(). - // So how can I know the modulo, so to construct a valid zero value for? - fn zero() -> Self { - todo!() - } - - // TODO: if I perform this equality in this manner, do I lose constant-timeness? Can I do it another way? - fn is_zero(&self) -> bool { - todo!() - } -} - -impl num_traits::One for DynResidue { - // TODO: I don't have access to self here, and thus no access to params(). - // So how can I know the modulo, so to construct a valid one value for? - fn one() -> Self { - todo!() - } -} - -impl Div> for DynResidue { - type Output = DynResidue; - - // TODO: how to handle the case in which the element is non-invertible? - fn div(self, rhs: DynResidue) -> Self::Output { - self * (rhs.invert().0) - } -} - -impl Rem> for DynResidue { - type Output = DynResidue; - - // TODO: I'm not sure what it means to perform Rem for a ring element.. - fn rem(self, rhs: DynResidue) -> Self::Output { - todo!() - } -} - -impl Num for DynResidue { - type FromStrRadixErr = (); - - // TODO: what's the best way to do this? - fn from_str_radix(str: &str, radix: u32) -> Result { - todo!() - } -} diff --git a/src/wrapping.rs b/src/wrapping.rs index 77e1b78f8..50c4c12fb 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -4,6 +4,13 @@ use crate::Zero; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; +#[cfg(feature = "num-traits")] +use num_traits::{Num}; +#[cfg(feature = "num-traits")] +use core::ops::{Div, Rem, Mul, Add, Sub}; +#[cfg(feature = "num-traits")] +use crate::{Integer, NonZero}; + #[cfg(feature = "rand_core")] use {crate::Random, rand_core::CryptoRngCore}; @@ -63,6 +70,68 @@ impl ConstantTimeEq for Wrapping { } } +#[cfg(feature = "num-traits")] +impl num_traits::Zero for Wrapping + where Wrapping: + Add, Output = Wrapping> + + PartialEq> +{ + fn zero() -> Self { + Self::ZERO + } + + fn is_zero(&self) -> bool { self == &Self::ZERO } +} + +#[cfg(feature = "num-traits")] +impl num_traits::One for Wrapping + where Wrapping: + Add, Output = Wrapping> + + Mul, Output = Wrapping> +{ + fn one() -> Self { + Wrapping(T::ONE) + } +} + +#[cfg(feature = "num-traits")] +impl Div> for Wrapping + where Wrapping: Div, Output = Wrapping> +{ + type Output = Wrapping; + + fn div(self, rhs: Wrapping) -> Self::Output { + self / NonZero::new(rhs.0).unwrap() + } +} + +#[cfg(feature = "num-traits")] +impl Rem> for Wrapping + where Wrapping: Rem, Output = Wrapping> +{ + type Output = Wrapping; + + fn rem(self, rhs: Wrapping) -> Self::Output { + self % NonZero::new(rhs.0).unwrap() + } +} + +#[cfg(feature = "num-traits")] +impl Num for Wrapping + where Wrapping: + Add, Output = Wrapping> + + Sub, Output = Wrapping> + + Mul, Output = Wrapping> + + Div, Output = Wrapping> + + Rem, Output = Wrapping> +{ + type FromStrRadixErr = (); + + fn from_str_radix(str: &str, radix: u32) -> Result { + todo!() + } +} + #[cfg(feature = "rand_core")] impl Random for Wrapping { fn random(rng: &mut impl CryptoRngCore) -> Self { @@ -90,6 +159,24 @@ impl Serialize for Wrapping { } } +#[cfg(all(test, feature = "num-traits"))] +mod tests { + use num_traits::{Num, NumOps, Zero, One}; + use core::ops::{Div, Rem, Mul, Add, Sub}; + use crate::{Integer, NonZero}; + + use crate::{Wrapping, U64}; + + fn assures_num(x: T) {} + + #[test] + fn num_traits() { + const TEST: Wrapping = Wrapping(U64::from_u64(0x0011223344556677)); + + assures_num(TEST) + } +} + #[cfg(all(test, feature = "serde"))] mod tests { use crate::{Wrapping, U64}; From 2d2486402a358a115ed27e2e7810b4e9bc2df5ef Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 30 Apr 2023 12:51:19 +0300 Subject: [PATCH 10/11] deleted rust-toolchain --- rust-toolchain | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rust-toolchain diff --git a/rust-toolchain b/rust-toolchain deleted file mode 100644 index 07ade694b..000000000 --- a/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly \ No newline at end of file From dadbee943e1e02e2eaaf4b825d22b314abc63b1f Mon Sep 17 00:00:00 2001 From: Yehonatan Cohen Scaly Date: Sun, 30 Apr 2023 13:04:54 +0300 Subject: [PATCH 11/11] fmt --- src/wrapping.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/wrapping.rs b/src/wrapping.rs index 50c4c12fb..f97e9ce1d 100644 --- a/src/wrapping.rs +++ b/src/wrapping.rs @@ -5,11 +5,11 @@ use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; #[cfg(feature = "num-traits")] -use num_traits::{Num}; +use crate::{Integer, NonZero}; #[cfg(feature = "num-traits")] -use core::ops::{Div, Rem, Mul, Add, Sub}; +use core::ops::{Add, Div, Mul, Rem, Sub}; #[cfg(feature = "num-traits")] -use crate::{Integer, NonZero}; +use num_traits::Num; #[cfg(feature = "rand_core")] use {crate::Random, rand_core::CryptoRngCore}; @@ -72,22 +72,22 @@ impl ConstantTimeEq for Wrapping { #[cfg(feature = "num-traits")] impl num_traits::Zero for Wrapping - where Wrapping: - Add, Output = Wrapping> - + PartialEq> +where + Wrapping: Add, Output = Wrapping> + PartialEq>, { fn zero() -> Self { Self::ZERO } - fn is_zero(&self) -> bool { self == &Self::ZERO } + fn is_zero(&self) -> bool { + self == &Self::ZERO + } } #[cfg(feature = "num-traits")] impl num_traits::One for Wrapping - where Wrapping: - Add, Output = Wrapping> - + Mul, Output = Wrapping> +where + Wrapping: Add, Output = Wrapping> + Mul, Output = Wrapping>, { fn one() -> Self { Wrapping(T::ONE) @@ -96,7 +96,8 @@ impl num_traits::One for Wrapping #[cfg(feature = "num-traits")] impl Div> for Wrapping - where Wrapping: Div, Output = Wrapping> +where + Wrapping: Div, Output = Wrapping>, { type Output = Wrapping; @@ -107,7 +108,8 @@ impl Div> for Wrapping #[cfg(feature = "num-traits")] impl Rem> for Wrapping - where Wrapping: Rem, Output = Wrapping> +where + Wrapping: Rem, Output = Wrapping>, { type Output = Wrapping; @@ -118,12 +120,12 @@ impl Rem> for Wrapping #[cfg(feature = "num-traits")] impl Num for Wrapping - where Wrapping: - Add, Output = Wrapping> - + Sub, Output = Wrapping> - + Mul, Output = Wrapping> - + Div, Output = Wrapping> - + Rem, Output = Wrapping> +where + Wrapping: Add, Output = Wrapping> + + Sub, Output = Wrapping> + + Mul, Output = Wrapping> + + Div, Output = Wrapping> + + Rem, Output = Wrapping>, { type FromStrRadixErr = (); @@ -161,9 +163,9 @@ impl Serialize for Wrapping { #[cfg(all(test, feature = "num-traits"))] mod tests { - use num_traits::{Num, NumOps, Zero, One}; - use core::ops::{Div, Rem, Mul, Add, Sub}; use crate::{Integer, NonZero}; + use core::ops::{Add, Div, Mul, Rem, Sub}; + use num_traits::{Num, NumOps, One, Zero}; use crate::{Wrapping, U64};