From a5951eff4794f6b114604c6ec63320ccefdda76f Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Thu, 28 Aug 2014 09:16:53 -0700 Subject: [PATCH] Expose tweak functions in FFI, wrap a couple --- src/ffi.rs | 18 ++++++++++++++++++ src/key.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++++- src/secp256k1.rs | 2 ++ 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/ffi.rs b/src/ffi.rs index 9e22647..eb92464 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -47,5 +47,23 @@ extern "C" { recid: c_int) -> c_int; pub fn secp256k1_ecdsa_seckey_verify(sk: *const c_uchar) -> c_int; + + pub fn secp256k1_ecdsa_privkey_tweak_add(sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; + + pub fn secp256k1_ecdsa_pubkey_tweak_add(pk: *mut c_uchar, + pk_len: c_int, + tweak: *const c_uchar) + -> c_int; + + pub fn secp256k1_ecdsa_privkey_tweak_mul(sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; + + pub fn secp256k1_ecdsa_pubkey_tweak_mul(pk: *mut c_uchar, + pk_len: c_int, + tweak: *const c_uchar) + -> c_int; } diff --git a/src/key.rs b/src/key.rs index 14a1129..0278a91 100644 --- a/src/key.rs +++ b/src/key.rs @@ -21,7 +21,7 @@ use std::rand::Rng; use constants; use ffi; -use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey}; +use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey, Unknown}; /// Secret 256-bit nonce used as `k` in an ECDSA signature pub struct Nonce([u8, ..constants::NONCE_SIZE]); @@ -97,6 +97,18 @@ impl SecretKey { _ => Err(InvalidSecretKey) } } + + #[inline] + /// Adds one secret key to another, modulo the curve order + pub fn add_assign(&mut self, other: &SecretKey) -> Result<()> { + unsafe { + if ffi::secp256k1_ecdsa_privkey_tweak_add(self.as_mut_ptr(), other.as_ptr()) != 1 { + Err(Unknown) + } else { + Ok(()) + } + } + } } impl PublicKey { @@ -202,6 +214,20 @@ impl PublicKey { Uncompressed(ref mut x) => x.as_mut_ptr() } } + + #[inline] + /// Adds the pk corresponding to `other` to the pk `self` in place + pub fn add_exp_assign(&mut self, other: &SecretKey) -> Result<()> { + unsafe { + if ffi::secp256k1_ecdsa_pubkey_tweak_add(self.as_mut_ptr(), + self.len() as ::libc::c_int, + other.as_ptr()) != 1 { + Err(Unknown) + } else { + Ok(()) + } + } + } } impl PublicKeyData { @@ -322,6 +348,26 @@ mod test { 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err()); } + + #[test] + fn test_addition() { + let mut s = Secp256k1::new(); + + let (mut sk1, mut pk1) = s.generate_keypair(true).unwrap(); + let (mut sk2, mut pk2) = s.generate_keypair(true).unwrap(); + + unsafe { + assert_eq!(PublicKey::from_secret_key(&sk1, true), pk1); + assert!(sk1.add_assign(&sk2).is_ok()); + assert!(pk1.add_exp_assign(&sk2).is_ok()); + assert_eq!(PublicKey::from_secret_key(&sk1, true), pk1); + + assert_eq!(PublicKey::from_secret_key(&sk2, true), pk2); + assert!(sk2.add_assign(&sk1).is_ok()); + assert!(pk2.add_exp_assign(&sk1).is_ok()); + assert_eq!(PublicKey::from_secret_key(&sk2, true), pk2); + } + } } diff --git a/src/secp256k1.rs b/src/secp256k1.rs index d8f8ed5..8e4b6fc 100644 --- a/src/secp256k1.rs +++ b/src/secp256k1.rs @@ -95,6 +95,8 @@ pub enum Error { InvalidNonce, /// Rng problem RngError(IoError), + /// Boolean-returning function returned the wrong boolean + Unknown } /// Result type