Skip to content

Commit e4aa6b1

Browse files
committed
feat(derive): derive is now a feature
1 parent d8f1740 commit e4aa6b1

File tree

13 files changed

+204
-68
lines changed

13 files changed

+204
-68
lines changed

.github/workflows/rust.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ jobs:
2525
override: true
2626

2727
- name: Build
28-
run: cargo build --lib --verbose
28+
run: cargo build --lib --all-features --verbose
2929

3030
- name: Run basic tests
31-
run: cargo test --verbose
31+
run: cargo test --all-features --verbose
3232

3333
- name: Run a basic example
34-
run: cargo run --example simple_struct
34+
run: cargo run --example simple_struct --all-features
3535

3636
clippy-fmt:
3737
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 17 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repository = "https://github.com/mathisbot/homomorph-rust"
99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

1111
[dependencies]
12-
bincode = { version = "2.0.0-rc.3", default-features = false, features = ["alloc", "derive"] }
12+
bincode = { git = "https://github.com/bincode-org/bincode.git", branch = "trunk", default-features = false, features = ["alloc"] }
1313
getrandom = { version = "0.2.15", default-features = false, features = ["rdrand"] }
1414

1515
[dev-dependencies]
@@ -19,11 +19,21 @@ rand = "0.8.5"
1919
[features]
2020
default = []
2121
custom_rand = ["getrandom/custom"]
22+
derive = ["bincode/derive"]
2223

2324
[profile.release]
2425
codegen-units = 1
2526
lto = "thin"
2627

2728
[[bench]]
2829
name = "u32"
29-
harness = false
30+
harness = false
31+
32+
[[example]]
33+
name = "simple_struct"
34+
path = "examples/simple_struct.rs"
35+
required-features = ["derive"]
36+
[[example]]
37+
name = "unbalanced_struct"
38+
path = "examples/unbalanced_struct.rs"
39+
required-features = ["derive"]

check.ps1

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ function Count-Lines {
3535
return $nonEmptyLines
3636
}
3737

38-
Run-Command "cargo build --lib"
39-
Run-Command "cargo build --lib --target x86_64-unknown-none"
40-
Run-Command "cargo test"
41-
Run-Command "cargo run --example simple_struct"
38+
Run-Command "cargo build --lib --all-features"
39+
Run-Command "cargo build --lib --target x86_64-unknown-none --all-features"
40+
Run-Command "cargo test --all-features"
41+
Run-Command "cargo run --example simple_struct --all-features"
42+
Run-Command "cargo run --example unbalanced_struct --all-features"
4243
Run-Command "cargo clippy --all-targets --all-features -- -D warnings --no-deps"
43-
Run-Command "cargo test --release -- --ignored"
44+
Run-Command "cargo test --release --all-features -- --ignored"
4445
Run-Command "cargo fmt"
4546
# Optional
4647
# Run-Command "cargo tarpaulin --lib --all-features --locked --out Html"

check.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ count_lines() {
3333
echo "$non_empty_lines"
3434
}
3535

36-
run_command "cargo build --lib"
37-
run_command "cargo build --lib --target x86_64-unknown-none"
38-
run_command "cargo test"
39-
run_command "cargo run --example simple_struct"
36+
run_command "cargo build --lib --all-features"
37+
run_command "cargo build --lib --target x86_64-unknown-none --all-features"
38+
run_command "cargo test --all-features"
39+
run_command "cargo run --example simple_struct --all-features"
40+
run_command "cargo run --example unbalanced_struct --all-features"
4041
run_command "cargo clippy --all-targets --all-features -- -D warnings --no-deps"
41-
run_command "cargo test --release -- --ignored"
42+
run_command "cargo test --release --all-features -- --ignored"
4243
run_command "cargo fmt"
4344
# Optional
4445
# run_command "cargo tarpaulin --lib --all-features --locked --out Html"

examples/simple_struct.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ impl HomomorphicOperation2<Vec3> for Vec3Add {
4343
let z = homomorph_impls::numbers::HomomorphicAddition::apply(&az, &bz);
4444

4545
// Merge the results
46-
let mut res = Vec::with_capacity(8 * size_of::<Vec3>());
47-
res.extend_from_slice(x.as_slice());
48-
res.extend_from_slice(y.as_slice());
49-
res.extend_from_slice(z.as_slice());
46+
let mut res = Vec::with_capacity(x.len() + y.len() + z.len());
47+
res.extend_from_slice(&x);
48+
res.extend_from_slice(&y);
49+
res.extend_from_slice(&z);
5050

5151
Ciphered::new_from_raw(res)
5252
}

examples/unbalanced_struct.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! This example runs perfectly on bare metal
2+
//! (assuming there's an `alloc` crate)
3+
#![no_std]
4+
5+
extern crate alloc;
6+
use alloc::vec::Vec;
7+
8+
use homomorph::prelude::*;
9+
10+
// Notice that Rust will optimize the struct by reorganizing the fields in memory.
11+
// This will not have any influence on the order of the fiels in `Ciphered<Unbalanced>`.
12+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode)]
13+
struct Unbalanced {
14+
x: u8,
15+
y: u64,
16+
z: u8,
17+
}
18+
19+
struct UnbalancedAdd;
20+
21+
impl HomomorphicOperation2<Unbalanced> for UnbalancedAdd {
22+
/// ## Safety
23+
///
24+
/// `d/delta` on cipher must have been at least `21*sizeof::<u64>()`.
25+
unsafe fn apply(a: &Ciphered<Unbalanced>, b: &Ciphered<Unbalanced>) -> Ciphered<Unbalanced> {
26+
// Even if Rust has optimized the order of the fields in memory, they will remain
27+
// in the same order in the `Ciphered<Unbalanced>` struct.
28+
29+
// Unwrap the first `Unbalanced`
30+
let (ax, a) = a.split_at(u8::BITS as usize);
31+
let (ay, az) = a.split_at(u64::BITS as usize);
32+
let ax: Ciphered<u8> = Ciphered::new_from_raw(ax.to_vec());
33+
let ay: Ciphered<u64> = Ciphered::new_from_raw(ay.to_vec());
34+
let az: Ciphered<u8> = Ciphered::new_from_raw(az.to_vec());
35+
36+
// Unwrap the second `Unbalanced`
37+
let (bx, b) = b.split_at(u8::BITS as usize);
38+
let (by, bz) = b.split_at(u64::BITS as usize);
39+
let bx: Ciphered<u8> = Ciphered::new_from_raw(bx.to_vec());
40+
let by: Ciphered<u64> = Ciphered::new_from_raw(by.to_vec());
41+
let bz: Ciphered<u8> = Ciphered::new_from_raw(bz.to_vec());
42+
43+
// Perform the already implemented homomorphic addition over `Coordinate`
44+
let x = homomorph_impls::numbers::HomomorphicAddition::apply(&ax, &bx);
45+
let y = homomorph_impls::numbers::HomomorphicAddition::apply(&ay, &by);
46+
let z = homomorph_impls::numbers::HomomorphicAddition::apply(&az, &bz);
47+
48+
// Merge the results
49+
// Notice that here, the final size of the vector is not 8*sizeof::<Unbalanced>
50+
// but actually smaller.
51+
let mut res = Vec::with_capacity(x.len() + y.len() + z.len());
52+
res.extend_from_slice(&x);
53+
res.extend_from_slice(&y);
54+
res.extend_from_slice(&z);
55+
56+
Ciphered::new_from_raw(res)
57+
}
58+
}
59+
60+
fn main() {
61+
const PARAMS: Parameters = Parameters::new(64, 32, 1, 32);
62+
let mut context = Context::new(PARAMS);
63+
context.generate_secret_key();
64+
context.generate_public_key().unwrap();
65+
let sk = context.get_secret_key().unwrap();
66+
let pk = context.get_public_key().unwrap();
67+
68+
let a = Ciphered::cipher(&Unbalanced { x: 1, y: 2, z: 3 }, pk);
69+
let b = Ciphered::cipher(&Unbalanced { x: 4, y: 5, z: 6 }, pk);
70+
let c = unsafe { UnbalancedAdd::apply(&a, &b) };
71+
let d = Ciphered::decipher(&c, sk);
72+
73+
assert_eq!(Unbalanced { x: 5, y: 7, z: 9 }, d);
74+
}

src/cipher.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ use crate::{PublicKey, SecretKey};
33

44
use alloc::vec::Vec;
55

6-
use core::ops::Deref;
7-
86
const CONFIG: bincode::config::Configuration<
97
bincode::config::LittleEndian,
108
bincode::config::Fixint,
@@ -212,8 +210,8 @@ impl<T: crate::Encode + crate::Decode> Ciphered<T> {
212210
}
213211
}
214212

215-
impl<T: crate::Encode + crate::Decode> Deref for Ciphered<T> {
216-
type Target = Vec<CipheredBit>;
213+
impl<T: crate::Encode + crate::Decode> core::ops::Deref for Ciphered<T> {
214+
type Target = [CipheredBit];
217215

218216
fn deref(&self) -> &Self::Target {
219217
&self.c_data
@@ -223,8 +221,11 @@ impl<T: crate::Encode + crate::Decode> Deref for Ciphered<T> {
223221
#[cfg(test)]
224222
mod tests {
225223
use super::*;
226-
use crate::{Context, Decode, Encode, Parameters};
224+
use crate::{Context, Parameters};
225+
#[cfg(feature = "derive")]
226+
use crate::{Decode, Encode};
227227

228+
#[cfg(feature = "derive")]
228229
#[derive(Copy, Clone, Debug, PartialEq, Decode, Encode)]
229230
struct MyStruct {
230231
a: u32,
@@ -252,11 +253,14 @@ mod tests {
252253
let decrypted = ciphered.decipher(sk);
253254
assert_eq!(data, decrypted);
254255

255-
let data = MyStruct { a: 42, b: 69 };
256-
let ciphered = Ciphered::cipher(&data, pk);
257-
assert_eq!(8 * size_of::<MyStruct>(), ciphered.len());
258-
let decrypted = ciphered.decipher(sk);
259-
assert_eq!(data, decrypted);
256+
#[cfg(feature = "derive")]
257+
{
258+
let data = MyStruct { a: 42, b: 69 };
259+
let ciphered = Ciphered::cipher(&data, pk);
260+
assert_eq!(8 * size_of::<MyStruct>(), ciphered.len());
261+
let decrypted = ciphered.decipher(sk);
262+
assert_eq!(data, decrypted);
263+
}
260264
}
261265

262266
#[test]

src/context.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::polynomial::Polynomial;
22

3+
use alloc::boxed::Box;
34
use alloc::vec::Vec;
45

56
/// Parameters for the algorithm.
@@ -181,7 +182,7 @@ impl Drop for SecretKey {
181182

182183
/// The public key.
183184
#[derive(Clone, Debug, PartialEq, Eq)]
184-
pub struct PublicKey(Vec<Polynomial>);
185+
pub struct PublicKey(Box<[Polynomial]>);
185186

186187
impl PublicKey {
187188
#[must_use]
@@ -210,31 +211,31 @@ impl PublicKey {
210211
///
211212
/// let pk = PublicKey::from_bytes(&p);
212213
/// ```
213-
pub fn from_bytes(bytes_vec: &Vec<Vec<u8>>) -> Self {
214+
pub fn from_bytes(bytes_vec: &[Vec<u8>]) -> Self {
214215
let mut list: Vec<Polynomial> = Vec::with_capacity(bytes_vec.len());
215216
for bytes in bytes_vec {
216217
list.push(Polynomial::from_bytes(bytes));
217218
}
218-
Self(list)
219+
Self(list.into_boxed_slice())
219220
}
220221

221222
#[must_use]
222223
/// Generates a random public key
223224
fn random(dp: u16, delta: u16, tau: u16, secret_key: &SecretKey) -> Self {
224-
let list: Vec<_> = (0..tau)
225+
let list = (0..tau)
225226
.map(|_| {
226227
let q = Polynomial::random(dp as usize);
227228
let sq = secret_key.clone().get_polynomial().mul(&q);
228229
let r = Polynomial::random(delta as usize);
229230
let rx = r.mul(&Polynomial::monomial(1));
230231
sq.add(&rx)
231232
})
232-
.collect();
233+
.collect::<Vec<_>>();
233234

234-
Self(list)
235+
Self(list.into_boxed_slice())
235236
}
236237

237-
pub(crate) const fn get_polynomials(&self) -> &Vec<Polynomial> {
238+
pub(crate) const fn get_polynomials(&self) -> &[Polynomial] {
238239
&self.0
239240
}
240241

src/impls/numbers/uint.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ fn homomorph_add_internal(a: &[CipheredBit], b: &[CipheredBit]) -> Vec<CipheredB
6565
let mut result = Vec::with_capacity(a.len());
6666
let mut carry = CipheredBit::zero();
6767

68+
let one_bit = CipheredBit::one();
69+
6870
for (i, (cb1, cb2)) in a.iter().zip(b.iter()).enumerate() {
6971
let s = cb1.xor(cb2).xor(&carry);
7072

@@ -82,7 +84,7 @@ fn homomorph_add_internal(a: &[CipheredBit], b: &[CipheredBit]) -> Vec<CipheredB
8284
let cb1_cb2 = cb1.and(cb2);
8385
carry = carry
8486
.and(&cb1.xor(cb2))
85-
.and(&CipheredBit::one().xor(&cb1_cb2))
87+
.and(&one_bit.xor(&cb1_cb2))
8688
.xor(&cb1_cb2);
8789
}
8890

0 commit comments

Comments
 (0)