@@ -278,4 +278,42 @@ mod test {
278278
279279 assert_eq ! ( result, expected) ;
280280 }
281+
282+ // Proptest for vartime_triple_scalar_mul_basepoint equivalence
283+ proptest:: proptest! {
284+ #[ test]
285+ fn proptest_triple_scalar_mul_equivalence(
286+ a1_bytes_16 in proptest:: array:: uniform16( proptest:: num:: u8 :: ANY ) ,
287+ a2_bytes_16 in proptest:: array:: uniform16( proptest:: num:: u8 :: ANY ) ,
288+ b_bytes in proptest:: array:: uniform32( proptest:: num:: u8 :: ANY ) ,
289+ A1_scalar_bytes in proptest:: array:: uniform32( proptest:: num:: u8 :: ANY ) ,
290+ A2_scalar_bytes in proptest:: array:: uniform32( proptest:: num:: u8 :: ANY ) ,
291+ ) {
292+ // Construct 128-bit scalars a1 and a2 (upper 16 bytes are zero)
293+ let mut a1_bytes = [ 0u8 ; 32 ] ;
294+ let mut a2_bytes = [ 0u8 ; 32 ] ;
295+ a1_bytes[ ..16 ] . copy_from_slice( & a1_bytes_16) ;
296+ a2_bytes[ ..16 ] . copy_from_slice( & a2_bytes_16) ;
297+
298+ let a1 = Scalar :: from_bytes_mod_order( a1_bytes) ;
299+ let a2 = Scalar :: from_bytes_mod_order( a2_bytes) ;
300+
301+ // Construct full 256-bit scalar b
302+ let b = Scalar :: from_bytes_mod_order( b_bytes) ;
303+
304+ // Generate random points A1 and A2 using scalar multiplication of basepoint
305+ let A1_scalar = Scalar :: from_bytes_mod_order( A1_scalar_bytes ) ;
306+ let A2_scalar = Scalar :: from_bytes_mod_order( A2_scalar_bytes ) ;
307+ let A1 = & constants:: ED25519_BASEPOINT_POINT * & A1_scalar ;
308+ let A2 = & constants:: ED25519_BASEPOINT_POINT * & A2_scalar ;
309+
310+ // Compute using the optimized triple-base function
311+ let result_optimized = mul_128_128_256( & a1, & A1 , & a2, & A2 , & b) ;
312+
313+ // Compute using raw operations: a1*A1 + a2*A2 + b*B
314+ let expected = & ( & ( & a1 * & A1 ) + & ( & a2 * & A2 ) ) + & ( & b * & constants:: ED25519_BASEPOINT_POINT ) ;
315+
316+ proptest:: prop_assert_eq!( result_optimized, expected, "Optimized triple scalar mul should equal raw operations" ) ;
317+ }
318+ }
281319}
0 commit comments