diff --git a/src/key.rs b/src/key.rs index fd13850..ab56aa2 100644 --- a/src/key.rs +++ b/src/key.rs @@ -46,7 +46,7 @@ enum PublicKeyData { Uncompressed([u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) } -fn random_32_bytes(rng: &mut R) -> [u8; 32] { +fn random_32_bytes(rng: &mut R) -> [u8; 32] { let mut ret = [0u8; 32]; rng.fill_bytes(&mut ret); ret @@ -55,11 +55,11 @@ fn random_32_bytes(rng: &mut R) -> [u8; 32] { impl SecretKey { /// Creates a new random secret key #[inline] - pub fn new(secp: &mut Secp256k1) -> SecretKey { - let mut data = random_32_bytes(&mut secp.rng); + pub fn new(secp: &Secp256k1, rng: &mut R) -> SecretKey { + let mut data = random_32_bytes(rng); unsafe { while ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { - data = random_32_bytes(&mut secp.rng); + data = random_32_bytes(rng); } } SecretKey(data) @@ -67,7 +67,7 @@ impl SecretKey { /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) + pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { match data.len() { constants::SECRET_KEY_SIZE => { @@ -88,10 +88,8 @@ impl SecretKey { #[inline] /// Adds one secret key to another, modulo the curve order - pub fn add_assign(&mut self, - secp: &Secp256k1, - other: &SecretKey) - -> Result<(), Error> { + pub fn add_assign(&mut self, secp: &Secp256k1, other: &SecretKey) + -> Result<(), Error> { unsafe { if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 { Err(Unknown) @@ -117,7 +115,7 @@ impl PublicKey { /// Creates a new public key from a secret key. #[inline] - pub fn from_secret_key(secp: &Secp256k1, + pub fn from_secret_key(secp: &Secp256k1, sk: &SecretKey, compressed: bool) -> PublicKey { @@ -139,7 +137,7 @@ impl PublicKey { /// Creates a public key directly from a slice #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) + pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { match data.len() { constants::COMPRESSED_PUBLIC_KEY_SIZE => { @@ -216,10 +214,8 @@ impl PublicKey { #[inline] /// Adds the pk corresponding to `other` to the pk `self` in place - pub fn add_exp_assign(&mut self, - secp: &Secp256k1, - other: &SecretKey) - -> Result<(), Error> { + pub fn add_exp_assign(&mut self, secp: &Secp256k1, other: &SecretKey) + -> Result<(), Error> { unsafe { if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, self.as_mut_ptr(), self.len() as ::libc::c_int, @@ -473,11 +469,11 @@ mod test { use super::{PublicKey, SecretKey}; use super::super::constants; - use rand::Rng; + use rand::{Rng, thread_rng}; #[test] fn skey_from_slice() { - let s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); let sk = SecretKey::from_slice(&s, &[1; 31]); assert_eq!(sk, Err(InvalidSecretKey)); @@ -487,7 +483,7 @@ mod test { #[test] fn pubkey_from_slice() { - let s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey)); assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey)); @@ -502,20 +498,20 @@ mod test { #[test] fn keypair_slice_round_trip() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); - let (sk1, pk1) = s.generate_keypair(true); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng(), true); assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1)); assert_eq!(PublicKey::from_slice(&s, &pk1[..]), Ok(pk1)); - let (sk2, pk2) = s.generate_keypair(false); + let (sk2, pk2) = s.generate_keypair(&mut thread_rng(), false); assert_eq!(SecretKey::from_slice(&s, &sk2[..]), Ok(sk2)); assert_eq!(PublicKey::from_slice(&s, &pk2[..]), Ok(pk2)); } #[test] fn invalid_secret_key() { - let s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); // Zero assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey)); // -1 @@ -589,12 +585,12 @@ mod test { }) ); - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); for _ in 0..500 { - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), false); round_trip!(sk); round_trip!(pk); - let (sk, pk) = s.generate_keypair(true); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), true); round_trip!(sk); round_trip!(pk); } @@ -650,12 +646,12 @@ mod test { }) ); - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); for _ in 0..500 { - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), false); round_trip!(sk); round_trip!(pk); - let (sk, pk) = s.generate_keypair(true); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), true); round_trip!(sk); round_trip!(pk); } @@ -688,15 +684,14 @@ mod test { } } - let mut s = Secp256k1::with_rng(BadRng(0xff)); - s.generate_keypair(false); - let mut s = Secp256k1::with_rng(BadRng(0xff)); - s.generate_keypair(true); + let s = Secp256k1::new(); + s.generate_keypair(&mut BadRng(0xff), false); + s.generate_keypair(&mut BadRng(0xff), true); } #[test] fn test_pubkey_from_bad_slice() { - let s = Secp256k1::new_deterministic(); + let s = Secp256k1::new(); // Bad sizes assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE - 1]), Err(InvalidPublicKey)); @@ -724,26 +719,26 @@ mod test { } } - let mut s = Secp256k1::with_rng(DumbRng(0)); - let (sk1, pk1) = s.generate_keypair(false); - let (sk2, pk2) = s.generate_keypair(true); + let s = Secp256k1::new(); + let (sk1, pk1) = s.generate_keypair(&mut DumbRng(0), false); + let (sk2, pk2) = s.generate_keypair(&mut DumbRng(0), true); assert_eq!(&format!("{:?}", sk1), "SecretKey(0200000001000000040000000300000006000000050000000800000007000000)"); assert_eq!(&format!("{:?}", pk1), "PublicKey(049510c48c265cefb3413be0e6b75beef02ebafcaf6634f962b27b4832abc4feec01bd8ff2e31057f7b7a244ed8c5ccd9781a63a6f607b40b493330cd159ecd5ce)"); assert_eq!(&format!("{:?}", sk2), - "SecretKey(0a000000090000000c0000000b0000000e0000000d000000100000000f000000)"); + "SecretKey(0200000001000000040000000300000006000000050000000800000007000000)"); assert_eq!(&format!("{:?}", pk2), - "PublicKey(024889f1f4a9407f8588b55358c2b392a6d9662872d5b9fff98b6f68c5e290a866)"); + "PublicKey(029510c48c265cefb3413be0e6b75beef02ebafcaf6634f962b27b4832abc4feec)"); } #[test] fn test_addition() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); - let (mut sk1, mut pk1) = s.generate_keypair(true); - let (mut sk2, mut pk2) = s.generate_keypair(true); + let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng(), true); + let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng(), true); assert_eq!(PublicKey::from_secret_key(&s, &sk1, true), pk1); assert!(sk1.add_assign(&s, &sk2).is_ok()); diff --git a/src/lib.rs b/src/lib.rs index 5dbe528..8730c0a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,6 @@ #![deny(unused_mut)] #![warn(missing_docs)] -extern crate crypto; extern crate rustc_serialize as serialize; extern crate serde; #[cfg(test)] extern crate test; @@ -44,11 +43,9 @@ extern crate libc; extern crate rand; use std::intrinsics::copy_nonoverlapping; -use std::{cmp, fmt, io, ops, ptr}; +use std::{cmp, fmt, ops, ptr}; use libc::c_int; -use rand::{OsRng, Rng, SeedableRng}; - -use crypto::fortuna::Fortuna; +use rand::Rng; #[macro_use] mod macros; @@ -233,84 +230,55 @@ impl fmt::Display for Error { } /// The secp256k1 engine, used to execute all signature operations -pub struct Secp256k1 { - ctx: ffi::Context, - rng: R +pub struct Secp256k1 { + ctx: ffi::Context } -impl Clone for Secp256k1 { - fn clone(&self) -> Secp256k1 { +impl Clone for Secp256k1 { + fn clone(&self) -> Secp256k1 { Secp256k1 { - ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) }, - rng: self.rng.clone() + ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) } } } } -impl PartialEq for Secp256k1 { - fn eq(&self, other: &Secp256k1) -> bool { - // The contexts will always be "equal" in a functional sense - self.rng == other.rng - } +impl PartialEq for Secp256k1 { + // Contexts will always be "equal" in a functional sense + fn eq(&self, _: &Secp256k1) -> bool { true } } -impl Eq for Secp256k1 { } +impl Eq for Secp256k1 { } -impl fmt::Debug for Secp256k1 { +impl fmt::Debug for Secp256k1 { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "Secp256k1 {{ ctx: (secp256k1 context), rng: {:?} }}", self.rng) + write!(f, "Secp256k1 {{ secp256k1 context }}") } } -impl Drop for Secp256k1 { +impl Drop for Secp256k1 { fn drop(&mut self) { unsafe { ffi::secp256k1_context_destroy(self.ctx); } } } -impl Secp256k1<()> { - /// Constructs a new secp256k1 engine without a RNG. This is - /// useful for, e.g. BIP32 implementations, where all keys are - /// computed externally to the secp256k1 engine. Note that if - /// you try to use this for `SecretKey::new`, which generates - /// a random key, it will panic. - pub fn new_deterministic() -> Secp256k1<()> { - Secp256k1::with_rng(()) - } -} - -impl Secp256k1 { - /// Constructs a new secp256k1 engine with the default key-generation Rng - /// (a Fortuna seeded with randomness from the OS during `new`) - pub fn new() -> io::Result> { - let mut osrng = try!(OsRng::new()); - let mut seed = [0; 2048]; - osrng.fill_bytes(&mut seed); - let rng: Fortuna = SeedableRng::from_seed(&seed[..]); - Ok(Secp256k1::with_rng(rng)) - } -} - -impl Secp256k1 { - /// Generates a random keypair. Convenience function for `key::SecretKey::new` - /// and `key::PublicKey::from_secret_key`; call those functions directly for - /// batch key generation. - #[inline] - pub fn generate_keypair(&mut self, compressed: bool) - -> (key::SecretKey, key::PublicKey) { - let sk = key::SecretKey::new(self); - let pk = key::PublicKey::from_secret_key(self, &sk, compressed); - (sk, pk) - } -} - -impl Secp256k1 { - /// Constructs a new secp256k1 engine with its key-generation RNG specified - pub fn with_rng(rng: R) -> Secp256k1 { +impl Secp256k1 { + /// Creates a new Secp256k1 context + pub fn new() -> Secp256k1 { let ctx = unsafe { ffi::secp256k1_context_create(ffi::SECP256K1_START_VERIFY | ffi::SECP256K1_START_SIGN) }; - Secp256k1 { ctx: ctx, rng: rng } + Secp256k1 { ctx: ctx } + } + + /// Generates a random keypair. Convenience function for `key::SecretKey::new` + /// and `key::PublicKey::from_secret_key`; call those functions directly for + /// batch key generation. + #[inline] + pub fn generate_keypair(&self, rng: &mut R, compressed: bool) + -> (key::SecretKey, key::PublicKey) { + let sk = key::SecretKey::new(self, rng); + let pk = key::PublicKey::from_secret_key(self, &sk, compressed); + (sk, pk) } /// Constructs a signature for `msg` using the secret key `sk` and nonce `nonce` @@ -412,7 +380,7 @@ mod tests { #[test] fn invalid_pubkey() { - let s = Secp256k1::new_deterministic(); + let s = Secp256k1::new(); let sig = Signature::from_slice(&[0; 72]).unwrap(); let pk = PublicKey::new(true); let mut msg = [0u8; 32]; @@ -424,9 +392,9 @@ mod tests { #[test] fn valid_pubkey_uncompressed() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); - let (_, pk) = s.generate_keypair(false); + let (_, pk) = s.generate_keypair(&mut thread_rng(), false); let sig = Signature::from_slice(&[0; 72]).unwrap(); let mut msg = [0u8; 32]; @@ -438,9 +406,9 @@ mod tests { #[test] fn valid_pubkey_compressed() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); - let (_, pk) = s.generate_keypair(true); + let (_, pk) = s.generate_keypair(&mut thread_rng(), true); let sig = Signature::from_slice(&[0; 72]).unwrap(); let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); @@ -451,7 +419,7 @@ mod tests { #[test] fn sign() { - let s = Secp256k1::new_deterministic(); + let s = Secp256k1::new(); let one = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; @@ -473,14 +441,14 @@ mod tests { #[test] fn sign_and_verify() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); let mut msg = [0; 32]; for _ in 0..100 { thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), false); let sig = s.sign(&msg, &sk); assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); } @@ -488,13 +456,13 @@ mod tests { #[test] fn sign_and_verify_fail() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), false); let sig = s.sign(&msg, &sk); let (sig_compact, recid) = s.sign_compact(&msg, &sk); @@ -510,13 +478,13 @@ mod tests { #[test] fn sign_compact_with_recovery() { - let mut s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); let mut msg = [0u8; 32]; thread_rng().fill_bytes(&mut msg); let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut thread_rng(), false); let (sig, recid) = s.sign_compact(&msg, &sk); @@ -525,7 +493,7 @@ mod tests { #[test] fn bad_recovery() { - let s = Secp256k1::new().unwrap(); + let s = Secp256k1::new(); let msg = Message::from_slice(&[0x55; 32]).unwrap(); @@ -569,9 +537,15 @@ mod tests { #[bench] pub fn generate_compressed(bh: &mut Bencher) { - let mut s = Secp256k1::new().unwrap(); + struct CounterRng(u32); + impl Rng for CounterRng { + fn next_u32(&mut self) -> u32 { self.0 += 1; self.0 } + } + + let s = Secp256k1::new(); + let mut r = CounterRng(0); bh.iter( || { - let (sk, pk) = s.generate_keypair(true); + let (sk, pk) = s.generate_keypair(&mut r, true); black_box(sk); black_box(pk); }); @@ -579,9 +553,15 @@ mod tests { #[bench] pub fn generate_uncompressed(bh: &mut Bencher) { - let mut s = Secp256k1::new().unwrap(); + struct CounterRng(u32); + impl Rng for CounterRng { + fn next_u32(&mut self) -> u32 { self.0 += 1; self.0 } + } + + let s = Secp256k1::new(); + let mut r = CounterRng(0); bh.iter( || { - let (sk, pk) = s.generate_keypair(false); + let (sk, pk) = s.generate_keypair(&mut r, false); black_box(sk); black_box(pk); });