@@ -228,47 +228,67 @@ impl SecretKey {
228
228
}
229
229
}
230
230
231
- #[ inline]
232
231
/// Adds one secret key to another, modulo the curve order.
233
232
///
234
233
/// # Errors
235
234
///
236
235
/// Returns an error if the resulting key would be invalid.
237
- pub fn add_assign (
238
- & mut self ,
239
- other : & Scalar ,
240
- ) -> Result < ( ) , Error > {
236
+ #[ inline]
237
+ #[ deprecated( since = "0.23.0" , note = "Use add_tweak instead" ) ]
238
+ pub fn add_assign ( & mut self , other : & Scalar ) -> Result < ( ) , Error > {
239
+ * self = self . add_tweak ( other) ?;
240
+ Ok ( ( ) )
241
+ }
242
+
243
+ /// Tweaks a [`SecretKey`] by adding `tweak` modulo the curve order.
244
+ ///
245
+ /// # Errors
246
+ ///
247
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
248
+ /// length slice.
249
+ #[ inline]
250
+ pub fn add_tweak ( mut self , tweak : & Scalar ) -> Result < SecretKey , Error > {
241
251
unsafe {
242
252
if ffi:: secp256k1_ec_seckey_tweak_add (
243
253
ffi:: secp256k1_context_no_precomp,
244
254
self . as_mut_c_ptr ( ) ,
245
- other . as_c_ptr ( ) ,
255
+ tweak . as_c_ptr ( ) ,
246
256
) != 1
247
257
{
248
258
Err ( Error :: InvalidTweak )
249
259
} else {
250
- Ok ( ( ) )
260
+ Ok ( self )
251
261
}
252
262
}
253
263
}
254
264
255
- #[ inline]
256
265
/// Multiplies one secret key by another, modulo the curve order. Will
257
266
/// return an error if the resulting key would be invalid.
258
- pub fn mul_assign (
259
- & mut self ,
260
- other : & Scalar ,
261
- ) -> Result < ( ) , Error > {
267
+ #[ inline]
268
+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
269
+ pub fn mul_assign ( & mut self , other : & Scalar ) -> Result < ( ) , Error > {
270
+ * self = self . mul_tweak ( other) ?;
271
+ Ok ( ( ) )
272
+ }
273
+
274
+ /// Tweaks a [`SecretKey`] by multiplying by `tweak` modulo the curve order.
275
+ ///
276
+ /// # Errors
277
+ ///
278
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
279
+ /// length slice.
280
+ #[ inline]
281
+ pub fn mul_tweak ( mut self , tweak : & Scalar ) -> Result < SecretKey , Error > {
262
282
unsafe {
263
283
if ffi:: secp256k1_ec_seckey_tweak_mul (
264
284
ffi:: secp256k1_context_no_precomp,
265
285
self . as_mut_c_ptr ( ) ,
266
- other . as_c_ptr ( ) ,
286
+ tweak . as_c_ptr ( ) ,
267
287
) != 1
268
288
{
269
289
Err ( Error :: InvalidTweak )
270
290
} else {
271
- Ok ( ( ) )
291
+ Ok ( self )
272
292
}
273
293
}
274
294
}
@@ -490,40 +510,72 @@ impl PublicKey {
490
510
}
491
511
}
492
512
493
- #[ inline]
494
513
/// Adds `other * G` to `self` in place.
495
514
///
496
515
/// # Errors
497
516
///
498
517
/// Returns an error if the resulting key would be invalid.
518
+ #[ inline]
519
+ #[ deprecated( since = "0.23.0" , note = "Use add_exp_tweak instead" ) ]
499
520
pub fn add_exp_assign < C : Verification > (
500
521
& mut self ,
501
522
secp : & Secp256k1 < C > ,
502
523
other : & Scalar
503
524
) -> Result < ( ) , Error > {
525
+ * self = self . add_exp_tweak ( secp, other) ?;
526
+ Ok ( ( ) )
527
+ }
528
+
529
+ /// Tweaks a [`PublicKey`] by adding `tweak * G` modulo the curve order.
530
+ ///
531
+ /// # Errors
532
+ ///
533
+ /// Returns an error if the resulting key would be invalid.
534
+ #[ inline]
535
+ pub fn add_exp_tweak < C : Verification > (
536
+ mut self ,
537
+ secp : & Secp256k1 < C > ,
538
+ tweak : & Scalar
539
+ ) -> Result < PublicKey , Error > {
504
540
unsafe {
505
- if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , other . as_c_ptr ( ) ) == 1 {
506
- Ok ( ( ) )
541
+ if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , tweak . as_c_ptr ( ) ) == 1 {
542
+ Ok ( self )
507
543
} else {
508
544
Err ( Error :: InvalidTweak )
509
545
}
510
546
}
511
547
}
512
548
513
- #[ inline]
514
549
/// Muliplies the public key in place by the scalar `other`.
515
550
///
516
551
/// # Errors
517
552
///
518
553
/// Returns an error if the resulting key would be invalid.
554
+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
555
+ #[ inline]
519
556
pub fn mul_assign < C : Verification > (
520
557
& mut self ,
521
558
secp : & Secp256k1 < C > ,
522
559
other : & Scalar ,
523
560
) -> Result < ( ) , Error > {
561
+ * self = self . mul_tweak ( secp, other) ?;
562
+ Ok ( ( ) )
563
+ }
564
+
565
+ /// Tweaks a [`PublicKey`] by multiplying by `tweak` modulo the curve order.
566
+ ///
567
+ /// # Errors
568
+ ///
569
+ /// Returns an error if the resulting key would be invalid.
570
+ #[ inline]
571
+ pub fn mul_tweak < C : Verification > (
572
+ mut self ,
573
+ secp : & Secp256k1 < C > ,
574
+ other : & Scalar ,
575
+ ) -> Result < PublicKey , Error > {
524
576
unsafe {
525
577
if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
526
- Ok ( ( ) )
578
+ Ok ( self )
527
579
} else {
528
580
Err ( Error :: InvalidTweak )
529
581
}
@@ -1474,6 +1526,8 @@ pub mod serde_keypair {
1474
1526
#[ cfg( test) ]
1475
1527
#[ allow( unused_imports) ]
1476
1528
mod test {
1529
+ use super :: * ;
1530
+
1477
1531
use core:: str:: FromStr ;
1478
1532
1479
1533
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
@@ -1738,48 +1792,69 @@ mod test {
1738
1792
}
1739
1793
1740
1794
#[ test]
1741
- #[ cfg( any ( feature = "alloc" , feature = " std") ) ]
1742
- fn test_addition ( ) {
1795
+ #[ cfg( feature = "rand- std" ) ]
1796
+ fn tweak_add_arbitrary_data ( ) {
1743
1797
let s = Secp256k1 :: new ( ) ;
1744
1798
1745
- let ( mut sk1, mut pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1746
- let ( mut sk2, mut pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1747
- let scalar1 = Scalar :: from ( sk1) ;
1748
- let scalar2 = Scalar :: from ( sk1) ;
1799
+ let ( sk, pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1800
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & sk) , pk) ; // Sanity check.
1801
+
1802
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1803
+ let tweak = Scalar :: random ( ) ;
1749
1804
1750
- assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk1 ) , pk1 ) ;
1751
- assert ! ( sk1 . add_assign ( & scalar2 ) . is_ok ( ) ) ;
1752
- assert ! ( pk1 . add_exp_assign ( & s, & scalar2 ) . is_ok ( ) ) ;
1753
- assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk1 ) , pk1 ) ;
1805
+ let tweaked_sk = sk . add_tweak ( & tweak ) . unwrap ( ) ;
1806
+ assert_ne ! ( sk , tweaked_sk ) ; // Make sure we did something.
1807
+ let tweaked_pk = pk . add_exp_tweak ( & s, & tweak ) . unwrap ( ) ;
1808
+ assert_ne ! ( pk , tweaked_pk ) ;
1754
1809
1755
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1756
- assert ! ( sk2. add_assign( & scalar1) . is_ok( ) ) ;
1757
- assert ! ( pk2. add_exp_assign( & s, & scalar1) . is_ok( ) ) ;
1758
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1810
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1759
1811
}
1760
1812
1761
1813
#[ test]
1762
1814
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1763
- fn test_multiplication ( ) {
1815
+ fn tweak_add_zero ( ) {
1764
1816
let s = Secp256k1 :: new ( ) ;
1765
1817
1766
- let ( mut sk1, mut pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1767
- let ( mut sk2, mut pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1768
- let scalar1 = Scalar :: from ( sk1) ;
1769
- let scalar2 = Scalar :: from ( sk1) ;
1818
+ let ( sk, pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1770
1819
1771
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1772
- assert ! ( sk1. mul_assign( & scalar2) . is_ok( ) ) ;
1773
- assert ! ( pk1. mul_assign( & s, & scalar2) . is_ok( ) ) ;
1774
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1820
+ let tweak = Scalar :: ZERO ;
1775
1821
1776
- assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk2 ) , pk2 ) ;
1777
- assert ! ( sk2 . mul_assign ( & scalar1 ) . is_ok ( ) ) ;
1778
- assert ! ( pk2 . mul_assign ( & s, & scalar1 ) . is_ok ( ) ) ;
1779
- assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk2 ) , pk2 ) ;
1822
+ let tweaked_sk = sk . add_tweak ( & tweak ) . unwrap ( ) ;
1823
+ assert_eq ! ( sk , tweaked_sk ) ; // Tweak by zero does nothing.
1824
+ let tweaked_pk = pk . add_exp_tweak ( & s, & tweak ) . unwrap ( ) ;
1825
+ assert_eq ! ( pk , tweaked_pk ) ;
1780
1826
}
1781
1827
1782
1828
#[ test]
1829
+ #[ cfg( feature = "rand-std" ) ]
1830
+ fn tweak_mul_arbitrary_data ( ) {
1831
+ let s = Secp256k1 :: new ( ) ;
1832
+
1833
+ let ( sk, pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1834
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & sk) , pk) ; // Sanity check.
1835
+
1836
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1837
+ let tweak = Scalar :: random ( ) ;
1838
+
1839
+ let tweaked_sk = sk. mul_tweak ( & tweak) . unwrap ( ) ;
1840
+ assert_ne ! ( sk, tweaked_sk) ; // Make sure we did something.
1841
+ let tweaked_pk = pk. mul_tweak ( & s, & tweak) . unwrap ( ) ;
1842
+ assert_ne ! ( pk, tweaked_pk) ;
1843
+
1844
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1845
+ }
1846
+
1847
+ #[ test]
1848
+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1849
+ fn tweak_mul_zero ( ) {
1850
+ let s = Secp256k1 :: new ( ) ;
1851
+ let ( sk, _) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1852
+
1853
+ let tweak = Scalar :: ZERO ;
1854
+ assert ! ( sk. mul_tweak( & tweak) . is_err( ) )
1855
+ }
1856
+
1857
+ #[ test]
1783
1858
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1784
1859
fn test_negation ( ) {
1785
1860
let s = Secp256k1 :: new ( ) ;
@@ -1882,7 +1957,7 @@ mod test {
1882
1957
fn create_pubkey_combine ( ) {
1883
1958
let s = Secp256k1 :: new ( ) ;
1884
1959
1885
- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1960
+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1886
1961
let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1887
1962
1888
1963
let sum1 = pk1. combine ( & pk2) ;
@@ -1891,8 +1966,8 @@ mod test {
1891
1966
assert ! ( sum2. is_ok( ) ) ;
1892
1967
assert_eq ! ( sum1, sum2) ;
1893
1968
1894
- assert ! ( sk1. add_assign ( & Scalar :: from( sk2) ) . is_ok ( ) ) ;
1895
- let sksum = PublicKey :: from_secret_key ( & s, & sk1 ) ;
1969
+ let tweaked = sk1. add_tweak ( & Scalar :: from ( sk2) ) . unwrap ( ) ;
1970
+ let sksum = PublicKey :: from_secret_key ( & s, & tweaked ) ;
1896
1971
assert_eq ! ( Ok ( sksum) , sum1) ;
1897
1972
}
1898
1973
0 commit comments