@@ -154,6 +154,33 @@ impl PolyTrapdoorSampler for DCRTPolyTrapdoorSampler {
154154 log_mem ( "z_hat generated" ) ;
155155 z_hat_former. concat_rows ( & [ & z_hat_latter] )
156156 }
157+
158+ // Algorithm 5 of https://eprint.iacr.org/2017/601.pdf
159+ fn preimage_extend (
160+ & self ,
161+ params : & <<Self :: M as PolyMatrix >:: P as Poly >:: Params ,
162+ trapdoor : & Self :: Trapdoor ,
163+ public_matrix : & Self :: M ,
164+ ext_matrix : & Self :: M ,
165+ target : & Self :: M ,
166+ ) -> Self :: M {
167+ let d = public_matrix. row_size ( ) ;
168+ let ext_ncol = ext_matrix. col_size ( ) ;
169+ let target_ncol = target. col_size ( ) ;
170+ let n = params. ring_dimension ( ) as usize ;
171+ let k = params. modulus_digits ( ) ;
172+ let s = SPECTRAL_CONSTANT *
173+ ( self . base as f64 + 1.0 ) *
174+ SIGMA *
175+ SIGMA *
176+ ( ( ( d * n * k) as f64 ) . sqrt ( ) + ( ( 2 * n) as f64 ) . sqrt ( ) + 4.7 ) ;
177+ let dist = DistType :: GaussDist { sigma : s } ;
178+ let uniform_sampler = DCRTPolyUniformSampler :: new ( ) ;
179+ let preimage_right = uniform_sampler. sample_uniform ( params, ext_ncol, target_ncol, dist) ;
180+ let t = target - & ( ext_matrix * & preimage_right) ;
181+ let preimage_left = self . preimage ( params, trapdoor, public_matrix, & t) ;
182+ preimage_left. concat_rows ( & [ & preimage_right] )
183+ }
157184}
158185
159186pub ( crate ) fn decompose_dcrt_gadget (
@@ -502,4 +529,40 @@ mod test {
502529
503530 assert_eq ! ( product, target, "Product of public matrix and preimage should equal target" ) ;
504531 }
532+
533+ #[ test]
534+ fn test_preimage_generation_extend ( ) {
535+ let params = DCRTPolyParams :: default ( ) ;
536+ let size = 3 ;
537+ let k = params. modulus_digits ( ) ;
538+ let trapdoor_sampler = DCRTPolyTrapdoorSampler :: new ( & params, SIGMA ) ;
539+ let ( trapdoor, public_matrix) = trapdoor_sampler. trapdoor ( & params, size) ;
540+
541+ let uniform_sampler = DCRTPolyUniformSampler :: new ( ) ;
542+ let target = uniform_sampler. sample_uniform ( & params, size, 1 , DistType :: FinRingDist ) ;
543+ let m = size * params. modulus_digits ( ) ;
544+ let extend = uniform_sampler. sample_uniform ( & params, size, m, DistType :: FinRingDist ) ;
545+
546+ let preimage =
547+ trapdoor_sampler. preimage_extend ( & params, & trapdoor, & public_matrix, & extend, & target) ;
548+
549+ let expected_rows = size * ( k + 2 ) + m;
550+ let expected_cols = 1 ;
551+
552+ assert_eq ! (
553+ preimage. row_size( ) ,
554+ expected_rows,
555+ "Preimage matrix should have the correct number of rows"
556+ ) ;
557+
558+ assert_eq ! (
559+ preimage. col_size( ) ,
560+ expected_cols,
561+ "Preimage matrix should have the correct number of columns"
562+ ) ;
563+
564+ // public_matrix * preimage should be equal to target
565+ let product = public_matrix. concat_columns ( & [ & extend] ) * & preimage;
566+ assert_eq ! ( product, target, "Product of public matrix and preimage should equal target" ) ;
567+ }
505568}
0 commit comments