@@ -227,55 +227,75 @@ impl SecretKey {
227227 }
228228 }
229229
230- #[ inline]
231230 /// Adds one secret key to another, modulo the curve order.
232231 ///
233232 /// # Errors
234233 ///
235234 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
236235 /// 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 {
242252 return Err ( Error :: InvalidTweak ) ;
243253 }
244254 unsafe {
245255 if ffi:: secp256k1_ec_seckey_tweak_add (
246256 ffi:: secp256k1_context_no_precomp,
247257 self . as_mut_c_ptr ( ) ,
248- other . as_c_ptr ( ) ,
258+ tweak . as_c_ptr ( ) ,
249259 ) != 1
250260 {
251261 Err ( Error :: InvalidTweak )
252262 } else {
253- Ok ( ( ) )
263+ Ok ( self )
254264 }
255265 }
256266 }
257267
258- #[ inline]
259268 /// Multiplies one secret key by another, modulo the curve order. Will
260269 /// return an error if the resulting key would be invalid or if
261270 /// 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 {
267287 return Err ( Error :: InvalidTweak ) ;
268288 }
269289 unsafe {
270290 if ffi:: secp256k1_ec_seckey_tweak_mul (
271291 ffi:: secp256k1_context_no_precomp,
272292 self . as_mut_c_ptr ( ) ,
273- other . as_c_ptr ( ) ,
293+ tweak . as_c_ptr ( ) ,
274294 ) != 1
275295 {
276296 Err ( Error :: InvalidTweak )
277297 } else {
278- Ok ( ( ) )
298+ Ok ( self )
279299 }
280300 }
281301 }
@@ -497,48 +517,82 @@ impl PublicKey {
497517 }
498518 }
499519
500- #[ inline]
501520 /// Adds the `other` public key to `self` in place.
502521 ///
503522 /// # Errors
504523 ///
505524 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
506525 /// length slice.
526+ #[ inline]
527+ #[ deprecated( since = "0.23.0" , note = "Use add_tweak instead" ) ]
507528 pub fn add_exp_assign < C : Verification > (
508529 & mut self ,
509530 secp : & Secp256k1 < C > ,
510531 other : & [ u8 ]
511532 ) -> 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 {
513550 return Err ( Error :: InvalidTweak ) ;
514551 }
515552 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 )
518555 } else {
519556 Err ( Error :: InvalidTweak )
520557 }
521558 }
522559 }
523560
524- #[ inline]
525561 /// Muliplies the public key in place by the scalar `other`.
526562 ///
527563 /// # Errors
528564 ///
529565 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
530566 /// length slice.
567+ #[ deprecated( since = "0.23.0" , note = "Use mul_tweak instead" ) ]
568+ #[ inline]
531569 pub fn mul_assign < C : Verification > (
532570 & mut self ,
533571 secp : & Secp256k1 < C > ,
534572 other : & [ u8 ] ,
535573 ) -> 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 > {
536590 if other. len ( ) != 32 {
537591 return Err ( Error :: InvalidTweak ) ;
538592 }
539593 unsafe {
540594 if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
541- Ok ( ( ) )
595+ Ok ( self )
542596 } else {
543597 Err ( Error :: InvalidTweak )
544598 }
@@ -1501,6 +1555,8 @@ pub mod serde_keypair {
15011555#[ cfg( test) ]
15021556#[ allow( unused_imports) ]
15031557mod test {
1558+ use super :: * ;
1559+
15041560 use core:: str:: FromStr ;
15051561
15061562 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
@@ -1765,43 +1821,68 @@ mod test {
17651821
17661822 #[ test]
17671823 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1768- fn test_addition ( ) {
1824+ fn tweak_add_arbitrary_data ( ) {
17691825 let s = Secp256k1 :: new ( ) ;
17701826
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.
17731829
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 ( ) ) ;
17781832
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) ;
17831839 }
17841840
17851841 #[ test]
17861842 #[ 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 ( ) {
17881859 let s = Secp256k1 :: new ( ) ;
17891860
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.
17921863
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 ( ) ) ;
17971866
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) ;
18021873 }
18031874
18041875 #[ 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]
18051886 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
18061887 fn test_negation ( ) {
18071888 let s = Secp256k1 :: new ( ) ;
@@ -1904,7 +1985,7 @@ mod test {
19041985 fn create_pubkey_combine ( ) {
19051986 let s = Secp256k1 :: new ( ) ;
19061987
1907- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1988+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
19081989 let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
19091990
19101991 let sum1 = pk1. combine ( & pk2) ;
@@ -1913,8 +1994,8 @@ mod test {
19131994 assert ! ( sum2. is_ok( ) ) ;
19141995 assert_eq ! ( sum1, sum2) ;
19151996
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 ) ;
19181999 assert_eq ! ( Ok ( sksum) , sum1) ;
19192000 }
19202001
0 commit comments