concrete_boolean/server_key/
mod.rs

1//! The public key for homomorphic computation.
2//!
3//! This module implements the generation of the server's public key, together with all the
4//! available homomorphic Boolean gates ($\mathrm{AND}$, $\mathrm{MUX}$, $\mathrm{NAND}$,
5//! $\mathrm{NOR}$,
6//! $\mathrm{NOT}$, $\mathrm{OR}$, $\mathrm{XNOR}$, $\mathrm{XOR}$).
7
8#[cfg(test)]
9mod tests;
10
11use serde::{Deserialize, Serialize};
12
13use crate::ciphertext::Ciphertext;
14use crate::client_key::ClientKey;
15use crate::engine::bootstrapping::CpuBootstrapKey;
16#[cfg(feature = "cuda")]
17use crate::engine::{bootstrapping::CudaBootstrapKey, CudaBooleanEngine};
18use crate::engine::{BinaryGatesEngine, CpuBooleanEngine, WithThreadLocalEngine};
19#[cfg(feature = "cuda")]
20use std::sync::Arc;
21
22pub trait BinaryBooleanGates<L, R> {
23    fn and(&self, ct_left: L, ct_right: R) -> Ciphertext;
24    fn nand(&self, ct_left: L, ct_right: R) -> Ciphertext;
25    fn nor(&self, ct_left: L, ct_right: R) -> Ciphertext;
26    fn or(&self, ct_left: L, ct_right: R) -> Ciphertext;
27    fn xor(&self, ct_left: L, ct_right: R) -> Ciphertext;
28    fn xnor(&self, ct_left: L, ct_right: R) -> Ciphertext;
29}
30
31trait RefFromServerKey {
32    fn get_ref(server_key: &ServerKey) -> &Self;
33}
34
35trait DefaultImplementation {
36    type Engine: WithThreadLocalEngine;
37    type BootsrapKey: RefFromServerKey;
38}
39
40#[derive(Clone)]
41pub struct ServerKey {
42    cpu_key: CpuBootstrapKey,
43    #[cfg(feature = "cuda")]
44    cuda_key: Arc<CudaBootstrapKey>,
45}
46
47#[cfg(not(feature = "cuda"))]
48mod implementation {
49    use super::*;
50
51    impl RefFromServerKey for CpuBootstrapKey {
52        fn get_ref(server_key: &ServerKey) -> &Self {
53            &server_key.cpu_key
54        }
55    }
56
57    impl DefaultImplementation for ServerKey {
58        type Engine = CpuBooleanEngine;
59        type BootsrapKey = CpuBootstrapKey;
60    }
61}
62
63#[cfg(feature = "cuda")]
64mod implementation {
65    use super::*;
66
67    impl RefFromServerKey for CudaBootstrapKey {
68        fn get_ref(server_key: &ServerKey) -> &Self {
69            &server_key.cuda_key
70        }
71    }
72
73    impl DefaultImplementation for ServerKey {
74        type Engine = CudaBooleanEngine;
75        type BootsrapKey = CudaBootstrapKey;
76    }
77}
78
79impl<Lhs, Rhs> BinaryBooleanGates<Lhs, Rhs> for ServerKey
80where
81    <ServerKey as DefaultImplementation>::Engine:
82        BinaryGatesEngine<Lhs, Rhs, <ServerKey as DefaultImplementation>::BootsrapKey>,
83{
84    fn and(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
85        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
86        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
87            engine.and(ct_left, ct_right, bootstrap_key)
88        })
89    }
90
91    fn nand(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
92        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
93        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
94            engine.nand(ct_left, ct_right, bootstrap_key)
95        })
96    }
97
98    fn nor(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
99        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
100        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
101            engine.nor(ct_left, ct_right, bootstrap_key)
102        })
103    }
104
105    fn or(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
106        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
107        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
108            engine.or(ct_left, ct_right, bootstrap_key)
109        })
110    }
111
112    fn xor(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
113        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
114        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
115            engine.xor(ct_left, ct_right, bootstrap_key)
116        })
117    }
118
119    fn xnor(&self, ct_left: Lhs, ct_right: Rhs) -> Ciphertext {
120        let bootstrap_key = <ServerKey as DefaultImplementation>::BootsrapKey::get_ref(self);
121        <ServerKey as DefaultImplementation>::Engine::with_thread_local_mut(|engine| {
122            engine.xnor(ct_left, ct_right, bootstrap_key)
123        })
124    }
125}
126
127impl ServerKey {
128    pub fn new(cks: &ClientKey) -> Self {
129        let cpu_key =
130            CpuBooleanEngine::with_thread_local_mut(|engine| engine.create_server_key(cks));
131
132        Self::from(cpu_key)
133    }
134
135    pub fn trivial_encrypt(&self, message: bool) -> Ciphertext {
136        Ciphertext::Trivial(message)
137    }
138
139    pub fn not(&self, ct: &Ciphertext) -> Ciphertext {
140        CpuBooleanEngine::with_thread_local_mut(|engine| engine.not(ct))
141    }
142
143    pub fn mux(
144        &self,
145        ct_condition: &Ciphertext,
146        ct_then: &Ciphertext,
147        ct_else: &Ciphertext,
148    ) -> Ciphertext {
149        #[cfg(feature = "cuda")]
150        {
151            CudaBooleanEngine::with_thread_local_mut(|engine| {
152                engine.mux(ct_condition, ct_then, ct_else, &self.cuda_key)
153            })
154        }
155        #[cfg(not(feature = "cuda"))]
156        {
157            CpuBooleanEngine::with_thread_local_mut(|engine| {
158                engine.mux(ct_condition, ct_then, ct_else, &self.cpu_key)
159            })
160        }
161    }
162}
163
164impl From<CpuBootstrapKey> for ServerKey {
165    fn from(cpu_key: CpuBootstrapKey) -> Self {
166        #[cfg(feature = "cuda")]
167        {
168            let cuda_key = CudaBooleanEngine::with_thread_local_mut(|engine| {
169                engine.create_server_key(&cpu_key)
170            });
171
172            let cuda_key = Arc::new(cuda_key);
173
174            Self { cpu_key, cuda_key }
175        }
176        #[cfg(not(feature = "cuda"))]
177        {
178            Self { cpu_key }
179        }
180    }
181}
182
183impl Serialize for ServerKey {
184    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185    where
186        S: serde::Serializer,
187    {
188        self.cpu_key.serialize(serializer)
189    }
190}
191
192impl<'de> Deserialize<'de> for ServerKey {
193    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
194    where
195        D: serde::Deserializer<'de>,
196    {
197        let cpu_key = CpuBootstrapKey::deserialize(deserializer)?;
198
199        Ok(Self::from(cpu_key))
200    }
201}