@@ -148,6 +148,20 @@ impl SecretKey {
148148 }
149149 }
150150
151+ #[ inline]
152+ /// Negates one secret key.
153+ pub fn negate_assign (
154+ & mut self
155+ ) {
156+ unsafe {
157+ let res = ffi:: secp256k1_ec_privkey_negate (
158+ ffi:: secp256k1_context_no_precomp,
159+ self . as_mut_c_ptr ( )
160+ ) ;
161+ debug_assert_eq ! ( res, 1 ) ;
162+ }
163+ }
164+
151165 #[ inline]
152166 /// Adds one secret key to another, modulo the curve order. WIll
153167 /// return an error if the resulting key would be invalid or if
@@ -291,6 +305,19 @@ impl PublicKey {
291305 ret
292306 }
293307
308+ #[ inline]
309+ /// Negates the pk to the pk `self` in place
310+ /// Will return an error if the pk would be invalid.
311+ pub fn negate_assign < C : Verification > (
312+ & mut self ,
313+ secp : & Secp256k1 < C >
314+ ) {
315+ unsafe {
316+ let res = ffi:: secp256k1_ec_pubkey_negate ( secp. ctx , & mut self . 0 as * mut _ ) ;
317+ debug_assert_eq ! ( res, 1 ) ;
318+ }
319+ }
320+
294321 #[ inline]
295322 /// Adds the pk corresponding to `other` to the pk `self` in place
296323 /// Will return an error if the resulting key would be invalid or
@@ -752,6 +779,27 @@ mod test {
752779 assert_eq ! ( PublicKey :: from_secret_key( & s, & sk2) , pk2) ;
753780 }
754781
782+ #[ test]
783+ fn test_negation ( ) {
784+ let s = Secp256k1 :: new ( ) ;
785+
786+ let ( mut sk, mut pk) = s. generate_keypair ( & mut thread_rng ( ) ) ;
787+
788+ let original_sk = sk;
789+ let original_pk = pk;
790+
791+ assert_eq ! ( PublicKey :: from_secret_key( & s, & sk) , pk) ;
792+ sk. negate_assign ( ) ;
793+ pk. negate_assign ( & s) ;
794+ assert_ne ! ( original_sk, sk) ;
795+ assert_ne ! ( original_pk, pk) ;
796+ sk. negate_assign ( ) ;
797+ pk. negate_assign ( & s) ;
798+ assert_eq ! ( original_sk, sk) ;
799+ assert_eq ! ( original_pk, pk) ;
800+ assert_eq ! ( PublicKey :: from_secret_key( & s, & sk) , pk) ;
801+ }
802+
755803 #[ test]
756804 fn pubkey_hash ( ) {
757805 use std:: collections:: hash_map:: DefaultHasher ;
0 commit comments