1mod cipher;
4mod errors;
5mod message;
6mod public;
7mod secret;
8
9pub use self::{cipher::*, message::*, public::*, secret::*};
10
11use crate::curve_arithmetic::{Curve, Field, PrimeField, Value};
12use rand::*;
13
14#[derive(Clone, Copy, PartialEq, Eq)]
16pub enum ChunkSize {
17 One,
18 Two,
19 Four,
20 Eight,
21 Sixteen,
22 ThirtyTwo,
23 SixtyFour,
24}
25
26impl From<ChunkSize> for u8 {
27 fn from(c: ChunkSize) -> Self {
28 use ChunkSize::*;
29 match c {
30 One => 1,
31 Two => 2,
32 Four => 4,
33 Eight => 8,
34 Sixteen => 16,
35 ThirtyTwo => 32,
36 SixtyFour => 64,
37 }
38 }
39}
40
41impl ChunkSize {
42 pub fn mask(self) -> u64 {
49 use ChunkSize::*;
50 match self {
51 One => 1,
52 Two => 0b11,
53 Four => 0b1111,
54 Eight => (1 << 8) - 1,
55 Sixteen => (1 << 16) - 1,
56 ThirtyTwo => (1 << 32) - 1,
57 SixtyFour => !0,
58 }
59 }
60
61 pub fn u64_to_chunks(self, x: u64) -> Vec<u64> {
63 let mask = self.mask();
64 let size = u8::from(self);
65 let n = 64 / usize::from(size);
66 let mut out = Vec::with_capacity(n);
67 let mut tmp = x;
68 for _ in 0..n {
69 out.push(tmp & mask);
70 tmp >>= size;
71 }
72 out
73 }
74
75 pub fn chunks_to_u64(self, xs: impl IntoIterator<Item = u64>) -> u64 {
77 let size = u8::from(self);
78 let mut factor = 0;
79 let mut out = 0;
80 for x in xs {
81 out += x << factor;
82 factor += size;
83 }
84 out
85 }
86}
87
88pub fn value_to_chunks<C: Curve>(val: &C::Scalar, chunk_size: ChunkSize) -> Vec<Value<C>> {
91 let size = usize::from(u8::from(chunk_size));
93 let n = C::SCALAR_LENGTH / size;
94 let mut out = Vec::with_capacity(n);
95 let u64_chunks = val.into_repr();
96 for chunk in u64_chunks {
97 out.extend(
98 chunk_size
99 .u64_to_chunks(chunk)
100 .iter()
101 .map(|&x| Value::new(C::scalar_from_u64(x))),
102 );
103 }
104 out
105}
106
107pub fn chunks_to_value<C: Curve>(chunks: &[Value<C>], chunk_size: ChunkSize) -> Value<C> {
112 let mul = {
114 let mut factor = C::scalar_from_u64(1);
115 factor.add_assign(&C::scalar_from_u64(!0));
116 factor
117 };
118 let mut factor = C::Scalar::one();
119 let mut ret = C::Scalar::zero();
120 for chunk_section in chunks.chunks(64 / usize::from(u8::from(chunk_size))) {
121 let v = chunk_size.chunks_to_u64(chunk_section.iter().map(|chunk| {
123 let repr = chunk.into_repr();
124 repr[0]
125 }));
126 let mut val = C::scalar_from_u64(v);
127 val.mul_assign(&factor);
128 ret.add_assign(&val);
129 factor.mul_assign(&mul);
130 }
131 Value::new(ret)
132}
133
134pub fn encrypt_in_chunks<C: Curve, R: Rng>(
137 pk: &PublicKey<C>,
138 val: &Value<C>,
139 chunk_size: ChunkSize,
140 csprng: &mut R,
141) -> Vec<(Cipher<C>, Randomness<C>)> {
142 encrypt_in_chunks_given_generator(pk, val, chunk_size, &pk.generator, csprng)
143}
144
145pub fn encrypt_in_chunks_given_generator<C: Curve, R: Rng>(
146 pk: &PublicKey<C>,
147 val: &Value<C>,
148 chunk_size: ChunkSize,
149 generator: &C,
150 csprng: &mut R,
151) -> Vec<(Cipher<C>, Randomness<C>)> {
152 let chunks = value_to_chunks::<C>(val, chunk_size);
153 pk.encrypt_exponent_vec_given_generator(&chunks, generator, csprng)
154}
155
156pub fn encrypt_u64_in_chunks_given_generator<C: Curve, R: Rng>(
159 pk: &PublicKey<C>,
160 val: u64,
161 chunk_size: ChunkSize,
162 generator: &C,
163 csprng: &mut R,
164) -> Vec<(Cipher<C>, Randomness<C>)> {
165 let chunks = chunk_size
166 .u64_to_chunks(val)
167 .into_iter()
168 .map(Value::from)
169 .collect::<Vec<_>>();
170 pk.encrypt_exponent_vec_given_generator(&chunks, generator, csprng)
171}
172
173pub fn decrypt_from_chunks<C: Curve>(
176 sk: &SecretKey<C>,
177 cipher: &[Cipher<C>],
178 m: u64,
179 chunk_size: ChunkSize,
180) -> Value<C> {
181 decrypt_from_chunks_given_generator(sk, cipher, &sk.generator, m, chunk_size)
182}
183
184pub fn decrypt_from_chunks_given_generator<C: Curve>(
185 sk: &SecretKey<C>,
186 cipher: &[Cipher<C>],
187 generator: &C,
188 m: u64,
189 chunk_size: ChunkSize,
190) -> Value<C> {
191 let bsgs = BabyStepGiantStep::new(generator, m);
192 decrypt_from_chunks_given_table(sk, cipher, &bsgs, chunk_size)
193}
194
195pub fn decrypt_from_chunks_given_table<C: Curve>(
196 sk: &SecretKey<C>,
197 ciphers: &[Cipher<C>],
198 table: &BabyStepGiantStep<C>,
199 chunk_size: ChunkSize,
200) -> Value<C> {
201 let scalars = ciphers
202 .iter()
203 .map(|cipher| Value::from(sk.decrypt_exponent(cipher, table)))
204 .collect::<Vec<_>>();
205 chunks_to_value::<C>(&scalars, chunk_size)
206}
207
208#[cfg(test)]
209mod tests {
210 use crate::curve_arithmetic::arkworks_instances::ArkGroup;
211
212 use super::*;
213 use ark_bls12_381::{G1Projective, G2Projective};
214 use rand::{rngs::ThreadRng, Rng};
215
216 fn test_encrypt_decrypt_success_generic<C: Curve>() {
220 let mut csprng = thread_rng();
221 for _i in 1..10 {
222 let sk: SecretKey<C> = SecretKey::generate_all(&mut csprng);
223 let pk = PublicKey::from(&sk);
224 let m = Message::generate(&mut csprng);
225 let c = pk.encrypt(&mut csprng, &m);
226 let mm = sk.decrypt(&c);
227 assert_eq!(m, mm);
228
229 let canother = pk.encrypt(&mut csprng, &m);
231 assert_ne!(c, canother);
232 }
233 }
234
235 #[test]
236 fn encrypt_decrypt_success_g1() {
237 test_encrypt_decrypt_success_generic::<ArkGroup<G1Projective>>()
238 }
239
240 #[test]
241 fn encrypt_decrypt_success_g2() {
242 test_encrypt_decrypt_success_generic::<ArkGroup<G2Projective>>()
243 }
244
245 fn test_encrypt_decrypt_exponent_success_generic<C: Curve>() {
249 let mut csprng = thread_rng();
250 let sk: SecretKey<C> = SecretKey::generate_all(&mut csprng);
251 let pk = PublicKey::from(&sk);
252 for _i in 1..10 {
253 let n = csprng.gen_range(0..1000);
254 let mut e = <C as Curve>::Scalar::zero();
255 let one_scalar = Value::<C>::new(<C as Curve>::Scalar::one());
256 for _ in 0..n {
257 e.add_assign(&one_scalar);
258 }
259 let c = pk.encrypt_exponent(&mut csprng, &Value::new(e));
260 let e2 = sk.decrypt_exponent_slow(&c);
261 let e = Value::new(e);
262 assert_eq!(e, e2);
263 }
264 }
265
266 #[test]
267 fn encrypt_decrypt_exponent_success_g1() {
268 test_encrypt_decrypt_exponent_success_generic::<ArkGroup<G1Projective>>()
269 }
270
271 #[test]
272 fn encrypt_decrypt_exponent_success_g2() {
273 test_encrypt_decrypt_exponent_success_generic::<ArkGroup<G2Projective>>()
274 }
275
276 fn test_chunking_generic<C: Curve>() {
280 let mut csprng = thread_rng();
281 use ChunkSize::*;
282 let possible_chunk_sizes = [One, Two, Four, Eight, Sixteen, ThirtyTwo];
283 for _i in 1..10 {
286 let scalar = Value::<C>::generate(&mut csprng);
287 let chunk_size_index: usize = csprng.gen_range(0..possible_chunk_sizes.len());
288 let chunk_size = possible_chunk_sizes[chunk_size_index];
289 let chunks = value_to_chunks::<C>(&scalar, chunk_size);
290 let retrieved_scalar = chunks_to_value::<C>(&chunks, chunk_size);
291 assert_eq!(scalar, retrieved_scalar);
293 }
294 }
295
296 #[test]
297 fn chunking_test_g1() {
298 test_chunking_generic::<ArkGroup<G1Projective>>()
299 }
300
301 fn test_chunked_encrypt_decrypt_generic<C: Curve>() {
305 let mut csprng = thread_rng();
306 let sk = SecretKey::<C>::generate_all(&mut csprng);
307 let pk = PublicKey::<C>::from(&sk);
308 let possible_chunk_sizes = [ChunkSize::Two];
310
311 for _i in 1..2 {
312 let scalar = Value::<C>::generate(&mut csprng);
313 let chunk_size_index: usize = csprng.gen_range(0..possible_chunk_sizes.len());
314 let chunk_size = possible_chunk_sizes[chunk_size_index];
315 let m = 1 << (u8::from(chunk_size) - 1);
316 let cipher_pairs =
317 encrypt_in_chunks::<C, ThreadRng>(&pk, &scalar, chunk_size, &mut csprng);
318 let cipher = cipher_pairs.into_iter().map(|(x, _)| x).collect::<Vec<_>>();
319 let retrieved_scalar = decrypt_from_chunks::<C>(&sk, &cipher, m, chunk_size);
320 assert_eq!(
321 scalar, retrieved_scalar,
322 "Encrypted and retrieved scalars differ."
323 );
324 }
325 }
326
327 #[test]
328 fn chunked_encrypt_decrypt_test_g1() {
329 test_chunked_encrypt_decrypt_generic::<ArkGroup<G1Projective>>()
330 }
331}