@@ -227,55 +227,75 @@ impl SecretKey {
227
227
}
228
228
}
229
229
230
- #[ inline]
231
230
/// Adds one secret key to another, modulo the curve order.
232
231
///
233
232
/// # Errors
234
233
///
235
234
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
236
235
/// length slice.
237
- pub fn add_assign (
238
- & mut self ,
239
- other : & [ u8 ] ,
240
- ) -> Result < ( ) , Error > {
241
- if other. len ( ) != 32 {
236
+ #[ inline]
237
+ #[ deprecated( since = "0.23.0" , note = "Use add_tweak instead" ) ]
238
+ pub fn add_assign ( & mut self , other : & [ u8 ] ) -> 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 : & [ u8 ] ) -> Result < SecretKey , Error > {
251
+ if tweak. len ( ) != 32 {
242
252
return Err ( Error :: InvalidTweak ) ;
243
253
}
244
254
unsafe {
245
255
if ffi:: secp256k1_ec_seckey_tweak_add (
246
256
ffi:: secp256k1_context_no_precomp,
247
257
self . as_mut_c_ptr ( ) ,
248
- other . as_c_ptr ( ) ,
258
+ tweak . as_c_ptr ( ) ,
249
259
) != 1
250
260
{
251
261
Err ( Error :: InvalidTweak )
252
262
} else {
253
- Ok ( ( ) )
263
+ Ok ( self )
254
264
}
255
265
}
256
266
}
257
267
258
- #[ inline]
259
268
/// Multiplies one secret key by another, modulo the curve order. Will
260
269
/// return an error if the resulting key would be invalid or if
261
270
/// the tweak was not a 32-byte length slice.
262
- pub fn mul_assign (
263
- & mut self ,
264
- other : & [ u8 ] ,
265
- ) -> Result < ( ) , Error > {
266
- if other. len ( ) != 32 {
271
+ #[ inline]
272
+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
273
+ pub fn mul_assign ( & mut self , other : & [ u8 ] ) -> Result < ( ) , Error > {
274
+ * self = self . mul_tweak ( other) ?;
275
+ Ok ( ( ) )
276
+ }
277
+
278
+ /// Tweaks a [`SecretKey`] by multiplying by `tweak` modulo the curve order.
279
+ ///
280
+ /// # Errors
281
+ ///
282
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
283
+ /// length slice.
284
+ #[ inline]
285
+ pub fn mul_tweak ( mut self , tweak : & [ u8 ] ) -> Result < SecretKey , Error > {
286
+ if tweak. len ( ) != 32 {
267
287
return Err ( Error :: InvalidTweak ) ;
268
288
}
269
289
unsafe {
270
290
if ffi:: secp256k1_ec_seckey_tweak_mul (
271
291
ffi:: secp256k1_context_no_precomp,
272
292
self . as_mut_c_ptr ( ) ,
273
- other . as_c_ptr ( ) ,
293
+ tweak . as_c_ptr ( ) ,
274
294
) != 1
275
295
{
276
296
Err ( Error :: InvalidTweak )
277
297
} else {
278
- Ok ( ( ) )
298
+ Ok ( self )
279
299
}
280
300
}
281
301
}
@@ -497,48 +517,82 @@ impl PublicKey {
497
517
}
498
518
}
499
519
500
- #[ inline]
501
520
/// Adds the `other` public key to `self` in place.
502
521
///
503
522
/// # Errors
504
523
///
505
524
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
506
525
/// length slice.
526
+ #[ inline]
527
+ #[ deprecated( since = "0.23.0" , note = "Use add_tweak instead" ) ]
507
528
pub fn add_exp_assign < C : Verification > (
508
529
& mut self ,
509
530
secp : & Secp256k1 < C > ,
510
531
other : & [ u8 ]
511
532
) -> Result < ( ) , Error > {
512
- if other. len ( ) != 32 {
533
+ * self = self . add_tweak ( secp, other) ?;
534
+ Ok ( ( ) )
535
+ }
536
+
537
+ /// Tweaks a [`PublicKey`] by adding `tweak` modulo the curve order.
538
+ ///
539
+ /// # Errors
540
+ ///
541
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
542
+ /// length slice.
543
+ #[ inline]
544
+ pub fn add_tweak < C : Verification > (
545
+ mut self ,
546
+ secp : & Secp256k1 < C > ,
547
+ tweak : & [ u8 ]
548
+ ) -> Result < PublicKey , Error > {
549
+ if tweak. len ( ) != 32 {
513
550
return Err ( Error :: InvalidTweak ) ;
514
551
}
515
552
unsafe {
516
- if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , other . as_c_ptr ( ) ) == 1 {
517
- Ok ( ( ) )
553
+ if ffi:: secp256k1_ec_pubkey_tweak_add ( secp. ctx , & mut self . 0 , tweak . as_c_ptr ( ) ) == 1 {
554
+ Ok ( self )
518
555
} else {
519
556
Err ( Error :: InvalidTweak )
520
557
}
521
558
}
522
559
}
523
560
524
- #[ inline]
525
561
/// Muliplies the public key in place by the scalar `other`.
526
562
///
527
563
/// # Errors
528
564
///
529
565
/// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
530
566
/// length slice.
567
+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
568
+ #[ inline]
531
569
pub fn mul_assign < C : Verification > (
532
570
& mut self ,
533
571
secp : & Secp256k1 < C > ,
534
572
other : & [ u8 ] ,
535
573
) -> Result < ( ) , Error > {
574
+ * self = self . mul_tweak ( secp, other) ?;
575
+ Ok ( ( ) )
576
+ }
577
+
578
+ /// Tweaks a [`PublicKey`] by multiplying by `tweak` modulo the curve order.
579
+ ///
580
+ /// # Errors
581
+ ///
582
+ /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
583
+ /// length slice.
584
+ #[ inline]
585
+ pub fn mul_tweak < C : Verification > (
586
+ mut self ,
587
+ secp : & Secp256k1 < C > ,
588
+ other : & [ u8 ] ,
589
+ ) -> Result < PublicKey , Error > {
536
590
if other. len ( ) != 32 {
537
591
return Err ( Error :: InvalidTweak ) ;
538
592
}
539
593
unsafe {
540
594
if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
541
- Ok ( ( ) )
595
+ Ok ( self )
542
596
} else {
543
597
Err ( Error :: InvalidTweak )
544
598
}
@@ -1501,6 +1555,8 @@ pub mod serde_keypair {
1501
1555
#[ cfg( test) ]
1502
1556
#[ allow( unused_imports) ]
1503
1557
mod test {
1558
+ use super :: * ;
1559
+
1504
1560
use core:: str:: FromStr ;
1505
1561
1506
1562
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
@@ -1765,43 +1821,68 @@ mod test {
1765
1821
1766
1822
#[ test]
1767
1823
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1768
- fn test_addition ( ) {
1824
+ fn tweak_add_arbitrary_data ( ) {
1769
1825
let s = Secp256k1 :: new ( ) ;
1770
1826
1771
- let ( mut sk1 , mut pk1 ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1772
- let ( mut sk2 , mut pk2 ) = s . generate_keypair ( & mut thread_rng ( ) ) ;
1827
+ let ( sk , pk ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1828
+ assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk ) , pk ) ; // Sanity check.
1773
1829
1774
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1775
- assert ! ( sk1. add_assign( & sk2[ ..] ) . is_ok( ) ) ;
1776
- assert ! ( pk1. add_exp_assign( & s, & sk2[ ..] ) . is_ok( ) ) ;
1777
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1830
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1831
+ let tweak = random_32_bytes ( & mut thread_rng ( ) ) ;
1778
1832
1779
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1780
- assert ! ( sk2. add_assign( & sk1[ ..] ) . is_ok( ) ) ;
1781
- assert ! ( pk2. add_exp_assign( & s, & sk1[ ..] ) . is_ok( ) ) ;
1782
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1833
+ let tweaked_sk = sk. add_tweak ( & tweak[ ..] ) . unwrap ( ) ;
1834
+ assert_ne ! ( sk, tweaked_sk) ; // Make sure we did something.
1835
+ let tweaked_pk = pk. add_tweak ( & s, & tweak[ ..] ) . unwrap ( ) ;
1836
+ assert_ne ! ( pk, tweaked_pk) ;
1837
+
1838
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1783
1839
}
1784
1840
1785
1841
#[ test]
1786
1842
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1787
- fn test_multiplication ( ) {
1843
+ fn tweak_add_zero ( ) {
1844
+ let s = Secp256k1 :: new ( ) ;
1845
+
1846
+ let ( sk, pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1847
+
1848
+ let tweak = & [ 0u8 ; 32 ] ;
1849
+
1850
+ let tweaked_sk = sk. add_tweak ( tweak) . unwrap ( ) ;
1851
+ assert_eq ! ( sk, tweaked_sk) ; // Tweak by zero does nothing.
1852
+ let tweaked_pk = pk. add_tweak ( & s, tweak) . unwrap ( ) ;
1853
+ assert_eq ! ( pk, tweaked_pk) ;
1854
+ }
1855
+
1856
+ #[ test]
1857
+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1858
+ fn tweak_mul_arbitrary_data ( ) {
1788
1859
let s = Secp256k1 :: new ( ) ;
1789
1860
1790
- let ( mut sk1 , mut pk1 ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1791
- let ( mut sk2 , mut pk2 ) = s . generate_keypair ( & mut thread_rng ( ) ) ;
1861
+ let ( sk , pk ) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1862
+ assert_eq ! ( PublicKey :: from_secret_key ( & s , & sk ) , pk ) ; // Sanity check.
1792
1863
1793
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1794
- assert ! ( sk1. mul_assign( & sk2[ ..] ) . is_ok( ) ) ;
1795
- assert ! ( pk1. mul_assign( & s, & sk2[ ..] ) . is_ok( ) ) ;
1796
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk1) , pk1) ;
1864
+ // TODO: This would be better tested with a _lot_ of different tweaks.
1865
+ let tweak = random_32_bytes ( & mut thread_rng ( ) ) ;
1797
1866
1798
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1799
- assert ! ( sk2. mul_assign( & sk1[ ..] ) . is_ok( ) ) ;
1800
- assert ! ( pk2. mul_assign( & s, & sk1[ ..] ) . is_ok( ) ) ;
1801
- assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
1867
+ let tweaked_sk = sk. mul_tweak ( & tweak[ ..] ) . unwrap ( ) ;
1868
+ assert_ne ! ( sk, tweaked_sk) ; // Make sure we did something.
1869
+ let tweaked_pk = pk. mul_tweak ( & s, & tweak[ ..] ) . unwrap ( ) ;
1870
+ assert_ne ! ( pk, tweaked_pk) ;
1871
+
1872
+ assert_eq ! ( PublicKey :: from_secret_key( & s, & tweaked_sk) , tweaked_pk) ;
1802
1873
}
1803
1874
1804
1875
#[ test]
1876
+ #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1877
+ fn tweak_mul_zero ( ) {
1878
+ let s = Secp256k1 :: new ( ) ;
1879
+ let ( sk, _) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1880
+
1881
+ let tweak = & [ 0u8 ; 32 ] ;
1882
+ assert ! ( sk. mul_tweak( tweak) . is_err( ) )
1883
+ }
1884
+
1885
+ #[ test]
1805
1886
#[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1806
1887
fn test_negation ( ) {
1807
1888
let s = Secp256k1 :: new ( ) ;
@@ -1904,7 +1985,7 @@ mod test {
1904
1985
fn create_pubkey_combine ( ) {
1905
1986
let s = Secp256k1 :: new ( ) ;
1906
1987
1907
- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1988
+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1908
1989
let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1909
1990
1910
1991
let sum1 = pk1. combine ( & pk2) ;
@@ -1913,8 +1994,8 @@ mod test {
1913
1994
assert ! ( sum2. is_ok( ) ) ;
1914
1995
assert_eq ! ( sum1, sum2) ;
1915
1996
1916
- assert ! ( sk1. add_assign ( & sk2. as_ref( ) [ ..] ) . is_ok ( ) ) ;
1917
- let sksum = PublicKey :: from_secret_key ( & s, & sk1 ) ;
1997
+ let tweaked = sk1. add_tweak ( & sk2. as_ref ( ) [ ..] ) . unwrap ( ) ;
1998
+ let sksum = PublicKey :: from_secret_key ( & s, & tweaked ) ;
1918
1999
assert_eq ! ( Ok ( sksum) , sum1) ;
1919
2000
}
1920
2001
0 commit comments