Skip to content

Commit d45f709

Browse files
committed
Add negation support
1 parent a5147bb commit d45f709

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

secp256k1-sys/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@ extern "C" {
243243
//TODO secp256k1_ec_privkey_export
244244
//TODO secp256k1_ec_privkey_import
245245

246+
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_privkey_negate")]
247+
pub fn secp256k1_ec_privkey_negate(cx: *const Context,
248+
sk: *mut c_uchar) -> c_int;
249+
250+
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_pubkey_negate")]
251+
pub fn secp256k1_ec_pubkey_negate(cx: *const Context,
252+
pk: *mut PublicKey) -> c_int;
253+
246254
#[cfg_attr(not(feature = "external-symbols"), link_name = "rustsecp256k1_v0_1_1_ec_privkey_tweak_add")]
247255
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
248256
sk: *mut c_uchar,

src/key.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ impl SecretKey {
148148
}
149149
}
150150

151+
#[inline]
152+
/// Negates one secret key.
153+
pub fn negate_assign(
154+
&mut self
155+
) {
156+
unsafe {
157+
ffi::secp256k1_ec_privkey_negate(
158+
ffi::secp256k1_context_no_precomp,
159+
self.as_mut_c_ptr()
160+
);
161+
}
162+
}
163+
151164
#[inline]
152165
/// Adds one secret key to another, modulo the curve order. WIll
153166
/// return an error if the resulting key would be invalid or if
@@ -291,6 +304,22 @@ impl PublicKey {
291304
ret
292305
}
293306

307+
#[inline]
308+
/// Negates the pk to the pk `self` in place
309+
/// Will return an error if the pk would be invalid.
310+
pub fn negate_assign<C: Verification>(
311+
&mut self,
312+
secp: &Secp256k1<C>
313+
) -> Result<(), Error> {
314+
unsafe {
315+
if ffi::secp256k1_ec_pubkey_negate(secp.ctx, &mut self.0 as *mut _) == 1 {
316+
Ok(())
317+
} else {
318+
Err(Error::InvalidPublicKey)
319+
}
320+
}
321+
}
322+
294323
#[inline]
295324
/// Adds the pk corresponding to `other` to the pk `self` in place
296325
/// Will return an error if the resulting key would be invalid or
@@ -752,6 +781,27 @@ mod test {
752781
assert_eq!(PublicKey::from_secret_key(&s, &sk2), pk2);
753782
}
754783

784+
#[test]
785+
fn test_negation() {
786+
let s = Secp256k1::new();
787+
788+
let (mut sk, mut pk) = s.generate_keypair(&mut thread_rng());
789+
790+
let original_sk = sk;
791+
let original_pk = pk;
792+
793+
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk);
794+
sk.negate_assign();
795+
assert!(pk.negate_assign(&s).is_ok());
796+
assert_ne!(original_sk, sk);
797+
assert_ne!(original_pk, pk);
798+
sk.negate_assign();
799+
assert!(pk.negate_assign(&s).is_ok());
800+
assert_eq!(original_sk, sk);
801+
assert_eq!(original_pk, pk);
802+
assert_eq!(PublicKey::from_secret_key(&s, &sk), pk);
803+
}
804+
755805
#[test]
756806
fn pubkey_hash() {
757807
use std::collections::hash_map::DefaultHasher;

0 commit comments

Comments
 (0)