@@ -401,6 +401,114 @@ void test_keypair(void) {
401
401
secp256k1_context_destroy (verify );
402
402
}
403
403
404
+ void test_keypair_add (void ) {
405
+ unsigned char sk [32 ];
406
+ secp256k1_keypair keypair ;
407
+ unsigned char overflows [32 ];
408
+ unsigned char zeros96 [96 ] = { 0 };
409
+ unsigned char tweak [32 ];
410
+ int i ;
411
+ int ecount = 0 ;
412
+ secp256k1_context * none = api_test_context (SECP256K1_CONTEXT_NONE , & ecount );
413
+ secp256k1_context * sign = api_test_context (SECP256K1_CONTEXT_SIGN , & ecount );
414
+ secp256k1_context * verify = api_test_context (SECP256K1_CONTEXT_VERIFY , & ecount );
415
+
416
+ CHECK (sizeof (zeros96 ) == sizeof (keypair ));
417
+ secp256k1_rand256 (sk );
418
+ secp256k1_rand256 (tweak );
419
+ memset (overflows , 0xFF , 32 );
420
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
421
+
422
+ CHECK (secp256k1_keypair_xonly_tweak_add (none , & keypair , tweak ) == 0 );
423
+ CHECK (ecount == 1 );
424
+ CHECK (secp256k1_keypair_xonly_tweak_add (sign , & keypair , tweak ) == 0 );
425
+ CHECK (ecount == 2 );
426
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , & keypair , tweak ) == 1 );
427
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , NULL , tweak ) == 0 );
428
+ CHECK (ecount == 3 );
429
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , & keypair , NULL ) == 0 );
430
+ CHECK (ecount == 4 );
431
+ /* This does not set the keypair to zeroes */
432
+ CHECK (memcmp (& keypair , zeros96 , sizeof (keypair )) != 0 );
433
+
434
+ /* Invalid tweak zeroes the keypair */
435
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
436
+ CHECK (secp256k1_keypair_xonly_tweak_add (ctx , & keypair , overflows ) == 0 );
437
+ CHECK (memcmp (& keypair , zeros96 , sizeof (keypair )) == 0 );
438
+
439
+ /* A zero tweak is fine */
440
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
441
+ CHECK (secp256k1_keypair_xonly_tweak_add (ctx , & keypair , zeros96 ) == 1 );
442
+
443
+ /* Fails if the resulting keypair was (sk=0, pk=infinity) */
444
+ for (i = 0 ; i < count ; i ++ ) {
445
+ secp256k1_scalar scalar_tweak ;
446
+ secp256k1_keypair keypair_tmp ;
447
+ secp256k1_rand256 (sk );
448
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
449
+ memcpy (& keypair_tmp , & keypair , sizeof (keypair ));
450
+ /* Because sk may be negated before adding, we need to try with tweak =
451
+ * sk as well as tweak = -sk. */
452
+ secp256k1_scalar_set_b32 (& scalar_tweak , sk , NULL );
453
+ secp256k1_scalar_negate (& scalar_tweak , & scalar_tweak );
454
+ secp256k1_scalar_get_b32 (tweak , & scalar_tweak );
455
+ CHECK ((secp256k1_keypair_xonly_tweak_add (ctx , & keypair , sk ) == 0 )
456
+ || (secp256k1_keypair_xonly_tweak_add (ctx , & keypair_tmp , tweak ) == 0 ));
457
+ CHECK (memcmp (& keypair , zeros96 , sizeof (keypair )) == 0
458
+ || memcmp (& keypair_tmp , zeros96 , sizeof (keypair_tmp )) == 0 );
459
+ }
460
+
461
+ /* Invalid keypair with a valid tweak */
462
+ memset (& keypair , 0 , sizeof (keypair ));
463
+ secp256k1_rand256 (tweak );
464
+ ecount = 0 ;
465
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , & keypair , tweak ) == 0 );
466
+ CHECK (ecount == 1 );
467
+ CHECK (memcmp (& keypair , zeros96 , sizeof (keypair )) == 0 );
468
+ /* Only seckey part of keypair invalid */
469
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
470
+ memset (& keypair , 0 , 32 );
471
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , & keypair , tweak ) == 0 );
472
+ CHECK (ecount == 2 );
473
+ /* Only pubkey part of keypair invalid */
474
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
475
+ memset (& keypair .data [32 ], 0 , 64 );
476
+ CHECK (secp256k1_keypair_xonly_tweak_add (verify , & keypair , tweak ) == 0 );
477
+ CHECK (ecount == 3 );
478
+
479
+ /* Check that the keypair_tweak_add implementation is correct */
480
+ CHECK (secp256k1_keypair_create (ctx , & keypair , sk ) == 1 );
481
+ for (i = 0 ; i < count ; i ++ ) {
482
+ secp256k1_xonly_pubkey internal_pk ;
483
+ secp256k1_xonly_pubkey output_pk ;
484
+ secp256k1_pubkey output_pk_xy ;
485
+ secp256k1_pubkey output_pk_expected ;
486
+ unsigned char pk32 [32 ];
487
+ int pk_parity ;
488
+
489
+ secp256k1_rand256 (tweak );
490
+ CHECK (secp256k1_keypair_xonly_pub (ctx , & internal_pk , NULL , & keypair ) == 1 );
491
+ CHECK (secp256k1_keypair_xonly_tweak_add (ctx , & keypair , tweak ) == 1 );
492
+ CHECK (secp256k1_keypair_xonly_pub (ctx , & output_pk , & pk_parity , & keypair ) == 1 );
493
+
494
+ /* Check that it passes xonly_pubkey_tweak_add_check */
495
+ CHECK (secp256k1_xonly_pubkey_serialize (ctx , pk32 , & output_pk ) == 1 );
496
+ CHECK (secp256k1_xonly_pubkey_tweak_add_check (ctx , pk32 , pk_parity , & internal_pk , tweak ) == 1 );
497
+
498
+ /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */
499
+ CHECK (secp256k1_keypair_pub (ctx , & output_pk_xy , & keypair ) == 1 );
500
+ CHECK (secp256k1_xonly_pubkey_tweak_add (ctx , & output_pk_expected , & internal_pk , tweak ) == 1 );
501
+ CHECK (memcmp (& output_pk_xy , & output_pk_expected , sizeof (output_pk_xy )) == 0 );
502
+
503
+ /* Check that the secret key in the keypair is tweaked correctly */
504
+ CHECK (secp256k1_ec_pubkey_create (ctx , & output_pk_expected , & keypair .data [0 ]) == 1 );
505
+ CHECK (memcmp (& output_pk_xy , & output_pk_expected , sizeof (output_pk_xy )) == 0 );
506
+ }
507
+ secp256k1_context_destroy (none );
508
+ secp256k1_context_destroy (sign );
509
+ secp256k1_context_destroy (verify );
510
+ }
511
+
404
512
void run_extrakeys_tests (void ) {
405
513
/* xonly key test cases */
406
514
test_xonly_pubkey ();
@@ -410,6 +518,7 @@ void run_extrakeys_tests(void) {
410
518
411
519
/* keypair tests */
412
520
test_keypair ();
521
+ test_keypair_add ();
413
522
}
414
523
415
524
#endif
0 commit comments