Skip to content

Commit 3692c94

Browse files
authored
Merge pull request #220 from rantan/add_negate_support
Add negate support
2 parents c6ab14b + 02ed061 commit 3692c94

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

secp256k1-sys/src/lib.rs

Lines changed: 22 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,
@@ -694,6 +702,20 @@ mod fuzz_dummy {
694702
//TODO secp256k1_ec_privkey_export
695703
//TODO secp256k1_ec_privkey_import
696704

705+
pub unsafe fn secp256k1_ec_privkey_negate(cx: *const Context,
706+
sk: *mut c_uchar) -> c_int {
707+
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
708+
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
709+
1
710+
}
711+
712+
pub unsafe fn secp256k1_ec_pubkey_negate(cx: *const Context,
713+
pk: *mut PublicKey) -> c_int {
714+
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
715+
if test_pk_validate(cx, pk) != 1 { return 0; }
716+
1
717+
}
718+
697719
/// Copies the first 16 bytes of tweak into the last 16 bytes of sk
698720
pub unsafe fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
699721
sk: *mut c_uchar,

src/key.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)