@@ -232,55 +232,75 @@ impl SecretKey {
232
232
}
233
233
}
234
234
235
- #[ inline]
236
235
/// Adds one secret key to another, modulo the curve order.
237
236
///
238
237
/// # Errors
239
238
///
240
239
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
241
240
/// length slice.
242
- pub fn add_assign (
243
- & mut self ,
244
- other : & [ u8 ] ,
245
- ) -> Result < ( ) , Error > {
246
- if other. len ( ) != 32 {
241
+ #[ inline]
242
+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use add_tweak instead" ) ]
243
+ pub fn add_assign ( & mut self , other : & [ u8 ] ) -> Result < ( ) , Error > {
244
+ * self = self . add_tweak ( other) ?;
245
+ Ok ( ( ) )
246
+ }
247
+
248
+ /// Tweaks a [`SecretKey`] by adding `tweak` modulo the curve order.
249
+ ///
250
+ /// # Errors
251
+ ///
252
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
253
+ /// length slice.
254
+ #[ inline]
255
+ pub fn add_tweak ( mut self , tweak : & [ u8 ] ) -> Result < SecretKey , Error > {
256
+ if tweak. len ( ) != 32 {
247
257
return Err ( Error :: InvalidTweak ) ;
248
258
}
249
259
unsafe {
250
260
if ffi:: secp256k1_ec_seckey_tweak_add (
251
261
ffi:: secp256k1_context_no_precomp,
252
262
self . as_mut_c_ptr ( ) ,
253
- other . as_c_ptr ( ) ,
263
+ tweak . as_c_ptr ( ) ,
254
264
) != 1
255
265
{
256
266
Err ( Error :: InvalidTweak )
257
267
} else {
258
- Ok ( ( ) )
268
+ Ok ( self )
259
269
}
260
270
}
261
271
}
262
272
263
- #[ inline]
264
273
/// Multiplies one secret key by another, modulo the curve order. Will
265
274
/// return an error if the resulting key would be invalid or if
266
275
/// the tweak was not a 32-byte length slice.
267
- pub fn mul_assign (
268
- & mut self ,
269
- other : & [ u8 ] ,
270
- ) -> Result < ( ) , Error > {
271
- if other. len ( ) != 32 {
276
+ #[ inline]
277
+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use mul_tweak instead" ) ]
278
+ pub fn mul_assign ( & mut self , other : & [ u8 ] ) -> Result < ( ) , Error > {
279
+ * self = self . mul_tweak ( other) ?;
280
+ Ok ( ( ) )
281
+ }
282
+
283
+ /// Tweaks a [`SecretKey`] by multiplying by `tweak` modulo the curve order.
284
+ ///
285
+ /// # Errors
286
+ ///
287
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
288
+ /// length slice.
289
+ #[ inline]
290
+ pub fn mul_tweak ( mut self , tweak : & [ u8 ] ) -> Result < SecretKey , Error > {
291
+ if tweak. len ( ) != 32 {
272
292
return Err ( Error :: InvalidTweak ) ;
273
293
}
274
294
unsafe {
275
295
if ffi:: secp256k1_ec_seckey_tweak_mul (
276
296
ffi:: secp256k1_context_no_precomp,
277
297
self . as_mut_c_ptr ( ) ,
278
- other . as_c_ptr ( ) ,
298
+ tweak . as_c_ptr ( ) ,
279
299
) != 1
280
300
{
281
301
Err ( Error :: InvalidTweak )
282
302
} else {
283
- Ok ( ( ) )
303
+ Ok ( self )
284
304
}
285
305
}
286
306
}
@@ -470,48 +490,82 @@ impl PublicKey {
470
490
}
471
491
}
472
492
473
- #[ inline]
474
493
/// Adds the `other` public key to `self` in place.
475
494
///
476
495
/// # Errors
477
496
///
478
497
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
479
498
/// length slice.
499
+ #[ inline]
500
+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use add_tweak instead" ) ]
480
501
pub fn add_exp_assign < C : Verification > (
481
502
& mut self ,
482
503
secp : & Secp256k1 < C > ,
483
504
other : & [ u8 ]
484
505
) -> Result < ( ) , Error > {
485
- if other. len ( ) != 32 {
506
+ * self = self . add_tweak ( secp, other) ?;
507
+ Ok ( ( ) )
508
+ }
509
+
510
+ /// Tweaks a [`PublicKey`] by adding `tweak` modulo the curve order.
511
+ ///
512
+ /// # Errors
513
+ ///
514
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
515
+ /// length slice.
516
+ #[ inline]
517
+ pub fn add_tweak < C : Verification > (
518
+ mut self ,
519
+ secp : & Secp256k1 < C > ,
520
+ tweak : & [ u8 ]
521
+ ) -> Result < PublicKey , Error > {
522
+ if tweak. len ( ) != 32 {
486
523
return Err ( Error :: InvalidTweak ) ;
487
524
}
488
525
unsafe {
489
- if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , other . as_c_ptr ( ) ) == 1 {
490
- Ok ( ( ) )
526
+ if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , tweak . as_c_ptr ( ) ) == 1 {
527
+ Ok ( self )
491
528
} else {
492
529
Err ( Error :: InvalidTweak )
493
530
}
494
531
}
495
532
}
496
533
497
- #[ inline]
498
534
/// Muliplies the public key in place by the scalar `other`.
499
535
///
500
536
/// # Errors
501
537
///
502
538
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
503
539
/// length slice.
540
+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use mul_tweak instead" ) ]
541
+ #[ inline]
504
542
pub fn mul_assign < C : Verification > (
505
543
& mut self ,
506
544
secp : & Secp256k1 < C > ,
507
545
other : & [ u8 ] ,
508
546
) -> Result < ( ) , Error > {
547
+ * self = self . mul_tweak ( secp, other) ?;
548
+ Ok ( ( ) )
549
+ }
550
+
551
+ /// Tweaks a [`PublicKey`] by multiplying by `tweak` modulo the curve order.
552
+ ///
553
+ /// # Errors
554
+ ///
555
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
556
+ /// length slice.
557
+ #[ inline]
558
+ pub fn mul_tweak < C : Verification > (
559
+ mut self ,
560
+ secp : & Secp256k1 < C > ,
561
+ other : & [ u8 ] ,
562
+ ) -> Result < PublicKey , Error > {
509
563
if other. len ( ) != 32 {
510
564
return Err ( Error :: InvalidTweak ) ;
511
565
}
512
566
unsafe {
513
567
if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
514
- Ok ( ( ) )
568
+ Ok ( self )
515
569
} else {
516
570
Err ( Error :: InvalidTweak )
517
571
}
@@ -1740,43 +1794,68 @@ mod test {
1740
1794
1741
1795
#[ test]
1742
1796
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1743
- fn test_addition ( ) {
1797
+ fn tweak_add_arbitrary_data ( ) {
1744
1798
let s = Secp256k1 :: new ( ) ;
1745
1799
1746
- let ( mut sk1 , mut pk1 ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1747
- let ( mut sk2 , mut pk2 ) = s . generate_keypair ( & mut thread_rng ( ) ) ;
1800
+ let ( sk , pk ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1801
+ assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk ) , pk ) ; // Sanity check.
1748
1802
1749
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1750
- assert ! ( sk1. add_assign( & sk2[ ..] ) . is_ok( ) ) ;
1751
- assert ! ( pk1. add_exp_assign( & s, & sk2[ ..] ) . is_ok( ) ) ;
1752
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1803
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1804
+ let tweak = random_32_bytes ( & mut thread_rng ( ) ) ;
1753
1805
1754
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1755
- assert ! ( sk2. add_assign( & sk1[ ..] ) . is_ok( ) ) ;
1756
- assert ! ( pk2. add_exp_assign( & s, & sk1[ ..] ) . is_ok( ) ) ;
1757
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1806
+ let tweaked_sk = sk. add_tweak ( & tweak[ ..] ) . unwrap ( ) ;
1807
+ assert_ne ! ( sk, tweaked_sk) ; // Make sure we did something.
1808
+ let tweaked_pk = pk. add_tweak ( & s, & tweak[ ..] ) . unwrap ( ) ;
1809
+ assert_ne ! ( pk, tweaked_pk) ;
1810
+
1811
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1758
1812
}
1759
1813
1760
1814
#[ test]
1761
1815
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1762
- fn test_multiplication ( ) {
1816
+ fn tweak_add_zero ( ) {
1817
+ let s = Secp256k1 :: new ( ) ;
1818
+
1819
+ let ( sk, pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1820
+
1821
+ let tweak = & [ 0u8 ; 32 ] ;
1822
+
1823
+ let tweaked_sk = sk. add_tweak ( tweak) . unwrap ( ) ;
1824
+ assert_eq ! ( sk, tweaked_sk) ; // Tweak by zero does nothing.
1825
+ let tweaked_pk = pk. add_tweak ( & s, tweak) . unwrap ( ) ;
1826
+ assert_eq ! ( pk, tweaked_pk) ;
1827
+ }
1828
+
1829
+ #[ test]
1830
+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1831
+ fn tweak_mul_arbitrary_data ( ) {
1763
1832
let s = Secp256k1 :: new ( ) ;
1764
1833
1765
- let ( mut sk1 , mut pk1 ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1766
- let ( mut sk2 , mut pk2 ) = s . generate_keypair ( & mut thread_rng ( ) ) ;
1834
+ let ( sk , pk ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1835
+ assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk ) , pk ) ; // Sanity check.
1767
1836
1768
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1769
- assert ! ( sk1. mul_assign( & sk2[ ..] ) . is_ok( ) ) ;
1770
- assert ! ( pk1. mul_assign( & s, & sk2[ ..] ) . is_ok( ) ) ;
1771
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1837
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1838
+ let tweak = random_32_bytes ( & mut thread_rng ( ) ) ;
1772
1839
1773
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1774
- assert ! ( sk2. mul_assign( & sk1[ ..] ) . is_ok( ) ) ;
1775
- assert ! ( pk2. mul_assign( & s, & sk1[ ..] ) . is_ok( ) ) ;
1776
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1840
+ let tweaked_sk = sk. mul_tweak ( & tweak[ ..] ) . unwrap ( ) ;
1841
+ assert_ne ! ( sk, tweaked_sk) ; // Make sure we did something.
1842
+ let tweaked_pk = pk. mul_tweak ( & s, & tweak[ ..] ) . unwrap ( ) ;
1843
+ assert_ne ! ( pk, tweaked_pk) ;
1844
+
1845
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1777
1846
}
1778
1847
1779
1848
#[ test]
1849
+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1850
+ fn tweak_mul_zero ( ) {
1851
+ let s = Secp256k1 :: new ( ) ;
1852
+ let ( sk, _) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1853
+
1854
+ let tweak = & [ 0u8 ; 32 ] ;
1855
+ assert ! ( sk. mul_tweak( tweak) . is_err( ) )
1856
+ }
1857
+
1858
+ #[ test]
1780
1859
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1781
1860
fn test_negation ( ) {
1782
1861
let s = Secp256k1 :: new ( ) ;
@@ -1879,7 +1958,7 @@ mod test {
1879
1958
fn create_pubkey_combine ( ) {
1880
1959
let s = Secp256k1 :: new ( ) ;
1881
1960
1882
- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1961
+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1883
1962
let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1884
1963
1885
1964
let sum1 = pk1. combine ( & pk2) ;
@@ -1888,8 +1967,8 @@ mod test {
1888
1967
assert ! ( sum2. is_ok( ) ) ;
1889
1968
assert_eq ! ( sum1, sum2) ;
1890
1969
1891
- assert ! ( sk1. add_assign ( & sk2. as_ref( ) [ ..] ) . is_ok ( ) ) ;
1892
- let sksum = PublicKey :: from_secret_key ( & s, & sk1 ) ;
1970
+ let tweaked = sk1. add_tweak ( & sk2. as_ref ( ) [ ..] ) . unwrap ( ) ;
1971
+ let sksum = PublicKey :: from_secret_key ( & s, & tweaked ) ;
1893
1972
assert_eq ! ( Ok ( sksum) , sum1) ;
1894
1973
}
1895
1974
0 commit comments