diff --git a/Cargo.toml b/Cargo.toml index 94648b7..016947d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "secp256k1" -version = "0.7.1" +version = "0.8.0" authors = [ "Dawid Ciężarkiewicz ", "Andrew Poelstra " ] license = "CC0-1.0" @@ -23,14 +23,26 @@ path = "src/lib.rs" [features] unstable = [] default = [] -dev = ["clippy"] -[dependencies] -arrayvec = "0.3" -clippy = {version = "0.0", optional = true} -rand = "0.3" -libc = "0.2" -rustc-serialize = "0.3" +[dev-dependencies] serde = "1.0" serde_json = "1.0" +rand = "0.3" +rustc-serialize = "0.3" + +[dependencies] +libc = "0.2" + +[dependencies.rand] +version = "0.3" +optional = true + +[dependencies.rustc-serialize] +version = "0.3" +optional = true + +[dependencies.serde] +version = "1.0" +optional = true + diff --git a/build.rs b/build.rs index db70863..63c050d 100644 --- a/build.rs +++ b/build.rs @@ -24,7 +24,7 @@ extern crate gcc; fn main() { - let mut base_config = gcc::Config::new(); + let mut base_config = gcc::Build::new(); base_config.include("depend/secp256k1/") .include("depend/secp256k1/include") .include("depend/secp256k1/src") diff --git a/src/constants.rs b/src/constants.rs index 9a219ee..48189f6 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -22,16 +22,12 @@ pub const MESSAGE_SIZE: usize = 32; /// The size (in bytes) of a secret key pub const SECRET_KEY_SIZE: usize = 32; -/// The size (in bytes) of a public key array. This only needs to be 65 -/// but must be 72 for compatibility with the `ArrayVec` library. -pub const PUBLIC_KEY_SIZE: usize = 72; +/// The size (in bytes) of a serialized public key. +pub const PUBLIC_KEY_SIZE: usize = 33; -/// The size (in bytes) of an uncompressed public key +/// The size (in bytes) of an serialized uncompressed public key pub const UNCOMPRESSED_PUBLIC_KEY_SIZE: usize = 65; -/// The size (in bytes) of a compressed public key -pub const COMPRESSED_PUBLIC_KEY_SIZE: usize = 33; - /// The maximum size of a signature pub const MAX_SIGNATURE_SIZE: usize = 72; diff --git a/src/ffi.rs b/src/ffi.rs index 313aa95..b11175c 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -140,7 +140,7 @@ extern "C" { input: *const c_uchar, in_len: size_t) -> c_int; - pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *const c_uchar, + pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar, out_len: *mut size_t, pk: *const PublicKey , compressed: c_uint) -> c_int; diff --git a/src/key.rs b/src/key.rs index aeb777a..f572d41 100644 --- a/src/key.rs +++ b/src/key.rs @@ -15,11 +15,10 @@ //! # Public and secret keys -use std::marker; -use arrayvec::ArrayVec; -use rand::Rng; -use serialize::{Decoder, Decodable, Encoder, Encodable}; -use serde::{Serialize, Deserialize, Serializer, Deserializer}; +#[cfg(any(test, feature = "serde"))] use std::marker; +#[cfg(any(test, feature = "rand"))] use rand::Rng; +#[cfg(any(test, feature = "rustc-serialize"))] use serialize::{Decoder, Decodable, Encoder, Encodable}; +#[cfg(any(test, feature = "serde"))] use serde::{Serialize, Deserialize, Serializer, Deserializer}; use super::{Secp256k1, ContextFlag}; use super::Error::{self, IncapableContext, InvalidPublicKey, InvalidSecretKey}; @@ -55,6 +54,7 @@ pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0, pub struct PublicKey(ffi::PublicKey); +#[cfg(any(test, feature = "rand"))] fn random_32_bytes(rng: &mut R) -> [u8; 32] { let mut ret = [0u8; 32]; rng.fill_bytes(&mut ret); @@ -64,6 +64,7 @@ fn random_32_bytes(rng: &mut R) -> [u8; 32] { impl SecretKey { /// Creates a new random secret key #[inline] + #[cfg(any(test, feature = "rand"))] pub fn new(secp: &Secp256k1, rng: &mut R) -> SecretKey { let mut data = random_32_bytes(rng); unsafe { @@ -179,17 +180,41 @@ impl PublicKey { /// Serialize the key as a byte-encoded pair of values. In compressed form /// the y-coordinate is represented by only a single bit, as x determines /// it up to one bit. - pub fn serialize_vec(&self, secp: &Secp256k1, compressed: bool) -> ArrayVec<[u8; constants::PUBLIC_KEY_SIZE]> { - let mut ret = ArrayVec::new(); + pub fn serialize(&self) -> [u8; constants::PUBLIC_KEY_SIZE] { + let secp = Secp256k1::with_caps(ContextFlag::None); + let mut ret = [0; constants::PUBLIC_KEY_SIZE]; unsafe { let mut ret_len = constants::PUBLIC_KEY_SIZE as ::libc::size_t; - let compressed = if compressed { ffi::SECP256K1_SER_COMPRESSED } else { ffi::SECP256K1_SER_UNCOMPRESSED }; - let err = ffi::secp256k1_ec_pubkey_serialize(secp.ctx, ret.as_ptr(), - &mut ret_len, self.as_ptr(), - compressed); + let err = ffi::secp256k1_ec_pubkey_serialize( + secp.ctx, + ret.as_mut_ptr(), + &mut ret_len, + self.as_ptr(), + ffi::SECP256K1_SER_COMPRESSED, + ); debug_assert_eq!(err, 1); - ret.set_len(ret_len as usize); + debug_assert_eq!(ret_len, ret.len()); + } + ret + } + + /// Serialize the key as a byte-encoded pair of values, in uncompressed form + pub fn serialize_uncompressed(&self) -> [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] { + let secp = Secp256k1::with_caps(ContextFlag::None); + let mut ret = [0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]; + + unsafe { + let mut ret_len = constants::UNCOMPRESSED_PUBLIC_KEY_SIZE as ::libc::size_t; + let err = ffi::secp256k1_ec_pubkey_serialize( + secp.ctx, + ret.as_mut_ptr(), + &mut ret_len, + self.as_ptr(), + ffi::SECP256K1_SER_UNCOMPRESSED, + ); + debug_assert_eq!(err, 1); + debug_assert_eq!(ret_len, ret.len()); } ret } @@ -229,6 +254,7 @@ impl PublicKey { } } +#[cfg(any(test, feature = "rustc-serialize"))] impl Decodable for PublicKey { fn decode(d: &mut D) -> Result { d.read_seq(|d, len| { @@ -242,10 +268,10 @@ impl Decodable for PublicKey { } PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) } - } else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE { + } else if len == constants::PUBLIC_KEY_SIZE { unsafe { use std::mem; - let mut ret: [u8; constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); + let mut ret: [u8; constants::PUBLIC_KEY_SIZE] = mem::uninitialized(); for i in 0..len { ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); } @@ -267,13 +293,14 @@ impl From for PublicKey { } +#[cfg(any(test, feature = "rustc-serialize"))] impl Encodable for PublicKey { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - let secp = Secp256k1::with_caps(::ContextFlag::None); - self.serialize_vec(&secp, true).encode(s) + self.serialize().encode(s) } } +#[cfg(any(test, feature = "serde"))] impl<'de> Deserialize<'de> for PublicKey { fn deserialize(d: D) -> Result where D: Deserializer<'de> @@ -289,7 +316,7 @@ impl<'de> Deserialize<'de> for PublicKey { fn visit_seq(self, mut a: A) -> Result where A: de::SeqAccess<'de> { - debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= constants::COMPRESSED_PUBLIC_KEY_SIZE); + debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= constants::PUBLIC_KEY_SIZE); let s = Secp256k1::with_caps(::ContextFlag::None); unsafe { @@ -311,7 +338,7 @@ impl<'de> Deserialize<'de> for PublicKey { } match read_len { - constants::UNCOMPRESSED_PUBLIC_KEY_SIZE | constants::COMPRESSED_PUBLIC_KEY_SIZE + constants::UNCOMPRESSED_PUBLIC_KEY_SIZE | constants::PUBLIC_KEY_SIZE => PublicKey::from_slice(&s, &ret[..read_len]).map_err( |e| match e { InvalidPublicKey => de::Error::invalid_value(de::Unexpected::Seq, &self), @@ -325,7 +352,7 @@ impl<'de> Deserialize<'de> for PublicKey { fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { write!(f, "a sequence of {} or {} bytes representing a valid compressed or uncompressed public key", - constants::COMPRESSED_PUBLIC_KEY_SIZE, constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) + constants::PUBLIC_KEY_SIZE, constants::UNCOMPRESSED_PUBLIC_KEY_SIZE) } } @@ -334,12 +361,12 @@ impl<'de> Deserialize<'de> for PublicKey { } } +#[cfg(any(test, feature = "serde"))] impl Serialize for PublicKey { fn serialize(&self, s: S) -> Result where S: Serializer { - let secp = Secp256k1::with_caps(::ContextFlag::None); - (&self.serialize_vec(&secp, true)[..]).serialize(s) + self.serialize().serialize(s) } } @@ -381,8 +408,8 @@ mod test { let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1)); - assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, true)[..]), Ok(pk1)); - assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, false)[..]), Ok(pk1)); + assert_eq!(PublicKey::from_slice(&s, &pk1.serialize()[..]), Ok(pk1)); + assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_uncompressed()[..]), Ok(pk1)); } #[test] @@ -597,9 +624,9 @@ mod test { fn test_pubkey_from_bad_slice() { let s = Secp256k1::new(); // Bad sizes - assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE - 1]), + assert_eq!(PublicKey::from_slice(&s, &[0; constants::PUBLIC_KEY_SIZE - 1]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]), + assert_eq!(PublicKey::from_slice(&s, &[0; constants::PUBLIC_KEY_SIZE + 1]), Err(InvalidPublicKey)); assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), Err(InvalidPublicKey)); @@ -609,7 +636,7 @@ mod test { // Bad parse assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::COMPRESSED_PUBLIC_KEY_SIZE]), + assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::PUBLIC_KEY_SIZE]), Err(InvalidPublicKey)); } @@ -642,9 +669,9 @@ mod test { let s = Secp256k1::new(); let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap(); - assert_eq!(&pk1.serialize_vec(&s, false)[..], + assert_eq!(&pk1.serialize_uncompressed()[..], &[4, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236, 1, 189, 143, 242, 227, 16, 87, 247, 183, 162, 68, 237, 140, 92, 205, 151, 129, 166, 58, 111, 96, 123, 64, 180, 147, 51, 12, 209, 89, 236, 213, 206][..]); - assert_eq!(&pk1.serialize_vec(&s, true)[..], + assert_eq!(&pk1.serialize()[..], &[2, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236][..]); } diff --git a/src/lib.rs b/src/lib.rs index d7cc58b..1bdd9f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,18 +38,16 @@ #![cfg_attr(all(test, feature = "unstable"), feature(test))] #[cfg(all(test, feature = "unstable"))] extern crate test; - -extern crate arrayvec; -extern crate rustc_serialize as serialize; -extern crate serde; -extern crate serde_json as json; +#[cfg(any(test, feature = "serde"))] extern crate serde; +#[cfg(test)] extern crate serde_json as json; +#[cfg(any(test, feature = "rand"))] extern crate rand; +#[cfg(any(test, feature = "rustc-serialize"))] extern crate rustc_serialize as serialize; extern crate libc; -extern crate rand; use libc::size_t; use std::{error, fmt, ops, ptr}; -use rand::Rng; +#[cfg(any(test, feature = "rand"))] use rand::Rng; #[macro_use] mod macros; @@ -202,6 +200,7 @@ impl Signature { } } +#[cfg(any(test, feature = "serde"))] impl serde::Serialize for Signature { fn serialize(&self, s: S) -> Result where S: serde::Serializer @@ -211,6 +210,7 @@ impl serde::Serialize for Signature { } } +#[cfg(any(test, feature = "serde"))] impl<'de> serde::Deserialize<'de> for Signature { fn deserialize(d: D) -> Result where D: serde::Deserializer<'de> @@ -520,6 +520,7 @@ impl Secp256k1 { /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistence; /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell + #[cfg(any(test, feature = "rand"))] pub fn randomize(&mut self, rng: &mut R) { let mut seed = [0; 32]; rng.fill_bytes(&mut seed); @@ -541,6 +542,7 @@ impl Secp256k1 { /// and `key::PublicKey::from_secret_key`; call those functions directly for /// batch key generation. Requires a signing-capable context. #[inline] + #[cfg(any(test, feature = "rand"))] pub fn generate_keypair(&self, rng: &mut R) -> Result<(key::SecretKey, key::PublicKey), Error> { let sk = key::SecretKey::new(self, rng); @@ -690,7 +692,7 @@ mod tests { assert_eq!(full.recover(&msg, &sigr), Ok(pk)); // Check that we can produce keys from slices with no precomputation - let (pk_slice, sk_slice) = (&pk.serialize_vec(&none, true), &sk[..]); + let (pk_slice, sk_slice) = (&pk.serialize(), &sk[..]); let new_pk = PublicKey::from_slice(&none, pk_slice).unwrap(); let new_sk = SecretKey::from_slice(&none, sk_slice).unwrap(); assert_eq!(sk, new_sk); diff --git a/src/macros.rs b/src/macros.rs index 4f5b8d5..92eccbf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -116,6 +116,7 @@ macro_rules! impl_array_newtype { } } + #[cfg(any(test, feature = "rustc-serialize"))] impl ::serialize::Decodable for $thing { fn decode(d: &mut D) -> Result<$thing, D::Error> { use serialize::Decodable; @@ -137,6 +138,7 @@ macro_rules! impl_array_newtype { } } + #[cfg(any(test, feature = "rustc-serialize"))] impl ::serialize::Encodable for $thing { fn encode(&self, s: &mut S) -> Result<(), S::Error> { @@ -144,6 +146,7 @@ macro_rules! impl_array_newtype { } } + #[cfg(any(test, feature = "serde"))] impl<'de> ::serde::Deserialize<'de> for $thing { fn deserialize(d: D) -> Result<$thing, D::Error> where D: ::serde::Deserializer<'de> @@ -188,6 +191,7 @@ macro_rules! impl_array_newtype { } } + #[cfg(any(test, feature = "serde"))] impl ::serde::Serialize for $thing { fn serialize(&self, s: S) -> Result where S: ::serde::Serializer