11// Goldwasser-Micali Encryption and its AND variance
22// Support 32-bit unsigned integers as plaintext
33
4- use crate :: number:: { get_strong_prime, Jacobi } ;
4+ use crate :: number:: get_strong_prime;
55use num_bigint:: BigInt ;
66use num_traits:: { One , Zero } ;
77use rand:: { rngs:: StdRng , Rng , SeedableRng } ;
@@ -55,30 +55,29 @@ pub fn generate_keys(prime_size: Option<u64>) -> Keys {
5555
5656static mut MY_COUNTER : u64 = 0 ;
5757
58- pub fn get_next_random ( n : BigInt ) -> BigInt {
58+ pub fn get_next_random ( n : & BigInt ) -> BigInt {
5959 unsafe {
6060 MY_COUNTER += 1 ;
6161 n - BigInt :: from ( MY_COUNTER )
6262 }
6363}
6464
65- pub fn encrypt_bit_gm ( bit : u8 , n : & BigInt ) -> BigInt {
66- let r = get_next_random ( n - 1 ) ;
67-
68- let m = if bit == 1 { BigInt :: one ( ) } else { BigInt :: zero ( ) } ;
69- ( r. clone ( ) * r. clone ( ) * & ( n - BigInt :: one ( ) ) . modpow ( & m, & n) ) % n
65+ pub fn encrypt_bit_gm ( bit : & BigInt , n : & BigInt ) -> BigInt {
66+ let r = get_next_random ( & ( n - BigInt :: one ( ) ) ) ;
67+ ( r. clone ( ) * r. clone ( ) * & ( n - BigInt :: one ( ) ) . modpow ( & bit, & n) ) % n
7068}
7169
72- pub fn encrypt_bit_gm_coin ( bit : u8 , n : & BigInt , r : BigInt ) -> BigInt {
70+ pub fn encrypt_bit_gm_coin ( bit : & BigInt /* only 0 or 1 */ , n : & BigInt , r : BigInt ) -> BigInt {
7371 assert ! ( r >= BigInt :: zero( ) && r <= n - 1 ) ;
74-
75- let m = if bit == 1 { BigInt :: one ( ) } else { BigInt :: zero ( ) } ;
76- ( r. clone ( ) * r. clone ( ) * & ( n - BigInt :: one ( ) ) . modpow ( & m, & n) ) % n
72+ ( r. clone ( ) * r. clone ( ) * & ( n - BigInt :: one ( ) ) . modpow ( & bit, & n) ) % n
7773}
7874
79- pub fn encrypt_gm ( number : u32 , pub_key : & BigInt ) -> Vec < BigInt > {
75+ pub fn encrypt_gm ( number : & BigInt , pub_key : & BigInt ) -> Vec < BigInt > {
8076 let bits_str = format ! ( "{:032b}" , number) ;
81- bits_str. chars ( ) . map ( |bit| encrypt_bit_gm ( bit. to_digit ( 2 ) . unwrap ( ) as u8 , pub_key) ) . collect ( )
77+ bits_str
78+ . chars ( )
79+ . map ( |bit| encrypt_bit_gm ( & BigInt :: from ( bit. to_digit ( 2 ) . unwrap ( ) ) , pub_key) )
80+ . collect ( )
8281}
8382
8483pub fn decrypt_bit_gm ( c : & BigInt , sk_gm : & BigInt , n : & BigInt ) -> u8 {
@@ -89,7 +88,7 @@ pub fn decrypt_bit_gm(c: &BigInt, sk_gm: &BigInt, n: &BigInt) -> u8 {
8988 }
9089}
9190
92- pub fn decrypt_gm ( cipher_numbers : & [ BigInt ] , priv_key : & ( BigInt , BigInt ) ) -> Option < u32 > {
91+ pub fn decrypt_gm ( cipher_numbers : & [ BigInt ] , priv_key : & ( BigInt , BigInt ) ) -> Option < BigInt > {
9392 let ( p, q) = priv_key;
9493 let n = p * q;
9594
@@ -101,21 +100,21 @@ pub fn decrypt_gm(cipher_numbers: &[BigInt], priv_key: &(BigInt, BigInt)) -> Opt
101100 . map ( |bit| if bit == 1 { '1' } else { '0' } ) // Convert BigInt to '1' or '0'
102101 . collect ( ) ;
103102
104- println ! ( "String is {}" , bits_str) ;
105-
106- u32:: from_str_radix ( & bits_str, 2 ) . ok ( )
103+ Some ( BigInt :: from ( u32:: from_str_radix ( & bits_str, 2 ) . unwrap ( ) ) )
107104}
108105
109106pub fn encrypt_bit_and ( bit : u8 , pub_key : & BigInt ) -> Vec < BigInt > {
110107 let mut rng = StdRng :: from_entropy ( ) ;
111108 if bit == 1 {
112- ( 0 ..AND_SIZE_FACTOR ) . map ( |_| encrypt_bit_gm ( 0 , pub_key) ) . collect ( )
109+ ( 0 ..AND_SIZE_FACTOR ) . map ( |_| encrypt_bit_gm ( & BigInt :: zero ( ) , pub_key) ) . collect ( )
113110 } else {
114- ( 0 ..AND_SIZE_FACTOR ) . map ( |_| encrypt_bit_gm ( rng. gen_range ( 0 ..=1 ) , pub_key) ) . collect ( )
111+ ( 0 ..AND_SIZE_FACTOR )
112+ . map ( |_| encrypt_bit_gm ( & BigInt :: from ( rng. gen_range ( 0 ..=1 ) ) , pub_key) )
113+ . collect ( )
115114 }
116115}
117116
118- pub fn decrypt_bit_and ( cipher : & Vec < BigInt > , priv_key : ( BigInt , BigInt ) ) -> u8 {
117+ pub fn decrypt_bit_and ( cipher : & Vec < BigInt > , priv_key : & ( BigInt , BigInt ) ) -> u8 {
119118 let ( p, q) = priv_key;
120119 let sk_gm: BigInt = ( ( p. clone ( ) - 1 ) * ( q. clone ( ) - 1 ) ) / 4 ;
121120 let n = p. clone ( ) * q. clone ( ) ;
@@ -139,9 +138,9 @@ pub fn embed_bit_and(bit_cipher: &BigInt, pub_key: &BigInt, r: &[BigInt]) -> Vec
139138 ( 0 ..AND_SIZE_FACTOR )
140139 . map ( |i| {
141140 if rng. gen_range ( 0 ..=1 ) == 1 {
142- encrypt_bit_gm_coin ( 0 , n, r[ i] . clone ( ) )
141+ encrypt_bit_gm_coin ( & BigInt :: zero ( ) , n, r[ i] . clone ( ) )
143142 } else {
144- encrypt_bit_gm_coin ( 0 , n, r[ i] . clone ( ) ) * bit_cipher * ( n - 1 ) % n
143+ encrypt_bit_gm_coin ( & BigInt :: zero ( ) , n, r[ i] . clone ( ) ) * bit_cipher * ( n - 1 ) % n
145144 }
146145 } )
147146 . collect ( )
@@ -155,13 +154,13 @@ pub fn embed_and(cipher: &[BigInt], pub_key: &BigInt, r: &[Vec<BigInt>]) -> Vec<
155154 . collect ( )
156155}
157156
158- pub fn encrypt_gm_coin ( mpz_number : u32 , pub_key : BigInt , r : & [ BigInt ] ) -> Vec < BigInt > {
157+ pub fn encrypt_gm_coin ( mpz_number : & BigInt , pub_key : & BigInt , r : & [ BigInt ] ) -> Vec < BigInt > {
159158 let bits_str = format ! ( "{:032b}" , mpz_number) ;
160159
161160 ( 0 ..32 )
162161 . map ( |i| {
163162 encrypt_bit_gm_coin (
164- bits_str. chars ( ) . nth ( i) . unwrap ( ) . to_digit ( 2 ) . unwrap ( ) as u8 ,
163+ & BigInt :: from ( bits_str. chars ( ) . nth ( i) . unwrap ( ) . to_digit ( 2 ) . unwrap ( ) ) ,
165164 & pub_key,
166165 r[ i] . clone ( ) ,
167166 )
@@ -172,6 +171,7 @@ pub fn encrypt_gm_coin(mpz_number: u32, pub_key: BigInt, r: &[BigInt]) -> Vec<Bi
172171#[ cfg( test) ] // This module is included only during testing
173172mod tests {
174173 use super :: * ;
174+ use crate :: number:: Jacobi ;
175175 use std:: time:: Instant ;
176176
177177 #[ test]
@@ -199,13 +199,15 @@ mod tests {
199199 let mut rng = StdRng :: from_entropy ( ) ;
200200
201201 for _ in 0 ..iters {
202- let num: u32 = rng. gen :: < u32 > ( ) ;
203- let mut cipher = encrypt_gm ( num, & n) ;
202+ let num: BigInt = BigInt :: from ( rng. gen :: < u32 > ( ) ) ;
203+ let mut cipher = encrypt_gm ( & num, & n) ;
204204
205205 // Re-encryption
206206 for _ in 0 ..3 {
207- cipher =
208- cipher. iter ( ) . map ( |c| ( c * encrypt_gm ( 0u32 , & n) [ 0 ] . clone ( ) ) % & n) . collect ( ) ;
207+ cipher = cipher
208+ . iter ( )
209+ . map ( |c| ( c * encrypt_gm ( & BigInt :: zero ( ) , & n) [ 0 ] . clone ( ) ) % & n)
210+ . collect ( ) ;
209211 }
210212
211213 let decrypted = decrypt_gm ( & cipher, & keys. priv_key ) ;
@@ -227,22 +229,31 @@ mod tests {
227229 let n = keys. pub_key ;
228230 let priv_key = keys. priv_key ;
229231
230- let c0 = encrypt_bit_gm ( 0 , & n) ;
231- let c1 = encrypt_bit_gm ( 1 , & n) ;
232+ let c0 = encrypt_bit_gm ( & BigInt :: zero ( ) , & n) ;
233+ let c1 = encrypt_bit_gm ( & BigInt :: one ( ) , & n) ;
232234
233235 // XOR tests
234- assert_eq ! ( decrypt_gm( & [ c0. clone( ) * c1. clone( ) % n. clone( ) ] , & priv_key) , Some ( 1u32 ) ) ;
235- assert_eq ! ( decrypt_gm( & [ c0. clone( ) * c0. clone( ) % n. clone( ) ] , & priv_key) , Some ( 0u32 ) ) ;
236- assert_eq ! ( decrypt_gm( & [ c1. clone( ) * c1. clone( ) % n. clone( ) ] , & priv_key) , Some ( 0u32 ) ) ;
236+ assert_eq ! (
237+ decrypt_gm( & [ c0. clone( ) * c1. clone( ) % n. clone( ) ] , & priv_key) ,
238+ Some ( BigInt :: one( ) )
239+ ) ;
240+ assert_eq ! (
241+ decrypt_gm( & [ c0. clone( ) * c0. clone( ) % n. clone( ) ] , & priv_key) ,
242+ Some ( BigInt :: zero( ) )
243+ ) ;
244+ assert_eq ! (
245+ decrypt_gm( & [ c1. clone( ) * c1. clone( ) % n. clone( ) ] , & priv_key) ,
246+ Some ( BigInt :: zero( ) )
247+ ) ;
237248
238249 // Flip tests
239250 assert_eq ! (
240251 decrypt_gm( & [ c0. clone( ) * ( n. clone( ) - 1 ) % n. clone( ) ] , & priv_key) ,
241- Some ( 1u32 )
252+ Some ( BigInt :: one ( ) )
242253 ) ;
243254 assert_eq ! (
244255 decrypt_gm( & [ c1. clone( ) * ( n. clone( ) - 1 ) % n. clone( ) ] , & priv_key) ,
245- Some ( 0u32 )
256+ Some ( BigInt :: zero ( ) )
246257 ) ;
247258 }
248259
@@ -270,35 +281,26 @@ mod tests {
270281 enc_times. push ( start. elapsed ( ) . as_secs_f64 ( ) ) ;
271282
272283 let start = Instant :: now ( ) ;
273- let bit0 = decrypt_bit_and ( & cipher0, priv_key. clone ( ) ) ;
284+ let bit0 = decrypt_bit_and ( & cipher0, & priv_key) ;
274285 dec_times. push ( start. elapsed ( ) . as_secs_f64 ( ) ) ;
275286
276287 let start = Instant :: now ( ) ;
277- let bit1 = decrypt_bit_and ( & cipher1, priv_key. clone ( ) ) ;
288+ let bit1 = decrypt_bit_and ( & cipher1, & priv_key) ;
278289 dec_times. push ( start. elapsed ( ) . as_secs_f64 ( ) ) ;
279290
280291 assert_eq ! ( bit0, 0u8 ) ;
281292 assert_eq ! ( bit1, 1u8 ) ;
282293
283294 assert_eq ! (
284- decrypt_bit_and(
285- & dot_mod( & cipher0, & encrypt_bit_and( 1u8 , & n) , & n) ,
286- priv_key. clone( )
287- ) ,
295+ decrypt_bit_and( & dot_mod( & cipher0, & encrypt_bit_and( 1u8 , & n) , & n) , & priv_key) ,
288296 0u8
289297 ) ;
290298 assert_eq ! (
291- decrypt_bit_and(
292- & dot_mod( & cipher0, & encrypt_bit_and( 0u8 , & n) , & n) ,
293- priv_key. clone( )
294- ) ,
299+ decrypt_bit_and( & dot_mod( & cipher0, & encrypt_bit_and( 0u8 , & n) , & n) , & priv_key) ,
295300 0u8
296301 ) ;
297302 assert_eq ! (
298- decrypt_bit_and(
299- & dot_mod( & cipher1, & encrypt_bit_and( 1u8 , & n) , & n) ,
300- priv_key. clone( )
301- ) ,
303+ decrypt_bit_and( & dot_mod( & cipher1, & encrypt_bit_and( 1u8 , & n) , & n) , & priv_key) ,
302304 1u8
303305 ) ;
304306 }
0 commit comments