@@ -228,47 +228,67 @@ impl SecretKey {
228228 }
229229 }
230230
231- #[ inline]
232231 /// Adds one secret key to another, modulo the curve order.
233232 ///
234233 /// # Errors
235234 ///
236235 /// 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 > {
241251 unsafe {
242252 if ffi:: secp256k1_ec_seckey_tweak_add (
243253 ffi:: secp256k1_context_no_precomp,
244254 self . as_mut_c_ptr ( ) ,
245- other . as_c_ptr ( ) ,
255+ tweak . as_c_ptr ( ) ,
246256 ) != 1
247257 {
248258 Err ( Error :: InvalidTweak )
249259 } else {
250- Ok ( ( ) )
260+ Ok ( self )
251261 }
252262 }
253263 }
254264
255- #[ inline]
256265 /// Multiplies one secret key by another, modulo the curve order. Will
257266 /// 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 > {
262282 unsafe {
263283 if ffi:: secp256k1_ec_seckey_tweak_mul (
264284 ffi:: secp256k1_context_no_precomp,
265285 self . as_mut_c_ptr ( ) ,
266- other . as_c_ptr ( ) ,
286+ tweak . as_c_ptr ( ) ,
267287 ) != 1
268288 {
269289 Err ( Error :: InvalidTweak )
270290 } else {
271- Ok ( ( ) )
291+ Ok ( self )
272292 }
273293 }
274294 }
@@ -490,40 +510,72 @@ impl PublicKey {
490510 }
491511 }
492512
493- #[ inline]
494513 /// Adds `other * G` to `self` in place.
495514 ///
496515 /// # Errors
497516 ///
498517 /// Returns an error if the resulting key would be invalid.
518+ #[ inline]
519+ #[ deprecated( since = "0.23.0" , note = "Use add_exp_tweak instead" ) ]
499520 pub fn add_exp_assign < C : Verification > (
500521 & mut self ,
501522 secp : & Secp256k1 < C > ,
502523 other : & Scalar
503524 ) -> 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 > {
504540 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 )
507543 } else {
508544 Err ( Error :: InvalidTweak )
509545 }
510546 }
511547 }
512548
513- #[ inline]
514549 /// Muliplies the public key in place by the scalar `other`.
515550 ///
516551 /// # Errors
517552 ///
518553 /// Returns an error if the resulting key would be invalid.
554+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
555+ #[ inline]
519556 pub fn mul_assign < C : Verification > (
520557 & mut self ,
521558 secp : & Secp256k1 < C > ,
522559 other : & Scalar ,
523560 ) -> 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 > {
524576 unsafe {
525577 if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
526- Ok ( ( ) )
578+ Ok ( self )
527579 } else {
528580 Err ( Error :: InvalidTweak )
529581 }
@@ -1474,6 +1526,8 @@ pub mod serde_keypair {
14741526#[ cfg( test) ]
14751527#[ allow( unused_imports) ]
14761528mod test {
1529+ use super :: * ;
1530+
14771531 use core:: str:: FromStr ;
14781532
14791533 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
@@ -1738,48 +1792,69 @@ mod test {
17381792 }
17391793
17401794 #[ test]
1741- #[ cfg( any ( feature = "alloc" , feature = " std") ) ]
1742- fn test_addition ( ) {
1795+ #[ cfg( feature = "rand- std" ) ]
1796+ fn tweak_add_arbitrary_data ( ) {
17431797 let s = Secp256k1 :: new ( ) ;
17441798
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 ( ) ;
17491804
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 ) ;
17541809
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) ;
17591811 }
17601812
17611813 #[ test]
17621814 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1763- fn test_multiplication ( ) {
1815+ fn tweak_add_zero ( ) {
17641816 let s = Secp256k1 :: new ( ) ;
17651817
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 ( ) ) ;
17701819
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 ;
17751821
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 ) ;
17801826 }
17811827
17821828 #[ 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]
17831858 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
17841859 fn test_negation ( ) {
17851860 let s = Secp256k1 :: new ( ) ;
@@ -1882,7 +1957,7 @@ mod test {
18821957 fn create_pubkey_combine ( ) {
18831958 let s = Secp256k1 :: new ( ) ;
18841959
1885- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1960+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
18861961 let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
18871962
18881963 let sum1 = pk1. combine ( & pk2) ;
@@ -1891,8 +1966,8 @@ mod test {
18911966 assert ! ( sum2. is_ok( ) ) ;
18921967 assert_eq ! ( sum1, sum2) ;
18931968
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 ) ;
18961971 assert_eq ! ( Ok ( sksum) , sum1) ;
18971972 }
18981973
0 commit comments