diff --git a/src/algebra/m231.rs b/src/algebra/m231.rs index af93d47..be9e690 100644 --- a/src/algebra/m231.rs +++ b/src/algebra/m231.rs @@ -4,6 +4,7 @@ use num_traits::identities::{One, Zero}; use rand::distributions::{Distribution, Standard}; use rand::Rng; use serde::{Deserialize, Serialize}; +use std::convert::TryFrom; use std::fmt; use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign}; @@ -106,6 +107,42 @@ impl From for Mod231 { } } +impl TryFrom for Mod231 { + type Error = &'static str; + + fn try_from(x: i32) -> Result { + let y: u32 = if x < 0 { + let y = x + MODULUSI32; + if y < 0 { + return Err("i32 out of range for Mod231"); + } else { + y as u32 + } + } else { + if x < MODULUSI32 { + x as u32 + } else { + return Err("i32 out of range for Mod231"); + } + }; + + Ok(Mod231(normalize(y))) + } +} + +impl Into for Mod231 { + fn into(self) -> i32 { + let y: u32 = self.0; + let max = MODULUS / 2; + + if y > max { + (y as i32) - MODULUSI32 + } else { + y as i32 + } + } +} + impl Add for Mod231 { type Output = Self; @@ -284,4 +321,10 @@ mod tests { } } } + + #[quickcheck] + fn prop_roundtrip_i32(x: Mod231) -> Result { + let y: i32 = x.into(); + Mod231::try_from(y).map(|z| z == x) + } } diff --git a/src/enc.rs b/src/enc.rs index f186b5f..794051e 100644 --- a/src/enc.rs +++ b/src/enc.rs @@ -5,8 +5,9 @@ use nalgebra::Matrix3; use num_traits::Zero; use rand::prelude::*; use serde::{Deserialize, Serialize}; +use std::convert::TryFrom; use std::fmt; -use std::ops::{Add, AddAssign, Mul, MulAssign}; +use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// Wrapper type for lifting `u32` type to FHE compatible /// form @@ -32,6 +33,21 @@ impl Enc { let dec = key_pair.backwards * self.inner * key_pair.forwards; dec[0].w.0 } + + #[inline] + fn enc_i32(key_pair: &KeyPair, value: i32) -> Option { + let m = Mod231::try_from(value).ok()?; + let enc: Matrix3<_> = Q231::from(m).into(); + let inner = key_pair.forwards * enc * key_pair.backwards; + + Some(Self { inner }) + } + + #[inline] + fn dec_i32(&self, key_pair: &KeyPair) -> i32 { + let dec = key_pair.backwards * self.inner * key_pair.forwards; + Mod231::into(dec[0].w) + } } impl fmt::Display for Enc { @@ -77,6 +93,35 @@ impl MulAssign for Enc { } } +impl Sub for Enc { + type Output = Self; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + Self { + inner: self.inner - rhs.inner, + } + } +} + +impl SubAssign for Enc { + #[inline] + fn sub_assign(&mut self, rhs: Self) { + *self = *self - rhs + } +} + +impl Neg for Enc { + type Output = Self; + + #[inline] + fn neg(self) -> Self::Output { + Self { + inner: self.inner.neg(), + } + } +} + /// Type representing a key pair which can be used for encrypting /// and decrypting data #[derive(Debug, Serialize, Deserialize)]