@@ -232,55 +232,75 @@ impl SecretKey {
232232 }
233233 }
234234
235- #[ inline]
236235 /// Adds one secret key to another, modulo the curve order.
237236 ///
238237 /// # Errors
239238 ///
240239 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
241240 /// 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 {
247257 return Err ( Error :: InvalidTweak ) ;
248258 }
249259 unsafe {
250260 if ffi:: secp256k1_ec_seckey_tweak_add (
251261 ffi:: secp256k1_context_no_precomp,
252262 self . as_mut_c_ptr ( ) ,
253- other . as_c_ptr ( ) ,
263+ tweak . as_c_ptr ( ) ,
254264 ) != 1
255265 {
256266 Err ( Error :: InvalidTweak )
257267 } else {
258- Ok ( ( ) )
268+ Ok ( self )
259269 }
260270 }
261271 }
262272
263- #[ inline]
264273 /// Multiplies one secret key by another, modulo the curve order. Will
265274 /// return an error if the resulting key would be invalid or if
266275 /// 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 {
272292 return Err ( Error :: InvalidTweak ) ;
273293 }
274294 unsafe {
275295 if ffi:: secp256k1_ec_seckey_tweak_mul (
276296 ffi:: secp256k1_context_no_precomp,
277297 self . as_mut_c_ptr ( ) ,
278- other . as_c_ptr ( ) ,
298+ tweak . as_c_ptr ( ) ,
279299 ) != 1
280300 {
281301 Err ( Error :: InvalidTweak )
282302 } else {
283- Ok ( ( ) )
303+ Ok ( self )
284304 }
285305 }
286306 }
@@ -470,48 +490,82 @@ impl PublicKey {
470490 }
471491 }
472492
473- #[ inline]
474493 /// Adds the `other` public key to `self` in place.
475494 ///
476495 /// # Errors
477496 ///
478497 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
479498 /// length slice.
499+ #[ inline]
500+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use add_tweak instead" ) ]
480501 pub fn add_exp_assign < C : Verification > (
481502 & mut self ,
482503 secp : & Secp256k1 < C > ,
483504 other : & [ u8 ]
484505 ) -> 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 {
486523 return Err ( Error :: InvalidTweak ) ;
487524 }
488525 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 )
491528 } else {
492529 Err ( Error :: InvalidTweak )
493530 }
494531 }
495532 }
496533
497- #[ inline]
498534 /// Muliplies the public key in place by the scalar `other`.
499535 ///
500536 /// # Errors
501537 ///
502538 /// Returns an error if the resulting key would be invalid or if the tweak was not a 32-byte
503539 /// length slice.
540+ #[ deprecated( since = "TODO: Set this prior to release" , note = "Use mul_tweak instead" ) ]
541+ #[ inline]
504542 pub fn mul_assign < C : Verification > (
505543 & mut self ,
506544 secp : & Secp256k1 < C > ,
507545 other : & [ u8 ] ,
508546 ) -> 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 > {
509563 if other. len ( ) != 32 {
510564 return Err ( Error :: InvalidTweak ) ;
511565 }
512566 unsafe {
513567 if ffi:: secp256k1_ec_pubkey_tweak_mul ( secp. ctx , & mut self . 0 , other. as_c_ptr ( ) ) == 1 {
514- Ok ( ( ) )
568+ Ok ( self )
515569 } else {
516570 Err ( Error :: InvalidTweak )
517571 }
@@ -1740,43 +1794,68 @@ mod test {
17401794
17411795 #[ test]
17421796 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
1743- fn test_addition ( ) {
1797+ fn tweak_add_arbitrary_data ( ) {
17441798 let s = Secp256k1 :: new ( ) ;
17451799
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.
17481802
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 ( ) ) ;
17531805
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) ;
17581812 }
17591813
17601814 #[ test]
17611815 #[ 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 ( ) {
17631832 let s = Secp256k1 :: new ( ) ;
17641833
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.
17671836
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 ( ) ) ;
17721839
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) ;
17771846 }
17781847
17791848 #[ 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]
17801859 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
17811860 fn test_negation ( ) {
17821861 let s = Secp256k1 :: new ( ) ;
@@ -1879,7 +1958,7 @@ mod test {
18791958 fn create_pubkey_combine ( ) {
18801959 let s = Secp256k1 :: new ( ) ;
18811960
1882- let ( mut sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
1961+ let ( sk1, pk1) = s. generate_keypair ( & mut thread_rng ( ) ) ;
18831962 let ( sk2, pk2) = s. generate_keypair ( & mut thread_rng ( ) ) ;
18841963
18851964 let sum1 = pk1. combine ( & pk2) ;
@@ -1888,8 +1967,8 @@ mod test {
18881967 assert ! ( sum2. is_ok( ) ) ;
18891968 assert_eq ! ( sum1, sum2) ;
18901969
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 ) ;
18931972 assert_eq ! ( Ok ( sksum) , sum1) ;
18941973 }
18951974
0 commit comments