diff --git a/secp256k1zkp/Cargo.toml b/secp256k1zkp/Cargo.toml index 6d88280e0..47153faf4 100644 --- a/secp256k1zkp/Cargo.toml +++ b/secp256k1zkp/Cargo.toml @@ -29,6 +29,5 @@ clippy = {version = "0.0", optional = true} rand = "0.3" libc = "0.1" rustc-serialize = "0.3" -serde = "0.6" -serde_json = "0.6" - +serde = "~1.0.8" +serde_json = "~1.0.2" diff --git a/secp256k1zkp/src/ecdh.rs b/secp256k1zkp/src/ecdh.rs index 4cba8d7f8..0448e8cf3 100644 --- a/secp256k1zkp/src/ecdh.rs +++ b/secp256k1zkp/src/ecdh.rs @@ -26,106 +26,106 @@ use ffi; pub struct SharedSecret(ffi::SharedSecret); impl SharedSecret { - /// Creates a new shared secret from a pubkey and secret key - #[inline] - pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret { - unsafe { - let mut ss = ffi::SharedSecret::blank(); - let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr()); - debug_assert_eq!(res, 1); - SharedSecret(ss) - } - } + /// Creates a new shared secret from a pubkey and secret key + #[inline] + pub fn new(secp: &Secp256k1, point: &PublicKey, scalar: &SecretKey) -> SharedSecret { + unsafe { + let mut ss = ffi::SharedSecret::blank(); + let res = ffi::secp256k1_ecdh(secp.ctx, &mut ss, point.as_ptr(), scalar.as_ptr()); + debug_assert_eq!(res, 1); + SharedSecret(ss) + } + } - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::SharedSecret { - &self.0 as *const _ - } + /// Obtains a raw pointer suitable for use with FFI functions + #[inline] + pub fn as_ptr(&self) -> *const ffi::SharedSecret { + &self.0 as *const _ + } } /// Creates a new shared secret from a FFI shared secret impl From for SharedSecret { - #[inline] - fn from(ss: ffi::SharedSecret) -> SharedSecret { - SharedSecret(ss) - } + #[inline] + fn from(ss: ffi::SharedSecret) -> SharedSecret { + SharedSecret(ss) + } } impl ops::Index for SharedSecret { - type Output = u8; + type Output = u8; - #[inline] - fn index(&self, index: usize) -> &u8 { - &self.0[index] - } + #[inline] + fn index(&self, index: usize) -> &u8 { + &self.0[index] + } } impl ops::Index> for SharedSecret { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] - } + #[inline] + fn index(&self, index: ops::Range) -> &[u8] { + &self.0[index] + } } impl ops::Index> for SharedSecret { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[u8] { - &self.0[index.start..] - } + #[inline] + fn index(&self, index: ops::RangeFrom) -> &[u8] { + &self.0[index.start..] + } } impl ops::Index for SharedSecret { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.0[..] - } + #[inline] + fn index(&self, _: ops::RangeFull) -> &[u8] { + &self.0[..] + } } #[cfg(test)] mod tests { - use rand::thread_rng; - use super::SharedSecret; - use super::super::Secp256k1; + use rand::thread_rng; + use super::SharedSecret; + use super::super::Secp256k1; - #[test] - fn ecdh() { - let s = Secp256k1::with_caps(::ContextFlag::SignOnly); - let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); + #[test] + fn ecdh() { + let s = Secp256k1::with_caps(::ContextFlag::SignOnly); + let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk2, pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sec1 = SharedSecret::new(&s, &pk1, &sk2); - let sec2 = SharedSecret::new(&s, &pk2, &sk1); - let sec_odd = SharedSecret::new(&s, &pk1, &sk1); - assert_eq!(sec1, sec2); - assert!(sec_odd != sec2); - } + let sec1 = SharedSecret::new(&s, &pk1, &sk2); + let sec2 = SharedSecret::new(&s, &pk2, &sk1); + let sec_odd = SharedSecret::new(&s, &pk1, &sk1); + assert_eq!(sec1, sec2); + assert!(sec_odd != sec2); + } } #[cfg(all(test, feature = "unstable"))] mod benches { - use rand::thread_rng; - use test::{Bencher, black_box}; + use rand::thread_rng; + use test::{Bencher, black_box}; - use super::SharedSecret; - use super::super::Secp256k1; + use super::SharedSecret; + use super::super::Secp256k1; - #[bench] - pub fn bench_ecdh(bh: &mut Bencher) { - let s = Secp256k1::with_caps(::ContextFlag::SignOnly); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + #[bench] + pub fn bench_ecdh(bh: &mut Bencher) { + let s = Secp256k1::with_caps(::ContextFlag::SignOnly); + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let s = Secp256k1::new(); - bh.iter(|| { - let res = SharedSecret::new(&s, &pk, &sk); - black_box(res); - }); - } + let s = Secp256k1::new(); + bh.iter(|| { + let res = SharedSecret::new(&s, &pk, &sk); + black_box(res); + }); + } } diff --git a/secp256k1zkp/src/ffi.rs b/secp256k1zkp/src/ffi.rs index 782aa523d..f9217e844 100644 --- a/secp256k1zkp/src/ffi.rs +++ b/secp256k1zkp/src/ffi.rs @@ -61,14 +61,14 @@ impl_array_newtype!(PublicKey, c_uchar, 64); impl_raw_debug!(PublicKey); impl PublicKey { - /// Create a new (zeroed) public key usable for the FFI interface - pub fn new() -> PublicKey { - PublicKey([0; 64]) - } - /// Create a new (uninitialized) public key usable for the FFI interface - pub unsafe fn blank() -> PublicKey { - mem::uninitialized() - } + /// Create a new (zeroed) public key usable for the FFI interface + pub fn new() -> PublicKey { + PublicKey([0; 64]) + } + /// Create a new (uninitialized) public key usable for the FFI interface + pub unsafe fn blank() -> PublicKey { + mem::uninitialized() + } } /// Library-internal representation of a Secp256k1 signature @@ -84,25 +84,25 @@ impl_array_newtype!(RecoverableSignature, c_uchar, 65); impl_raw_debug!(RecoverableSignature); impl Signature { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> Signature { - Signature([0; 64]) - } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> Signature { - mem::uninitialized() - } + /// Create a new (zeroed) signature usable for the FFI interface + pub fn new() -> Signature { + Signature([0; 64]) + } + /// Create a new (uninitialized) signature usable for the FFI interface + pub unsafe fn blank() -> Signature { + mem::uninitialized() + } } impl RecoverableSignature { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> RecoverableSignature { - RecoverableSignature([0; 65]) - } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> RecoverableSignature { - mem::uninitialized() - } + /// Create a new (zeroed) signature usable for the FFI interface + pub fn new() -> RecoverableSignature { + RecoverableSignature([0; 65]) + } + /// Create a new (uninitialized) signature usable for the FFI interface + pub unsafe fn blank() -> RecoverableSignature { + mem::uninitialized() + } } /// Library-internal representation of an ECDH shared secret @@ -112,263 +112,263 @@ impl_array_newtype!(SharedSecret, c_uchar, 32); impl_raw_debug!(SharedSecret); impl SharedSecret { - /// Create a new (zeroed) signature usable for the FFI interface - pub fn new() -> SharedSecret { - SharedSecret([0; 32]) - } - /// Create a new (uninitialized) signature usable for the FFI interface - pub unsafe fn blank() -> SharedSecret { - mem::uninitialized() - } + /// Create a new (zeroed) signature usable for the FFI interface + pub fn new() -> SharedSecret { + SharedSecret([0; 32]) + } + /// Create a new (uninitialized) signature usable for the FFI interface + pub unsafe fn blank() -> SharedSecret { + mem::uninitialized() + } } extern "C" { - pub static secp256k1_nonce_function_rfc6979: NonceFn; + pub static secp256k1_nonce_function_rfc6979: NonceFn; - pub static secp256k1_nonce_function_default: NonceFn; + pub static secp256k1_nonce_function_default: NonceFn; - // Contexts - pub fn secp256k1_context_create(flags: c_uint) -> *mut Context; + // Contexts + pub fn secp256k1_context_create(flags: c_uint) -> *mut Context; - pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context; + pub fn secp256k1_context_clone(cx: *mut Context) -> *mut Context; - pub fn secp256k1_context_destroy(cx: *mut Context); + pub fn secp256k1_context_destroy(cx: *mut Context); - pub fn secp256k1_context_randomize(cx: *mut Context, seed32: *const c_uchar) -> c_int; + pub fn secp256k1_context_randomize(cx: *mut Context, seed32: *const c_uchar) -> c_int; - pub fn secp256k1_pedersen_context_initialize(ctx: *mut Context); - pub fn secp256k1_rangeproof_context_initialize(ctx: *mut Context); + pub fn secp256k1_pedersen_context_initialize(ctx: *mut Context); + pub fn secp256k1_rangeproof_context_initialize(ctx: *mut Context); - // TODO secp256k1_context_set_illegal_callback - // TODO secp256k1_context_set_error_callback - // (Actually, I don't really want these exposed; if either of these - // are ever triggered it indicates a bug in rust-secp256k1, since - // one goal is to use Rust's type system to eliminate all possible - // bad inputs.) + // TODO secp256k1_context_set_illegal_callback + // TODO secp256k1_context_set_error_callback + // (Actually, I don't really want these exposed; if either of these + // are ever triggered it indicates a bug in rust-secp256k1, since + // one goal is to use Rust's type system to eliminate all possible + // bad inputs.) - // Pubkeys - pub fn secp256k1_ec_pubkey_parse(cx: *const Context, - pk: *mut PublicKey, - input: *const c_uchar, - in_len: size_t) - -> c_int; + // Pubkeys + pub fn secp256k1_ec_pubkey_parse(cx: *const Context, + pk: *mut PublicKey, + input: *const c_uchar, + in_len: size_t) + -> c_int; - pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, - output: *const c_uchar, - out_len: *mut size_t, - pk: *const PublicKey, - compressed: c_uint) - -> c_int; + pub fn secp256k1_ec_pubkey_serialize(cx: *const Context, + output: *const c_uchar, + out_len: *mut size_t, + pk: *const PublicKey, + compressed: c_uint) + -> c_int; - // Signatures - pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, - sig: *mut Signature, - input: *const c_uchar, - in_len: size_t) - -> c_int; + // Signatures + pub fn secp256k1_ecdsa_signature_parse_der(cx: *const Context, + sig: *mut Signature, + input: *const c_uchar, + in_len: size_t) + -> c_int; - pub fn ecdsa_signature_parse_der_lax(cx: *const Context, - sig: *mut Signature, - input: *const c_uchar, - in_len: size_t) - -> c_int; + pub fn ecdsa_signature_parse_der_lax(cx: *const Context, + sig: *mut Signature, + input: *const c_uchar, + in_len: size_t) + -> c_int; - pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, - output: *const c_uchar, - out_len: *mut size_t, - sig: *const Signature) - -> c_int; + pub fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, + output: *const c_uchar, + out_len: *mut size_t, + sig: *const Signature) + -> c_int; - pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, - sig: *mut RecoverableSignature, - input64: *const c_uchar, - recid: c_int) - -> c_int; + pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, + sig: *mut RecoverableSignature, + input64: *const c_uchar, + recid: c_int) + -> c_int; - pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar, + pub fn secp256k1_ecdsa_recoverable_signature_serialize_compact(cx: *const Context, output64: *const c_uchar, recid: *mut c_int, sig: *const RecoverableSignature) -> c_int; - pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, - sig: *mut Signature, - input: *const RecoverableSignature) - -> c_int; + pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, + sig: *mut Signature, + input: *const RecoverableSignature) + -> c_int; - pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, - out_sig: *mut Signature, - in_sig: *const Signature) - -> c_int; + pub fn secp256k1_ecdsa_signature_normalize(cx: *const Context, + out_sig: *mut Signature, + in_sig: *const Signature) + -> c_int; - // ECDSA - pub fn secp256k1_ecdsa_verify(cx: *const Context, - sig: *const Signature, - msg32: *const c_uchar, - pk: *const PublicKey) - -> c_int; + // ECDSA + pub fn secp256k1_ecdsa_verify(cx: *const Context, + sig: *const Signature, + msg32: *const c_uchar, + pk: *const PublicKey) + -> c_int; - pub fn secp256k1_ecdsa_sign(cx: *const Context, - sig: *mut Signature, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; + pub fn secp256k1_ecdsa_sign(cx: *const Context, + sig: *mut Signature, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; - pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, - sig: *mut RecoverableSignature, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; + pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context, + sig: *mut RecoverableSignature, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; - pub fn secp256k1_ecdsa_recover(cx: *const Context, - pk: *mut PublicKey, - sig: *const RecoverableSignature, - msg32: *const c_uchar) - -> c_int; + pub fn secp256k1_ecdsa_recover(cx: *const Context, + pk: *mut PublicKey, + sig: *const RecoverableSignature, + msg32: *const c_uchar) + -> c_int; - // Schnorr - pub fn secp256k1_schnorr_sign(cx: *const Context, - sig64: *mut c_uchar, - msg32: *const c_uchar, - sk: *const c_uchar, - noncefn: NonceFn, - noncedata: *const c_void) - -> c_int; + // Schnorr + pub fn secp256k1_schnorr_sign(cx: *const Context, + sig64: *mut c_uchar, + msg32: *const c_uchar, + sk: *const c_uchar, + noncefn: NonceFn, + noncedata: *const c_void) + -> c_int; - pub fn secp256k1_schnorr_verify(cx: *const Context, - sig64: *const c_uchar, - msg32: *const c_uchar, - pk: *const PublicKey) - -> c_int; + pub fn secp256k1_schnorr_verify(cx: *const Context, + sig64: *const c_uchar, + msg32: *const c_uchar, + pk: *const PublicKey) + -> c_int; - pub fn secp256k1_schnorr_recover(cx: *const Context, - pk: *mut PublicKey, - sig64: *const c_uchar, - msg32: *const c_uchar) - -> c_int; + pub fn secp256k1_schnorr_recover(cx: *const Context, + pk: *mut PublicKey, + sig64: *const c_uchar, + msg32: *const c_uchar) + -> c_int; - // EC - pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int; + // EC + pub fn secp256k1_ec_seckey_verify(cx: *const Context, sk: *const c_uchar) -> c_int; - pub fn secp256k1_ec_pubkey_create(cx: *const Context, - pk: *mut PublicKey, - sk: *const c_uchar) - -> c_int; + pub fn secp256k1_ec_pubkey_create(cx: *const Context, + pk: *mut PublicKey, + sk: *const c_uchar) + -> c_int; - // TODO secp256k1_ec_privkey_export - // TODO secp256k1_ec_privkey_import + // TODO secp256k1_ec_privkey_export + // TODO secp256k1_ec_privkey_import - pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int; + pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; - pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int; + pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int; - pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, - sk: *mut c_uchar, - tweak: *const c_uchar) - -> c_int; + pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context, + sk: *mut c_uchar, + tweak: *const c_uchar) + -> c_int; - pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, - pk: *mut PublicKey, - tweak: *const c_uchar) - -> c_int; + pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context, + pk: *mut PublicKey, + tweak: *const c_uchar) + -> c_int; - pub fn secp256k1_ec_pubkey_combine(cx: *const Context, - out: *mut PublicKey, - ins: *const *const PublicKey, - n: c_int) - -> c_int; + pub fn secp256k1_ec_pubkey_combine(cx: *const Context, + out: *mut PublicKey, + ins: *const *const PublicKey, + n: c_int) + -> c_int; - pub fn secp256k1_ecdh(cx: *const Context, - out: *mut SharedSecret, - point: *const PublicKey, - scalar: *const c_uchar) - -> c_int; + pub fn secp256k1_ecdh(cx: *const Context, + out: *mut SharedSecret, + point: *const PublicKey, + scalar: *const c_uchar) + -> c_int; - // Generates a pedersen commitment: *commit = blind * G + value * G2. - // The commitment is 33 bytes, the blinding factor is 32 bytes. - pub fn secp256k1_pedersen_commit(ctx: *const Context, - commit: *mut c_uchar, - blind: *const c_uchar, - value: uint64_t) - -> c_int; + // Generates a pedersen commitment: *commit = blind * G + value * G2. + // The commitment is 33 bytes, the blinding factor is 32 bytes. + pub fn secp256k1_pedersen_commit(ctx: *const Context, + commit: *mut c_uchar, + blind: *const c_uchar, + value: uint64_t) + -> c_int; - // Takes a list of n pointers to 32 byte blinding values, the first negs - // of which are treated with positive sign and the rest negative, then - // calculates an additional blinding value that adds to zero. - pub fn secp256k1_pedersen_blind_sum(ctx: *const Context, - blind_out: *const c_uchar, - blinds: *const *const c_uchar, - n: c_int, - npositive: c_int) - -> c_int; + // Takes a list of n pointers to 32 byte blinding values, the first negs + // of which are treated with positive sign and the rest negative, then + // calculates an additional blinding value that adds to zero. + pub fn secp256k1_pedersen_blind_sum(ctx: *const Context, + blind_out: *const c_uchar, + blinds: *const *const c_uchar, + n: c_int, + npositive: c_int) + -> c_int; - // Takes two list of 33-byte commitments and sums the first set, subtracts - // the second and returns the resulting commitment. - pub fn secp256k1_pedersen_commit_sum(ctx: *const Context, - commit_out: *const c_uchar, - commits: *const *const c_uchar, - pcnt: c_int, - ncommits: *const *const c_uchar, - ncnt: c_int) - -> c_int; + // Takes two list of 33-byte commitments and sums the first set, subtracts + // the second and returns the resulting commitment. + pub fn secp256k1_pedersen_commit_sum(ctx: *const Context, + commit_out: *const c_uchar, + commits: *const *const c_uchar, + pcnt: c_int, + ncommits: *const *const c_uchar, + ncnt: c_int) + -> c_int; - // Takes two list of 33-byte commitments and sums the first set and - // subtracts the second and verifies that they sum to excess. - pub fn secp256k1_pedersen_verify_tally(ctx: *const Context, - commits: *const *const c_uchar, - pcnt: c_int, - ncommits: *const *const c_uchar, - ncnt: c_int, - excess: int64_t) - -> c_int; + // Takes two list of 33-byte commitments and sums the first set and + // subtracts the second and verifies that they sum to excess. + pub fn secp256k1_pedersen_verify_tally(ctx: *const Context, + commits: *const *const c_uchar, + pcnt: c_int, + ncommits: *const *const c_uchar, + ncnt: c_int, + excess: int64_t) + -> c_int; - pub fn secp256k1_rangeproof_info(ctx: *const Context, - exp: *mut c_int, - mantissa: *mut c_int, - min_value: *mut uint64_t, - max_value: *mut uint64_t, - proof: *const c_uchar, - plen: c_int) - -> c_int; + pub fn secp256k1_rangeproof_info(ctx: *const Context, + exp: *mut c_int, + mantissa: *mut c_int, + min_value: *mut uint64_t, + max_value: *mut uint64_t, + proof: *const c_uchar, + plen: c_int) + -> c_int; - pub fn secp256k1_rangeproof_rewind(ctx: *const Context, - blind_out: *mut c_uchar, - value_out: *mut uint64_t, - message_out: *mut c_uchar, - outlen: *mut c_int, - nonce: *const c_uchar, - min_value: *mut uint64_t, - max_value: *mut uint64_t, - commit: *const c_uchar, - proof: *const c_uchar, - plen: c_int) - -> c_int; + pub fn secp256k1_rangeproof_rewind(ctx: *const Context, + blind_out: *mut c_uchar, + value_out: *mut uint64_t, + message_out: *mut c_uchar, + outlen: *mut c_int, + nonce: *const c_uchar, + min_value: *mut uint64_t, + max_value: *mut uint64_t, + commit: *const c_uchar, + proof: *const c_uchar, + plen: c_int) + -> c_int; - pub fn secp256k1_rangeproof_verify(ctx: *const Context, - min_value: &mut uint64_t, - max_value: &mut uint64_t, - commit: *const c_uchar, - proof: *const c_uchar, - plen: c_int) - -> c_int; + pub fn secp256k1_rangeproof_verify(ctx: *const Context, + min_value: &mut uint64_t, + max_value: &mut uint64_t, + commit: *const c_uchar, + proof: *const c_uchar, + plen: c_int) + -> c_int; - pub fn secp256k1_rangeproof_sign(ctx: *const Context, - proof: *mut c_uchar, - plen: *mut c_int, - min_value: uint64_t, - commit: *const c_uchar, - blind: *const c_uchar, - nonce: *const c_uchar, - exp: c_int, - min_bits: c_int, - value: uint64_t) - -> c_int; + pub fn secp256k1_rangeproof_sign(ctx: *const Context, + proof: *mut c_uchar, + plen: *mut c_int, + min_value: uint64_t, + commit: *const c_uchar, + blind: *const c_uchar, + nonce: *const c_uchar, + exp: c_int, + min_bits: c_int, + value: uint64_t) + -> c_int; } diff --git a/secp256k1zkp/src/key.rs b/secp256k1zkp/src/key.rs index 51d49121e..6eaf259f3 100644 --- a/secp256k1zkp/src/key.rs +++ b/secp256k1zkp/src/key.rs @@ -15,6 +15,7 @@ //! # Public and secret keys +use std::fmt; use std::intrinsics::copy_nonoverlapping; use std::marker; use arrayvec::ArrayVec; @@ -52,441 +53,445 @@ pub struct PublicKey(ffi::PublicKey); fn random_32_bytes(rng: &mut R) -> [u8; 32] { - let mut ret = [0u8; 32]; - rng.fill_bytes(&mut ret); - ret + let mut ret = [0u8; 32]; + rng.fill_bytes(&mut ret); + ret } impl SecretKey { - /// Creates a new random secret key - #[inline] - 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(rng); - } - } - SecretKey(data) - } + /// Creates a new random secret key + #[inline] + 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(rng); + } + } + SecretKey(data) + } - /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key - #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { - match data.len() { - constants::SECRET_KEY_SIZE => { - let mut ret = [0; constants::SECRET_KEY_SIZE]; - unsafe { - if ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { - return Err(InvalidSecretKey); - } - copy_nonoverlapping(data.as_ptr(), ret.as_mut_ptr(), data.len()); - } - Ok(SecretKey(ret)) - } - _ => Err(InvalidSecretKey), - } - } + /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key + #[inline] + pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { + match data.len() { + constants::SECRET_KEY_SIZE => { + let mut ret = [0; constants::SECRET_KEY_SIZE]; + unsafe { + if ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 { + return Err(InvalidSecretKey); + } + copy_nonoverlapping(data.as_ptr(), ret.as_mut_ptr(), data.len()); + } + Ok(SecretKey(ret)) + } + _ => Err(InvalidSecretKey), + } + } - #[inline] - /// Adds one secret key to another, modulo the curve order - 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(InvalidSecretKey) - } else { - Ok(()) - } - } - } + #[inline] + /// Adds one secret key to another, modulo the curve order + 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(InvalidSecretKey) + } else { + Ok(()) + } + } + } - #[inline] - /// Multiplies one secret key by another, modulo the curve order - pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) -> Result<(), Error> { - unsafe { - if ffi::secp256k1_ec_privkey_tweak_mul(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != - 1 { - Err(InvalidSecretKey) - } else { - Ok(()) - } - } - } + #[inline] + /// Multiplies one secret key by another, modulo the curve order + pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) -> Result<(), Error> { + unsafe { + if ffi::secp256k1_ec_privkey_tweak_mul(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != + 1 { + Err(InvalidSecretKey) + } else { + Ok(()) + } + } + } } impl PublicKey { - /// Creates a new zeroed out public key - #[inline] - pub fn new() -> PublicKey { - PublicKey(ffi::PublicKey::new()) - } + /// Creates a new zeroed out public key + #[inline] + pub fn new() -> PublicKey { + PublicKey(ffi::PublicKey::new()) + } - /// Determines whether a pubkey is valid - #[inline] - pub fn is_valid(&self) -> bool { - // The only invalid pubkey the API should be able to create is - // the zero one. - self.0[..].iter().any(|&x| x != 0) - } + /// Determines whether a pubkey is valid + #[inline] + pub fn is_valid(&self) -> bool { + // The only invalid pubkey the API should be able to create is + // the zero one. + self.0[..].iter().any(|&x| x != 0) + } - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::PublicKey { - &self.0 as *const _ - } + /// Obtains a raw pointer suitable for use with FFI functions + #[inline] + pub fn as_ptr(&self) -> *const ffi::PublicKey { + &self.0 as *const _ + } - /// Creates a new public key from a secret key. - #[inline] - pub fn from_secret_key(secp: &Secp256k1, sk: &SecretKey) -> Result { - if secp.caps == ContextFlag::VerifyOnly || secp.caps == ContextFlag::None { - return Err(IncapableContext); - } - let mut pk = unsafe { ffi::PublicKey::blank() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid `SecretKey` without transmute trickery or something - let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr()); - debug_assert_eq!(res, 1); - } - Ok(PublicKey(pk)) - } + /// Creates a new public key from a secret key. + #[inline] + pub fn from_secret_key(secp: &Secp256k1, sk: &SecretKey) -> Result { + if secp.caps == ContextFlag::VerifyOnly || secp.caps == ContextFlag::None { + return Err(IncapableContext); + } + let mut pk = unsafe { ffi::PublicKey::blank() }; + unsafe { + // We can assume the return value because it's not possible to construct + // an invalid `SecretKey` without transmute trickery or something + let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr()); + debug_assert_eq!(res, 1); + } + Ok(PublicKey(pk)) + } - /// Creates a public key directly from a slice - #[inline] - pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { + /// Creates a public key directly from a slice + #[inline] + pub fn from_slice(secp: &Secp256k1, data: &[u8]) -> Result { - let mut pk = unsafe { ffi::PublicKey::blank() }; - unsafe { - if ffi::secp256k1_ec_pubkey_parse(secp.ctx, - &mut pk, - data.as_ptr(), - data.len() as ::libc::size_t) == 1 { - Ok(PublicKey(pk)) - } else { - Err(InvalidPublicKey) - } - } - } + let mut pk = unsafe { ffi::PublicKey::blank() }; + unsafe { + if ffi::secp256k1_ec_pubkey_parse(secp.ctx, + &mut pk, + data.as_ptr(), + data.len() as ::libc::size_t) == 1 { + Ok(PublicKey(pk)) + } else { + Err(InvalidPublicKey) + } + } + } - #[inline] - /// 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(); + #[inline] + /// 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(); - 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); - debug_assert_eq!(err, 1); - ret.set_len(ret_len as usize); - } - ret - } + 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); + debug_assert_eq!(err, 1); + ret.set_len(ret_len as usize); + } + ret + } - #[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> { - if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { - return Err(IncapableContext); - } - unsafe { - if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, - &mut self.0 as *mut _, - other.as_ptr()) == 1 { - Ok(()) - } else { - Err(InvalidSecretKey) - } - } - } + #[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> { + if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { + return Err(IncapableContext); + } + unsafe { + if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, + &mut self.0 as *mut _, + other.as_ptr()) == 1 { + Ok(()) + } else { + Err(InvalidSecretKey) + } + } + } - #[inline] - /// Muliplies the pk `self` in place by the scalar `other` - pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) -> Result<(), Error> { - if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { - return Err(IncapableContext); - } - unsafe { - if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, - &mut self.0 as *mut _, - other.as_ptr()) == 1 { - Ok(()) - } else { - Err(InvalidSecretKey) - } - } - } + #[inline] + /// Muliplies the pk `self` in place by the scalar `other` + pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) -> Result<(), Error> { + if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None { + return Err(IncapableContext); + } + unsafe { + if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, + &mut self.0 as *mut _, + other.as_ptr()) == 1 { + Ok(()) + } else { + Err(InvalidSecretKey) + } + } + } } impl Decodable for PublicKey { - fn decode(d: &mut D) -> Result { - d.read_seq(|d, len| { - let s = Secp256k1::with_caps(::ContextFlag::None); - if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { - unsafe { - use std::mem; - let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = - mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) - } - } else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE { - unsafe { - use std::mem; - let mut ret: [u8; constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); - for i in 0..len { - ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); - } - PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) - } - } else { - Err(d.error("Invalid length")) - } - }) - } + fn decode(d: &mut D) -> Result { + d.read_seq(|d, len| { + let s = Secp256k1::with_caps(::ContextFlag::None); + if len == constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { + unsafe { + use std::mem; + let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = + mem::uninitialized(); + for i in 0..len { + ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) + } + } else if len == constants::COMPRESSED_PUBLIC_KEY_SIZE { + unsafe { + use std::mem; + let mut ret: [u8; constants::COMPRESSED_PUBLIC_KEY_SIZE] = mem::uninitialized(); + for i in 0..len { + ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + PublicKey::from_slice(&s, &ret).map_err(|_| d.error("invalid public key")) + } + } else { + Err(d.error("Invalid length")) + } + }) + } } /// Creates a new public key from a FFI public key impl From for PublicKey { - #[inline] - fn from(pk: ffi::PublicKey) -> PublicKey { - PublicKey(pk) - } + #[inline] + fn from(pk: ffi::PublicKey) -> PublicKey { + PublicKey(pk) + } } 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) - } + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + let secp = Secp256k1::with_caps(::ContextFlag::None); + self.serialize_vec(&secp, true).encode(s) + } } -impl Deserialize for PublicKey { - fn deserialize(d: &mut D) -> Result - where D: Deserializer - { - use serde::de; - struct Visitor { - marker: marker::PhantomData, - } - impl de::Visitor for Visitor { - type Value = PublicKey; +impl<'de> Deserialize<'de> for PublicKey { + fn deserialize(d: D) -> Result + where D: Deserializer<'de> + { + use serde::de; + struct Visitor { + marker: marker::PhantomData, + } + impl<'di> de::Visitor<'di> for Visitor { + type Value = PublicKey; - #[inline] - fn visit_seq(&mut self, mut v: V) -> Result - where V: de::SeqVisitor - { - debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= - constants::COMPRESSED_PUBLIC_KEY_SIZE); + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an array of bytes") + } - let s = Secp256k1::with_caps(::ContextFlag::None); - unsafe { - use std::mem; - let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = - mem::uninitialized(); + #[inline] + fn visit_seq(self, mut v: V) -> Result + where V: ::serde::de::SeqAccess<'di> + { + debug_assert!(constants::UNCOMPRESSED_PUBLIC_KEY_SIZE >= + constants::COMPRESSED_PUBLIC_KEY_SIZE); - let mut read_len = 0; - while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { - let read_ch = match try!(v.visit()) { - Some(c) => c, - None => break, - }; - ret[read_len] = read_ch; - read_len += 1; - } - try!(v.end()); + let s = Secp256k1::with_caps(::ContextFlag::None); + unsafe { + use std::mem; + let mut ret: [u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE] = + mem::uninitialized(); - PublicKey::from_slice(&s, &ret[..read_len]) - .map_err(|e| de::Error::syntax(&e.to_string())) - } - } - } + let mut read_len = 0; + while read_len < constants::UNCOMPRESSED_PUBLIC_KEY_SIZE { + let read_ch = match try!(v.next_element()) { + Some(c) => c, + None => break, + }; + ret[read_len] = read_ch; + read_len += 1; + } - // Begin actual function - d.visit(Visitor { marker: ::std::marker::PhantomData }) - } + PublicKey::from_slice(&s, &ret[..read_len]) + .map_err(|e| de::Error::custom(&e.to_string())) + } + } + } + + // Begin actual function + d.deserialize_seq(Visitor { marker: ::std::marker::PhantomData }) + } } impl Serialize for PublicKey { - fn serialize(&self, s: &mut S) -> Result<(), S::Error> - where S: Serializer - { - let secp = Secp256k1::with_caps(::ContextFlag::None); - (&self.serialize_vec(&secp, true)[..]).serialize(s) - } + fn serialize(&self, s: S) -> Result + where S: Serializer + { + let secp = Secp256k1::with_caps(::ContextFlag::None); + (&self.serialize_vec(&secp, true)[..]).serialize(s) + } } #[cfg(test)] mod test { - use super::super::{Secp256k1, ContextFlag}; - use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext}; - use super::{PublicKey, SecretKey}; - use super::super::constants; + use super::super::{Secp256k1, ContextFlag}; + use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext}; + use super::{PublicKey, SecretKey}; + use super::super::constants; + extern crate serde_json; - use rand::{Rng, thread_rng}; + use rand::{Rng, thread_rng}; - #[test] - fn skey_from_slice() { - let s = Secp256k1::new(); - let sk = SecretKey::from_slice(&s, &[1; 31]); - assert_eq!(sk, Err(InvalidSecretKey)); + #[test] + fn skey_from_slice() { + let s = Secp256k1::new(); + let sk = SecretKey::from_slice(&s, &[1; 31]); + assert_eq!(sk, Err(InvalidSecretKey)); - let sk = SecretKey::from_slice(&s, &[1; 32]); - assert!(sk.is_ok()); - } + let sk = SecretKey::from_slice(&s, &[1; 32]); + assert!(sk.is_ok()); + } - #[test] - fn pubkey_from_slice() { - let s = Secp256k1::new(); - assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey)); + #[test] + fn pubkey_from_slice() { + let s = Secp256k1::new(); + assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey)); + assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey)); - let uncompressed = - PublicKey::from_slice(&s, - &[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, - 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, - 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, - 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, - 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]); - assert!(uncompressed.is_ok()); + let uncompressed = + PublicKey::from_slice(&s, + &[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, + 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, + 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, + 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, + 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]); + assert!(uncompressed.is_ok()); - let compressed = PublicKey::from_slice(&s, - &[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, - 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, - 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, - 78]); - assert!(compressed.is_ok()); - } + let compressed = PublicKey::from_slice(&s, + &[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, + 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, + 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, + 78]); + assert!(compressed.is_ok()); + } - #[test] - fn keypair_slice_round_trip() { - let s = Secp256k1::new(); + #[test] + fn keypair_slice_round_trip() { + let s = Secp256k1::new(); - 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)); - } + 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)); + } - #[test] - fn invalid_secret_key() { - let s = Secp256k1::new(); - // Zero - assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey)); - // -1 - assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), - Err(InvalidSecretKey)); - // Top of range - assert!(SecretKey::from_slice(&s, - &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, - 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, - 0x8C, 0xD0, 0x36, 0x41, 0x40]) - .is_ok()); - // One past top of range - assert!(SecretKey::from_slice(&s, - &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, - 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, - 0x8C, 0xD0, 0x36, 0x41, 0x41]) - .is_err()); - } + #[test] + fn invalid_secret_key() { + let s = Secp256k1::new(); + // Zero + assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey)); + // -1 + assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), + Err(InvalidSecretKey)); + // Top of range + assert!(SecretKey::from_slice(&s, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, + 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, + 0x8C, 0xD0, 0x36, 0x41, 0x40]) + .is_ok()); + // One past top of range + assert!(SecretKey::from_slice(&s, + &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, + 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, + 0x8C, 0xD0, 0x36, 0x41, 0x41]) + .is_err()); + } - #[test] - fn test_pubkey_from_slice_bad_context() { - let s = Secp256k1::without_caps(); - let sk = SecretKey::new(&s, &mut thread_rng()); - assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); + #[test] + fn test_pubkey_from_slice_bad_context() { + let s = Secp256k1::without_caps(); + let sk = SecretKey::new(&s, &mut thread_rng()); + assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); - let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); - assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); + let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); + assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext)); - let s = Secp256k1::with_caps(ContextFlag::SignOnly); - assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); + let s = Secp256k1::with_caps(ContextFlag::SignOnly); + assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); - let s = Secp256k1::with_caps(ContextFlag::Full); - assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); - } + let s = Secp256k1::with_caps(ContextFlag::Full); + assert!(PublicKey::from_secret_key(&s, &sk).is_ok()); + } - #[test] - fn test_add_exp_bad_context() { - let s = Secp256k1::with_caps(ContextFlag::Full); - let (sk, mut pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + #[test] + fn test_add_exp_bad_context() { + let s = Secp256k1::with_caps(ContextFlag::Full); + let (sk, mut pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - assert!(pk.add_exp_assign(&s, &sk).is_ok()); + assert!(pk.add_exp_assign(&s, &sk).is_ok()); - let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); - assert!(pk.add_exp_assign(&s, &sk).is_ok()); + let s = Secp256k1::with_caps(ContextFlag::VerifyOnly); + assert!(pk.add_exp_assign(&s, &sk).is_ok()); - let s = Secp256k1::with_caps(ContextFlag::SignOnly); - assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); + let s = Secp256k1::with_caps(ContextFlag::SignOnly); + assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); - let s = Secp256k1::with_caps(ContextFlag::None); - assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); - } + let s = Secp256k1::with_caps(ContextFlag::None); + assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext)); + } - #[test] - fn test_bad_deserialize() { - use std::io::Cursor; - use serialize::{json, Decodable}; + #[test] + fn test_bad_deserialize() { + use std::io::Cursor; + use serialize::{json, Decodable}; - let zero31 = "[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]".as_bytes(); - let json31 = json::Json::from_reader(&mut Cursor::new(zero31)).unwrap(); - let zero32 = "[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,0]".as_bytes(); - let json32 = json::Json::from_reader(&mut Cursor::new(zero32)).unwrap(); - let zero65 = "[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,0,0,0,0,0,0,\ + let zero31 = "[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]".as_bytes(); + let json31 = json::Json::from_reader(&mut Cursor::new(zero31)).unwrap(); + let zero32 = "[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,0]".as_bytes(); + let json32 = json::Json::from_reader(&mut Cursor::new(zero32)).unwrap(); + let zero65 = "[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,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,0,0,0]" - .as_bytes(); - let json65 = json::Json::from_reader(&mut Cursor::new(zero65)).unwrap(); - let string = "\"my key\"".as_bytes(); - let json = json::Json::from_reader(&mut Cursor::new(string)).unwrap(); + .as_bytes(); + let json65 = json::Json::from_reader(&mut Cursor::new(zero65)).unwrap(); + let string = "\"my key\"".as_bytes(); + let json = json::Json::from_reader(&mut Cursor::new(string)).unwrap(); - // Invalid length - let mut decoder = json::Decoder::new(json31.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json31.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json32.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json32.clone()); - assert!(::decode(&mut decoder).is_ok()); - let mut decoder = json::Decoder::new(json65.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json65.clone()); - assert!(::decode(&mut decoder).is_err()); + // Invalid length + let mut decoder = json::Decoder::new(json31.clone()); + assert!(::decode(&mut decoder).is_err()); + let mut decoder = json::Decoder::new(json31.clone()); + assert!(::decode(&mut decoder).is_err()); + let mut decoder = json::Decoder::new(json32.clone()); + assert!(::decode(&mut decoder).is_err()); + let mut decoder = json::Decoder::new(json32.clone()); + assert!(::decode(&mut decoder).is_ok()); + let mut decoder = json::Decoder::new(json65.clone()); + assert!(::decode(&mut decoder).is_err()); + let mut decoder = json::Decoder::new(json65.clone()); + assert!(::decode(&mut decoder).is_err()); - // Syntax error - let mut decoder = json::Decoder::new(json.clone()); - assert!(::decode(&mut decoder).is_err()); - let mut decoder = json::Decoder::new(json.clone()); - assert!(::decode(&mut decoder).is_err()); - } + // Syntax error + let mut decoder = json::Decoder::new(json.clone()); + assert!(::decode(&mut decoder).is_err()); + let mut decoder = json::Decoder::new(json.clone()); + assert!(::decode(&mut decoder).is_err()); + } - #[test] - fn test_serialize() { - use std::io::Cursor; - use serialize::{json, Decodable, Encodable}; + #[test] + fn test_serialize() { + use std::io::Cursor; + use serialize::{json, Decodable, Encodable}; - macro_rules! round_trip ( + macro_rules! round_trip ( ($var:ident) => ({ let start = $var; let mut encoded = String::new(); @@ -501,220 +506,205 @@ mod test { }) ); - let s = Secp256k1::new(); - for _ in 0..500 { - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - round_trip!(sk); - round_trip!(pk); - } - } + let s = Secp256k1::new(); + for _ in 0..500 { + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + round_trip!(sk); + round_trip!(pk); + } + } - #[test] - fn test_bad_serde_deserialize() { - use serde::Deserialize; - use json; + #[test] + fn test_bad_serde_deserialize() { + use serde::Deserialize; + use json; - // Invalid length - let zero31 = "[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]".as_bytes(); - let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero31.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); + // Invalid length + let zero31 = "[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]"; + assert!(serde_json::from_str::(zero31).is_err()); + assert!(serde_json::from_str::(zero31).is_err()); - let zero32 = "[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,0]".as_bytes(); - let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero32.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_ok()); + let zero32 = "[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,0]"; + assert!(serde_json::from_str::(zero32).is_err()); + assert!(serde_json::from_str::(zero32).is_ok()); - // All zeroes pk is invalid - let zero65 = "[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,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,0,0,0]" - .as_bytes(); - let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(zero65.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); + // All zeroes pk is invalid + let zero65 = "[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,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,0,0,0]"; + assert!(serde_json::from_str::(zero31).is_err()); + assert!(serde_json::from_str::(zero31).is_err()); - // Syntax error - let string = "\"my key\"".as_bytes(); - let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - let mut json = json::de::Deserializer::new(string.iter().map(|c| Ok(*c))); - assert!(::deserialize(&mut json).is_err()); - } + // Syntax error + let string = "\"my key\""; + assert!(serde_json::from_str::(zero31).is_err()); + assert!(serde_json::from_str::(zero31).is_err()); + } - #[test] - fn test_serialize_serde() { - use serde::{Serialize, Deserialize}; - use json; + #[test] + fn test_serialize_serde() { + use serde::{Serialize, Deserialize}; + use json; - macro_rules! round_trip ( - ($var:ident) => ({ - let start = $var; - let mut encoded = Vec::new(); - { - let mut serializer = json::ser::Serializer::new(&mut encoded); - start.serialize(&mut serializer).unwrap(); - } - let mut deserializer = json::de::Deserializer::new(encoded.iter().map(|c| Ok(*c))); - let decoded = Deserialize::deserialize(&mut deserializer); - assert_eq!(Some(start), decoded.ok()); - }) + macro_rules! round_trip ( + ($e:ident, $d:ty) => { + let json = serde_json::to_string(&$e).unwrap(); + assert!(json.len() > 0); + assert!(serde_json::from_str::<$d>(json.as_str()).is_ok()); + } ); - let s = Secp256k1::new(); - for _ in 0..500 { - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - round_trip!(sk); - round_trip!(pk); - } - } + let s = Secp256k1::new(); + for _ in 0..500 { + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + // round_trip!(sk, SecretKey); + round_trip!(pk, PublicKey); + } + } - #[test] - fn test_out_of_range() { + #[test] + fn test_out_of_range() { - struct BadRng(u8); - impl Rng for BadRng { - fn next_u32(&mut self) -> u32 { - unimplemented!() - } - // This will set a secret key to a little over the - // group order, then decrement with repeated calls - // until it returns a valid key - fn fill_bytes(&mut self, data: &mut [u8]) { - let group_order: [u8; 32] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, - 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, - 0x8c, 0xd0, 0x36, 0x41, 0x41]; - assert_eq!(data.len(), 32); - unsafe { - use std::intrinsics::copy_nonoverlapping; - copy_nonoverlapping(group_order.as_ptr(), data.as_mut_ptr(), 32); - } - data[31] = self.0; - self.0 -= 1; - } - } + struct BadRng(u8); + impl Rng for BadRng { + fn next_u32(&mut self) -> u32 { + unimplemented!() + } + // This will set a secret key to a little over the + // group order, then decrement with repeated calls + // until it returns a valid key + fn fill_bytes(&mut self, data: &mut [u8]) { + let group_order: [u8; 32] = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, + 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, + 0x8c, 0xd0, 0x36, 0x41, 0x41]; + assert_eq!(data.len(), 32); + unsafe { + use std::intrinsics::copy_nonoverlapping; + copy_nonoverlapping(group_order.as_ptr(), data.as_mut_ptr(), 32); + } + data[31] = self.0; + self.0 -= 1; + } + } - let s = Secp256k1::new(); - s.generate_keypair(&mut BadRng(0xff)).unwrap(); - } + let s = Secp256k1::new(); + s.generate_keypair(&mut BadRng(0xff)).unwrap(); + } - #[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]), + #[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]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]), + assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), + assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]), Err(InvalidPublicKey)); - assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]), + assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]), Err(InvalidPublicKey)); - // Bad parse - assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]), + // 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::COMPRESSED_PUBLIC_KEY_SIZE]), Err(InvalidPublicKey)); - } + } - #[test] - fn test_debug_output() { - struct DumbRng(u32); - impl Rng for DumbRng { - fn next_u32(&mut self) -> u32 { - self.0 = self.0.wrapping_add(1); - self.0 - } - } + #[test] + fn test_debug_output() { + struct DumbRng(u32); + impl Rng for DumbRng { + fn next_u32(&mut self) -> u32 { + self.0 = self.0.wrapping_add(1); + self.0 + } + } - let s = Secp256k1::new(); - let (sk, _) = s.generate_keypair(&mut DumbRng(0)).unwrap(); + let s = Secp256k1::new(); + let (sk, _) = s.generate_keypair(&mut DumbRng(0)).unwrap(); - assert_eq!(&format!("{:?}", sk), + assert_eq!(&format!("{:?}", sk), "SecretKey(0200000001000000040000000300000006000000050000000800000007000000)"); - } + } - #[test] - fn test_pubkey_serialize() { - struct DumbRng(u32); - impl Rng for DumbRng { - fn next_u32(&mut self) -> u32 { - self.0 = self.0.wrapping_add(1); - self.0 - } - } + #[test] + fn test_pubkey_serialize() { + struct DumbRng(u32); + impl Rng for DumbRng { + fn next_u32(&mut self) -> u32 { + self.0 = self.0.wrapping_add(1); + self.0 + } + } - let s = Secp256k1::new(); - let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap(); - assert_eq!(&pk1.serialize_vec(&s, false)[..], + let s = Secp256k1::new(); + let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap(); + assert_eq!(&pk1.serialize_vec(&s, false)[..], &[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_vec(&s, true)[..], &[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][..]); - } + } - #[test] - fn test_addition() { - let s = Secp256k1::new(); + #[test] + fn test_addition() { + let s = Secp256k1::new(); - let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); - assert!(sk1.add_assign(&s, &sk2).is_ok()); - assert!(pk1.add_exp_assign(&s, &sk2).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); + assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); + assert!(sk1.add_assign(&s, &sk2).is_ok()); + assert!(pk1.add_exp_assign(&s, &sk2).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); - assert!(sk2.add_assign(&s, &sk1).is_ok()); - assert!(pk2.add_exp_assign(&s, &sk1).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); - } + assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); + assert!(sk2.add_assign(&s, &sk1).is_ok()); + assert!(pk2.add_exp_assign(&s, &sk1).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); + } - #[test] - fn test_multiplication() { - let s = Secp256k1::new(); + #[test] + fn test_multiplication() { + let s = Secp256k1::new(); - let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); - let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap(); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); - assert!(sk1.mul_assign(&s, &sk2).is_ok()); - assert!(pk1.mul_assign(&s, &sk2).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); + assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); + assert!(sk1.mul_assign(&s, &sk2).is_ok()); + assert!(pk1.mul_assign(&s, &sk2).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); - assert!(sk2.mul_assign(&s, &sk1).is_ok()); - assert!(pk2.mul_assign(&s, &sk1).is_ok()); - assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); - } + assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); + assert!(sk2.mul_assign(&s, &sk1).is_ok()); + assert!(pk2.mul_assign(&s, &sk1).is_ok()); + assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2); + } - #[test] - fn pubkey_hash() { - use std::hash::{Hash, SipHasher, Hasher}; - use std::collections::HashSet; + #[test] + fn pubkey_hash() { + use std::hash::{Hash, SipHasher, Hasher}; + use std::collections::HashSet; - fn hash(t: &T) -> u64 { - let mut s = SipHasher::new(); - t.hash(&mut s); - s.finish() - } + fn hash(t: &T) -> u64 { + let mut s = SipHasher::new(); + t.hash(&mut s); + s.finish() + } - let s = Secp256k1::new(); - let mut set = HashSet::new(); - const COUNT: usize = 1024; - let count = (0..COUNT) - .map(|_| { - let (_, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let hash = hash(&pk); - assert!(!set.contains(&hash)); - set.insert(hash); - }) - .count(); - assert_eq!(count, COUNT); - } + let s = Secp256k1::new(); + let mut set = HashSet::new(); + const COUNT: usize = 1024; + let count = (0..COUNT) + .map(|_| { + let (_, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let hash = hash(&pk); + assert!(!set.contains(&hash)); + set.insert(hash); + }) + .count(); + assert_eq!(count, COUNT); + } } diff --git a/secp256k1zkp/src/lib.rs b/secp256k1zkp/src/lib.rs index 29878fa29..5a7fce20d 100644 --- a/secp256k1zkp/src/lib.rs +++ b/secp256k1zkp/src/lib.rs @@ -70,9 +70,9 @@ pub struct RecoveryId(i32); pub struct Signature(ffi::Signature); impl std::convert::AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0.as_ref() - } + fn as_ref(&self) -> &[u8] { + &self.0.as_ref() + } } /// An ECDSA signature with a recovery ID for pubkey recovery @@ -80,227 +80,229 @@ impl std::convert::AsRef<[u8]> for Signature { pub struct RecoverableSignature(ffi::RecoverableSignature); impl RecoveryId { - #[inline] - /// Allows library users to create valid recovery IDs from i32. - pub fn from_i32(id: i32) -> Result { - match id { - 0 | 1 | 2 | 3 => Ok(RecoveryId(id)), - _ => Err(Error::InvalidRecoveryId), - } - } + #[inline] + /// Allows library users to create valid recovery IDs from i32. + pub fn from_i32(id: i32) -> Result { + match id { + 0 | 1 | 2 | 3 => Ok(RecoveryId(id)), + _ => Err(Error::InvalidRecoveryId), + } + } - #[inline] - /// Allows library users to convert recovery IDs to i32. - pub fn to_i32(&self) -> i32 { - self.0 - } + #[inline] + /// Allows library users to convert recovery IDs to i32. + pub fn to_i32(&self) -> i32 { + self.0 + } } impl Signature { - #[inline] - /// Converts a DER-encoded byte slice to a signature - pub fn from_der(secp: &Secp256k1, data: &[u8]) -> Result { - let mut ret = unsafe { ffi::Signature::blank() }; + #[inline] + /// Converts a DER-encoded byte slice to a signature + pub fn from_der(secp: &Secp256k1, data: &[u8]) -> Result { + let mut ret = unsafe { ffi::Signature::blank() }; - unsafe { - if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, - &mut ret, - data.as_ptr(), - data.len() as libc::size_t) == - 1 { - Ok(Signature(ret)) - } else { - Err(Error::InvalidSignature) - } - } - } + unsafe { + if ffi::secp256k1_ecdsa_signature_parse_der(secp.ctx, + &mut ret, + data.as_ptr(), + data.len() as libc::size_t) == 1 { + Ok(Signature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } - /// Converts a "lax DER"-encoded byte slice to a signature. This is basically - /// only useful for validating signatures in the Bitcoin blockchain from before - /// 2016. It should never be used in new applications. This library does not - /// support serializing to this "format" - pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result { - unsafe { - let mut ret = ffi::Signature::blank(); - if ffi::ecdsa_signature_parse_der_lax(secp.ctx, - &mut ret, - data.as_ptr(), - data.len() as libc::size_t) == 1 { - Ok(Signature(ret)) - } else { - Err(Error::InvalidSignature) - } - } - } + /// Converts a "lax DER"-encoded byte slice to a signature. This is + /// basically + /// only useful for validating signatures in the Bitcoin blockchain from + /// before + /// 2016. It should never be used in new applications. This library does not + /// support serializing to this "format" + pub fn from_der_lax(secp: &Secp256k1, data: &[u8]) -> Result { + unsafe { + let mut ret = ffi::Signature::blank(); + if ffi::ecdsa_signature_parse_der_lax(secp.ctx, + &mut ret, + data.as_ptr(), + data.len() as libc::size_t) == 1 { + Ok(Signature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } - /// Normalizes a signature to a "low S" form. In ECDSA, signatures are - /// of the form (r, s) where r and s are numbers lying in some finite - /// field. The verification equation will pass for (r, s) iff it passes - /// for (r, -s), so it is possible to ``modify'' signatures in transit - /// by flipping the sign of s. This does not constitute a forgery since - /// the signed message still cannot be changed, but for some applications, - /// changing even the signature itself can be a problem. Such applications - /// require a "strong signature". It is believed that ECDSA is a strong - /// signature except for this ambiguity in the sign of s, so to accomodate - /// these applications libsecp256k1 will only accept signatures for which - /// s is in the lower half of the field range. This eliminates the - /// ambiguity. - /// - /// However, for some systems, signatures with high s-values are considered - /// valid. (For example, parsing the historic Bitcoin blockchain requires - /// this.) For these applications we provide this normalization function, - /// which ensures that the s value lies in the lower half of its range. - pub fn normalize_s(&mut self, secp: &Secp256k1) { - unsafe { - // Ignore return value, which indicates whether the sig - // was already normalized. We don't care. - ffi::secp256k1_ecdsa_signature_normalize(secp.ctx, self.as_mut_ptr(), self.as_ptr()); - } - } + /// Normalizes a signature to a "low S" form. In ECDSA, signatures are + /// of the form (r, s) where r and s are numbers lying in some finite + /// field. The verification equation will pass for (r, s) iff it passes + /// for (r, -s), so it is possible to ``modify'' signatures in transit + /// by flipping the sign of s. This does not constitute a forgery since + /// the signed message still cannot be changed, but for some applications, + /// changing even the signature itself can be a problem. Such applications + /// require a "strong signature". It is believed that ECDSA is a strong + /// signature except for this ambiguity in the sign of s, so to accomodate + /// these applications libsecp256k1 will only accept signatures for which + /// s is in the lower half of the field range. This eliminates the + /// ambiguity. + /// + /// However, for some systems, signatures with high s-values are considered + /// valid. (For example, parsing the historic Bitcoin blockchain requires + /// this.) For these applications we provide this normalization function, + /// which ensures that the s value lies in the lower half of its range. + pub fn normalize_s(&mut self, secp: &Secp256k1) { + unsafe { + // Ignore return value, which indicates whether the sig + // was already normalized. We don't care. + ffi::secp256k1_ecdsa_signature_normalize(secp.ctx, self.as_mut_ptr(), self.as_ptr()); + } + } - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::Signature { - &self.0 as *const _ - } + /// Obtains a raw pointer suitable for use with FFI functions + #[inline] + pub fn as_ptr(&self) -> *const ffi::Signature { + &self.0 as *const _ + } - /// Obtains a raw mutable pointer suitable for use with FFI functions - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { - &mut self.0 as *mut _ - } + /// Obtains a raw mutable pointer suitable for use with FFI functions + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { + &mut self.0 as *mut _ + } - #[inline] - /// Serializes the signature in DER format - pub fn serialize_der(&self, secp: &Secp256k1) -> Vec { - let mut ret = Vec::with_capacity(72); - let mut len: size_t = ret.capacity() as size_t; - unsafe { - let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, - ret.as_mut_ptr(), - &mut len, - self.as_ptr()); - debug_assert!(err == 1); - ret.set_len(len as usize); - } - ret - } + #[inline] + /// Serializes the signature in DER format + pub fn serialize_der(&self, secp: &Secp256k1) -> Vec { + let mut ret = Vec::with_capacity(72); + let mut len: size_t = ret.capacity() as size_t; + unsafe { + let err = ffi::secp256k1_ecdsa_signature_serialize_der(secp.ctx, + ret.as_mut_ptr(), + &mut len, + self.as_ptr()); + debug_assert!(err == 1); + ret.set_len(len as usize); + } + ret + } } /// Creates a new signature from a FFI signature impl From for Signature { - #[inline] - fn from(sig: ffi::Signature) -> Signature { - Signature(sig) - } + #[inline] + fn from(sig: ffi::Signature) -> Signature { + Signature(sig) + } } impl RecoverableSignature { - #[inline] - /// Converts a compact-encoded byte slice to a signature. This - /// representation is nonstandard and defined by the libsecp256k1 - /// library. - pub fn from_compact(secp: &Secp256k1, - data: &[u8], - recid: RecoveryId) - -> Result { - let mut ret = unsafe { ffi::RecoverableSignature::blank() }; + #[inline] + /// Converts a compact-encoded byte slice to a signature. This + /// representation is nonstandard and defined by the libsecp256k1 + /// library. + pub fn from_compact(secp: &Secp256k1, + data: &[u8], + recid: RecoveryId) + -> Result { + let mut ret = unsafe { ffi::RecoverableSignature::blank() }; - unsafe { - if data.len() != 64 { - Err(Error::InvalidSignature) - } else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(secp.ctx, - &mut ret, - data.as_ptr(), - recid.0) == - 1 { - Ok(RecoverableSignature(ret)) - } else { - Err(Error::InvalidSignature) - } - } - } + unsafe { + if data.len() != 64 { + Err(Error::InvalidSignature) + } else if ffi::secp256k1_ecdsa_recoverable_signature_parse_compact(secp.ctx, + &mut ret, + data.as_ptr(), + recid.0) == + 1 { + Ok(RecoverableSignature(ret)) + } else { + Err(Error::InvalidSignature) + } + } + } - /// Obtains a raw pointer suitable for use with FFI functions - #[inline] - pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { - &self.0 as *const _ - } + /// Obtains a raw pointer suitable for use with FFI functions + #[inline] + pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { + &self.0 as *const _ + } - #[inline] - /// Serializes the recoverable signature in compact format - pub fn serialize_compact(&self, secp: &Secp256k1) -> (RecoveryId, [u8; 64]) { - let mut ret = [0u8; 64]; - let mut recid = 0i32; - unsafe { - let err = - ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(secp.ctx, - ret.as_mut_ptr(), - &mut recid, - self.as_ptr()); - assert!(err == 1); - } - (RecoveryId(recid), ret) - } + #[inline] + /// Serializes the recoverable signature in compact format + pub fn serialize_compact(&self, secp: &Secp256k1) -> (RecoveryId, [u8; 64]) { + let mut ret = [0u8; 64]; + let mut recid = 0i32; + unsafe { + let err = + ffi::secp256k1_ecdsa_recoverable_signature_serialize_compact(secp.ctx, + ret.as_mut_ptr(), + &mut recid, + self.as_ptr()); + assert!(err == 1); + } + (RecoveryId(recid), ret) + } - /// Converts a recoverable signature to a non-recoverable one (this is needed - /// for verification - #[inline] - pub fn to_standard(&self, secp: &Secp256k1) -> Signature { - let mut ret = unsafe { ffi::Signature::blank() }; - unsafe { - let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(secp.ctx, - &mut ret, - self.as_ptr()); - assert!(err == 1); - } - Signature(ret) - } + /// Converts a recoverable signature to a non-recoverable one (this is + /// needed + /// for verification + #[inline] + pub fn to_standard(&self, secp: &Secp256k1) -> Signature { + let mut ret = unsafe { ffi::Signature::blank() }; + unsafe { + let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(secp.ctx, + &mut ret, + self.as_ptr()); + assert!(err == 1); + } + Signature(ret) + } } /// Creates a new recoverable signature from a FFI one impl From for RecoverableSignature { - #[inline] - fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { - RecoverableSignature(sig) - } + #[inline] + fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { + RecoverableSignature(sig) + } } impl ops::Index for Signature { - type Output = u8; + type Output = u8; - #[inline] - fn index(&self, index: usize) -> &u8 { - &self.0[index] - } + #[inline] + fn index(&self, index: usize) -> &u8 { + &self.0[index] + } } impl ops::Index> for Signature { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] - } + #[inline] + fn index(&self, index: ops::Range) -> &[u8] { + &self.0[index] + } } impl ops::Index> for Signature { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[u8] { - &self.0[index.start..] - } + #[inline] + fn index(&self, index: ops::RangeFrom) -> &[u8] { + &self.0[index.start..] + } } impl ops::Index for Signature { - type Output = [u8]; + type Output = [u8]; - #[inline] - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.0[..] - } + #[inline] + fn index(&self, _: ops::RangeFull) -> &[u8] { + &self.0[..] + } } /// A (hashed) message input to an ECDSA signature @@ -309,77 +311,77 @@ impl_array_newtype!(Message, u8, constants::MESSAGE_SIZE); impl_pretty_debug!(Message); impl Message { - /// Converts a `MESSAGE_SIZE`-byte slice to a message object - #[inline] - pub fn from_slice(data: &[u8]) -> Result { - match data.len() { - constants::MESSAGE_SIZE => { - let mut ret = [0; constants::MESSAGE_SIZE]; - unsafe { - ptr::copy_nonoverlapping(data.as_ptr(), ret.as_mut_ptr(), data.len()); - } - Ok(Message(ret)) - } - _ => Err(Error::InvalidMessage), - } - } + /// Converts a `MESSAGE_SIZE`-byte slice to a message object + #[inline] + pub fn from_slice(data: &[u8]) -> Result { + match data.len() { + constants::MESSAGE_SIZE => { + let mut ret = [0; constants::MESSAGE_SIZE]; + unsafe { + ptr::copy_nonoverlapping(data.as_ptr(), ret.as_mut_ptr(), data.len()); + } + Ok(Message(ret)) + } + _ => Err(Error::InvalidMessage), + } + } } /// An ECDSA error #[derive(Copy, PartialEq, Eq, Clone, Debug)] pub enum Error { - /// A `Secp256k1` was used for an operation, but it was not created to - /// support this (so necessary precomputations have not been done) - IncapableContext, - /// Signature failed verification - IncorrectSignature, - /// Badly sized message - InvalidMessage, - /// Bad public key - InvalidPublicKey, - /// Bad signature - InvalidSignature, - /// Bad secret key - InvalidSecretKey, - /// Bad recovery id - InvalidRecoveryId, - /// Summing commitments led to incorrect result - IncorrectCommitSum, - /// Range proof is invalid - InvalidRangeProof, + /// A `Secp256k1` was used for an operation, but it was not created to + /// support this (so necessary precomputations have not been done) + IncapableContext, + /// Signature failed verification + IncorrectSignature, + /// Badly sized message + InvalidMessage, + /// Bad public key + InvalidPublicKey, + /// Bad signature + InvalidSignature, + /// Bad secret key + InvalidSecretKey, + /// Bad recovery id + InvalidRecoveryId, + /// Summing commitments led to incorrect result + IncorrectCommitSum, + /// Range proof is invalid + InvalidRangeProof, } // Passthrough Debug to Display, since errors should be user-visible impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - f.write_str(error::Error::description(self)) - } + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.write_str(error::Error::description(self)) + } } impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { - None - } + fn cause(&self) -> Option<&error::Error> { + None + } - fn description(&self) -> &str { - match *self { - Error::IncapableContext => "secp: context does not have sufficient capabilities", - Error::IncorrectSignature => "secp: signature failed verification", - Error::InvalidMessage => "secp: message was not 32 bytes (do you need to hash?)", - Error::InvalidPublicKey => "secp: malformed public key", - Error::InvalidSignature => "secp: malformed signature", - Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", - Error::InvalidRecoveryId => "secp: bad recovery id", - Error::IncorrectCommitSum => "secp: invalid pedersen commitment sum", - Error::InvalidRangeProof => "secp: invalid range proof", - } - } + fn description(&self) -> &str { + match *self { + Error::IncapableContext => "secp: context does not have sufficient capabilities", + Error::IncorrectSignature => "secp: signature failed verification", + Error::InvalidMessage => "secp: message was not 32 bytes (do you need to hash?)", + Error::InvalidPublicKey => "secp: malformed public key", + Error::InvalidSignature => "secp: malformed signature", + Error::InvalidSecretKey => "secp: malformed or out-of-range secret key", + Error::InvalidRecoveryId => "secp: bad recovery id", + Error::IncorrectCommitSum => "secp: invalid pedersen commitment sum", + Error::InvalidRangeProof => "secp: invalid range proof", + } + } } /// The secp256k1 engine, used to execute all signature operations pub struct Secp256k1 { - ctx: *mut ffi::Context, - caps: ContextFlag, + ctx: *mut ffi::Context, + caps: ContextFlag, } unsafe impl Send for Secp256k1 {} @@ -389,309 +391,315 @@ unsafe impl Sync for Secp256k1 {} /// the more capabilities, the more expensive it is to create. #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum ContextFlag { - /// Can neither sign nor verify signatures (cheapest to create, useful - /// for cases not involving signatures, such as creating keys from slices) - None, - /// Can sign but not verify signatures - SignOnly, - /// Can verify but not create signatures - VerifyOnly, - /// Can verify and create signatures - Full, - /// Can do all of the above plus pedersen commitments - Commit, + /// Can neither sign nor verify signatures (cheapest to create, useful + /// for cases not involving signatures, such as creating keys from slices) + None, + /// Can sign but not verify signatures + SignOnly, + /// Can verify but not create signatures + VerifyOnly, + /// Can verify and create signatures + Full, + /// Can do all of the above plus pedersen commitments + Commit, } // Passthrough Debug to Display, since caps should be user-visible impl fmt::Display for ContextFlag { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt::Debug::fmt(self, f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fmt::Debug::fmt(self, f) + } } impl Clone for Secp256k1 { - fn clone(&self) -> Secp256k1 { - Secp256k1 { - ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) }, - caps: self.caps, - } - } + fn clone(&self) -> Secp256k1 { + Secp256k1 { + ctx: unsafe { ffi::secp256k1_context_clone(self.ctx) }, + caps: self.caps, + } + } } impl PartialEq for Secp256k1 { - fn eq(&self, other: &Secp256k1) -> bool { - self.caps == other.caps - } + fn eq(&self, other: &Secp256k1) -> bool { + self.caps == other.caps + } } impl Eq for Secp256k1 {} impl fmt::Debug for Secp256k1 { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "Secp256k1 {{ [private], caps: {:?} }}", self.caps) - } + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "Secp256k1 {{ [private], caps: {:?} }}", self.caps) + } } impl Drop for Secp256k1 { - fn drop(&mut self) { - unsafe { - ffi::secp256k1_context_destroy(self.ctx); - } - } + fn drop(&mut self) { + unsafe { + ffi::secp256k1_context_destroy(self.ctx); + } + } } impl Secp256k1 { - /// Creates a new Secp256k1 context - #[inline] - pub fn new() -> Secp256k1 { - Secp256k1::with_caps(ContextFlag::Full) - } + /// Creates a new Secp256k1 context + #[inline] + pub fn new() -> Secp256k1 { + Secp256k1::with_caps(ContextFlag::Full) + } - /// Creates a new Secp256k1 context with the specified capabilities - pub fn with_caps(caps: ContextFlag) -> Secp256k1 { - let flag = match caps { - ContextFlag::None => ffi::SECP256K1_START_NONE, - ContextFlag::SignOnly => ffi::SECP256K1_START_SIGN, - ContextFlag::VerifyOnly => ffi::SECP256K1_START_VERIFY, - ContextFlag::Full | ContextFlag::Commit => { - ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY - } - }; - let ctx = unsafe { ffi::secp256k1_context_create(flag) }; - if caps == ContextFlag::Commit { - unsafe { - ffi::secp256k1_pedersen_context_initialize(ctx); - ffi::secp256k1_rangeproof_context_initialize(ctx); - } - } - Secp256k1 { - ctx: ctx, - caps: caps, - } - } + /// Creates a new Secp256k1 context with the specified capabilities + pub fn with_caps(caps: ContextFlag) -> Secp256k1 { + let flag = match caps { + ContextFlag::None => ffi::SECP256K1_START_NONE, + ContextFlag::SignOnly => ffi::SECP256K1_START_SIGN, + ContextFlag::VerifyOnly => ffi::SECP256K1_START_VERIFY, + ContextFlag::Full | ContextFlag::Commit => { + ffi::SECP256K1_START_SIGN | ffi::SECP256K1_START_VERIFY + } + }; + let ctx = unsafe { ffi::secp256k1_context_create(flag) }; + if caps == ContextFlag::Commit { + unsafe { + ffi::secp256k1_pedersen_context_initialize(ctx); + ffi::secp256k1_rangeproof_context_initialize(ctx); + } + } + Secp256k1 { + ctx: ctx, + caps: caps, + } + } - /// Creates a new Secp256k1 context with no capabilities (just de/serialization) - pub fn without_caps() -> Secp256k1 { - Secp256k1::with_caps(ContextFlag::None) - } + /// Creates a new Secp256k1 context with no capabilities (just + /// de/serialization) + pub fn without_caps() -> Secp256k1 { + Secp256k1::with_caps(ContextFlag::None) + } - /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistence; - /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell - pub fn randomize(&mut self, rng: &mut R) { - let mut seed = [0; 32]; - rng.fill_bytes(&mut seed); - unsafe { - let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_ptr()); - // This function cannot fail; it has an error return for future-proofing. - // We do not expose this error since it is impossible to hit, and we have - // precedent for not exposing impossible errors (for example in - // `PublicKey::from_secret_key` where it is impossble to create an invalid - // secret key through the API.) - // However, if this DOES fail, the result is potentially weaker side-channel - // resistance, which is deadly and undetectable, so we take out the entire - // thread to be on the safe side. - assert!(err == 1); - } - } + /// (Re)randomizes the Secp256k1 context for cheap sidechannel resistence; + /// see comment in libsecp256k1 commit d2275795f by Gregory Maxwell + pub fn randomize(&mut self, rng: &mut R) { + let mut seed = [0; 32]; + rng.fill_bytes(&mut seed); + unsafe { + let err = ffi::secp256k1_context_randomize(self.ctx, seed.as_ptr()); + // This function cannot fail; it has an error return for future-proofing. + // We do not expose this error since it is impossible to hit, and we have + // precedent for not exposing impossible errors (for example in + // `PublicKey::from_secret_key` where it is impossble to create an invalid + // secret key through the API.) + // However, if this DOES fail, the result is potentially weaker side-channel + // resistance, which is deadly and undetectable, so we take out the entire + // thread to be on the safe side. + assert!(err == 1); + } + } - /// Generates a random keypair. Convenience function for `key::SecretKey::new` - /// and `key::PublicKey::from_secret_key`; call those functions directly for - /// batch key generation. Requires a signing-capable context. - #[inline] - pub fn generate_keypair(&self, - rng: &mut R) - -> Result<(key::SecretKey, key::PublicKey), Error> { - let sk = key::SecretKey::new(self, rng); - let pk = try!(key::PublicKey::from_secret_key(self, &sk)); - Ok((sk, pk)) - } + /// Generates a random keypair. Convenience function for + /// `key::SecretKey::new` + /// and `key::PublicKey::from_secret_key`; call those functions directly for + /// batch key generation. Requires a signing-capable context. + #[inline] + pub fn generate_keypair(&self, + rng: &mut R) + -> Result<(key::SecretKey, key::PublicKey), Error> { + let sk = key::SecretKey::new(self, rng); + let pk = try!(key::PublicKey::from_secret_key(self, &sk)); + Ok((sk, pk)) + } - /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce - /// Requires a signing-capable context. - pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 + /// nonce + /// Requires a signing-capable context. + pub fn sign(&self, msg: &Message, sk: &key::SecretKey) -> Result { + if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - let mut ret = unsafe { ffi::Signature::blank() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid signature from a valid `Message` and `SecretKey` - assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, + let mut ret = unsafe { ffi::Signature::blank() }; + unsafe { + // We can assume the return value because it's not possible to construct + // an invalid signature from a valid `Message` and `SecretKey` + assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_ptr(), sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, ptr::null()), 1); - } - Ok(Signature::from(ret)) - } + } + Ok(Signature::from(ret)) + } - /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce - /// Requires a signing-capable context. - pub fn sign_recoverable(&self, - msg: &Message, - sk: &key::SecretKey) - -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 + /// nonce + /// Requires a signing-capable context. + pub fn sign_recoverable(&self, + msg: &Message, + sk: &key::SecretKey) + -> Result { + if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - let mut ret = unsafe { ffi::RecoverableSignature::blank() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid signature from a valid `Message` and `SecretKey` - assert_eq!(ffi::secp256k1_ecdsa_sign_recoverable(self.ctx, &mut ret, msg.as_ptr(), + let mut ret = unsafe { ffi::RecoverableSignature::blank() }; + unsafe { + // We can assume the return value because it's not possible to construct + // an invalid signature from a valid `Message` and `SecretKey` + assert_eq!(ffi::secp256k1_ecdsa_sign_recoverable(self.ctx, &mut ret, msg.as_ptr(), sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979, ptr::null()), 1); - } - Ok(RecoverableSignature::from(ret)) - } + } + Ok(RecoverableSignature::from(ret)) + } - /// Determines the public key for which `sig` is a valid signature for - /// `msg`. Requires a verify-capable context. - pub fn recover(&self, - msg: &Message, - sig: &RecoverableSignature) - -> Result { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Determines the public key for which `sig` is a valid signature for + /// `msg`. Requires a verify-capable context. + pub fn recover(&self, + msg: &Message, + sig: &RecoverableSignature) + -> Result { + if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - let mut pk = unsafe { ffi::PublicKey::blank() }; + let mut pk = unsafe { ffi::PublicKey::blank() }; - unsafe { - if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 { - return Err(Error::InvalidSignature); - } - }; - Ok(key::PublicKey::from(pk)) - } + unsafe { + if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 { + return Err(Error::InvalidSignature); + } + }; + Ok(key::PublicKey::from(pk)) + } - /// Checks that `sig` is a valid ECDSA signature for `msg` using the public - /// key `pubkey`. Returns `Ok(true)` on success. Note that this function cannot - /// be used for Bitcoin consensus checking since there may exist signatures - /// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a - /// verify-capable context. - #[inline] - pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Checks that `sig` is a valid ECDSA signature for `msg` using the public + /// key `pubkey`. Returns `Ok(true)` on success. Note that this function + /// cannot + /// be used for Bitcoin consensus checking since there may exist signatures + /// which OpenSSL would verify but not libsecp256k1, or vice-versa. + /// Requires a + /// verify-capable context. + #[inline] + pub fn verify(&self, msg: &Message, sig: &Signature, pk: &key::PublicKey) -> Result<(), Error> { + if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - if !pk.is_valid() { - Err(Error::InvalidPublicKey) - } else if unsafe { - ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr()) - } == 0 { - Err(Error::IncorrectSignature) - } else { - Ok(()) - } - } + if !pk.is_valid() { + Err(Error::InvalidPublicKey) + } else if unsafe { + ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr()) + } == 0 { + Err(Error::IncorrectSignature) + } else { + Ok(()) + } + } } #[cfg(test)] mod tests { - use rand::{Rng, thread_rng}; - use std::ptr; - use serialize::hex::FromHex; + use rand::{Rng, thread_rng}; + use std::ptr; + use serialize::hex::FromHex; - use key::{SecretKey, PublicKey}; - use super::constants; - use super::{Secp256k1, Signature, RecoverableSignature, Message, RecoveryId, ContextFlag}; - use super::Error::{InvalidMessage, InvalidPublicKey, IncorrectSignature, InvalidSignature, - IncapableContext}; + use key::{SecretKey, PublicKey}; + use super::constants; + use super::{Secp256k1, Signature, RecoverableSignature, Message, RecoveryId, ContextFlag}; + use super::Error::{InvalidMessage, InvalidPublicKey, IncorrectSignature, InvalidSignature, + IncapableContext}; - macro_rules! hex (($hex:expr) => ($hex.from_hex().unwrap())); + macro_rules! hex (($hex:expr) => ($hex.from_hex().unwrap())); - #[test] - fn capabilities() { - let none = Secp256k1::with_caps(ContextFlag::None); - let sign = Secp256k1::with_caps(ContextFlag::SignOnly); - let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); - let full = Secp256k1::with_caps(ContextFlag::Full); + #[test] + fn capabilities() { + let none = Secp256k1::with_caps(ContextFlag::None); + let sign = Secp256k1::with_caps(ContextFlag::SignOnly); + let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); + let full = Secp256k1::with_caps(ContextFlag::Full); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - // Try key generation - assert_eq!(none.generate_keypair(&mut thread_rng()), Err(IncapableContext)); - assert_eq!(vrfy.generate_keypair(&mut thread_rng()), Err(IncapableContext)); - assert!(sign.generate_keypair(&mut thread_rng()).is_ok()); - assert!(full.generate_keypair(&mut thread_rng()).is_ok()); - let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); + // Try key generation + assert_eq!(none.generate_keypair(&mut thread_rng()), Err(IncapableContext)); + assert_eq!(vrfy.generate_keypair(&mut thread_rng()), Err(IncapableContext)); + assert!(sign.generate_keypair(&mut thread_rng()).is_ok()); + assert!(full.generate_keypair(&mut thread_rng()).is_ok()); + let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); - // Try signing - assert_eq!(none.sign(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign(&msg, &sk).is_ok()); - assert!(full.sign(&msg, &sk).is_ok()); - assert_eq!(none.sign_recoverable(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign_recoverable(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign_recoverable(&msg, &sk).is_ok()); - assert!(full.sign_recoverable(&msg, &sk).is_ok()); - assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); - assert_eq!(sign.sign_recoverable(&msg, &sk), full.sign_recoverable(&msg, &sk)); - let sig = full.sign(&msg, &sk).unwrap(); - let sigr = full.sign_recoverable(&msg, &sk).unwrap(); + // Try signing + assert_eq!(none.sign(&msg, &sk), Err(IncapableContext)); + assert_eq!(vrfy.sign(&msg, &sk), Err(IncapableContext)); + assert!(sign.sign(&msg, &sk).is_ok()); + assert!(full.sign(&msg, &sk).is_ok()); + assert_eq!(none.sign_recoverable(&msg, &sk), Err(IncapableContext)); + assert_eq!(vrfy.sign_recoverable(&msg, &sk), Err(IncapableContext)); + assert!(sign.sign_recoverable(&msg, &sk).is_ok()); + assert!(full.sign_recoverable(&msg, &sk).is_ok()); + assert_eq!(sign.sign(&msg, &sk), full.sign(&msg, &sk)); + assert_eq!(sign.sign_recoverable(&msg, &sk), full.sign_recoverable(&msg, &sk)); + let sig = full.sign(&msg, &sk).unwrap(); + let sigr = full.sign_recoverable(&msg, &sk).unwrap(); - // Try verifying - assert_eq!(none.verify(&msg, &sig, &pk), Err(IncapableContext)); - assert_eq!(sign.verify(&msg, &sig, &pk), Err(IncapableContext)); - assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); - assert!(full.verify(&msg, &sig, &pk).is_ok()); + // Try verifying + assert_eq!(none.verify(&msg, &sig, &pk), Err(IncapableContext)); + assert_eq!(sign.verify(&msg, &sig, &pk), Err(IncapableContext)); + assert!(vrfy.verify(&msg, &sig, &pk).is_ok()); + assert!(full.verify(&msg, &sig, &pk).is_ok()); - // Try pk recovery - assert_eq!(none.recover(&msg, &sigr), Err(IncapableContext)); - assert_eq!(sign.recover(&msg, &sigr), Err(IncapableContext)); - assert!(vrfy.recover(&msg, &sigr).is_ok()); - assert!(full.recover(&msg, &sigr).is_ok()); + // Try pk recovery + assert_eq!(none.recover(&msg, &sigr), Err(IncapableContext)); + assert_eq!(sign.recover(&msg, &sigr), Err(IncapableContext)); + assert!(vrfy.recover(&msg, &sigr).is_ok()); + assert!(full.recover(&msg, &sigr).is_ok()); - assert_eq!(vrfy.recover(&msg, &sigr), + assert_eq!(vrfy.recover(&msg, &sigr), full.recover(&msg, &sigr)); - assert_eq!(full.recover(&msg, &sigr), Ok(pk)); + 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 new_pk = PublicKey::from_slice(&none, pk_slice).unwrap(); - let new_sk = SecretKey::from_slice(&none, sk_slice).unwrap(); - assert_eq!(sk, new_sk); - assert_eq!(pk, new_pk); - } + // Check that we can produce keys from slices with no precomputation + let (pk_slice, sk_slice) = (&pk.serialize_vec(&none, true), &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); + assert_eq!(pk, new_pk); + } - #[test] - fn recid_sanity_check() { - let one = RecoveryId(1); - assert_eq!(one, one.clone()); - } + #[test] + fn recid_sanity_check() { + let one = RecoveryId(1); + assert_eq!(one, one.clone()); + } - #[test] - fn invalid_pubkey() { - let s = Secp256k1::new(); - let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); - let pk = PublicKey::new(); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + #[test] + fn invalid_pubkey() { + let s = Secp256k1::new(); + let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); + let pk = PublicKey::new(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - assert_eq!(s.verify(&msg, &sig.to_standard(&s), &pk), Err(InvalidPublicKey)); - } + assert_eq!(s.verify(&msg, &sig.to_standard(&s), &pk), Err(InvalidPublicKey)); + } - #[test] - fn sign() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); - 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]; + #[test] + fn sign() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); + 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]; - let sk = SecretKey::from_slice(&s, &one).unwrap(); - let msg = Message::from_slice(&one).unwrap(); + let sk = SecretKey::from_slice(&s, &one).unwrap(); + let msg = Message::from_slice(&one).unwrap(); - let sig = s.sign_recoverable(&msg, &sk).unwrap(); - assert_eq!(Ok(sig), RecoverableSignature::from_compact(&s, &[ + let sig = s.sign_recoverable(&msg, &sk).unwrap(); + assert_eq!(Ok(sig), RecoverableSignature::from_compact(&s, &[ 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, @@ -701,29 +709,29 @@ mod tests { 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], RecoveryId(1))) - } + } - #[test] - fn signature_der_roundtrip() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn signature_der_roundtrip() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0; 32]; - for _ in 0..100 { - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0; 32]; + for _ in 0..100 { + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig1 = s.sign(&msg, &sk).unwrap(); - let der = sig1.serialize_der(&s); - let sig2 = Signature::from_der(&s, &der[..]).unwrap(); - assert_eq!(sig1, sig2); - } - } + let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); + let sig1 = s.sign(&msg, &sk).unwrap(); + let der = sig1.serialize_der(&s); + let sig2 = Signature::from_der(&s, &der[..]).unwrap(); + assert_eq!(sig1, sig2); + } + } - #[test] - fn signature_lax_der() { - macro_rules! check_lax_sig( + #[test] + fn signature_lax_der() { + macro_rules! check_lax_sig( ($hex:expr) => ({ let secp = Secp256k1::without_caps(); let sig = hex!($hex); @@ -731,278 +739,278 @@ mod tests { }) ); - check_lax_sig!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c"); - check_lax_sig!("304402202ea9d51c7173b1d96d331bd41b3d1b4e78e66148e64ed5992abd6ca66290321c0220628c47517e049b3e41509e9d71e480a0cdc766f8cdec265ef0017711c1b5336f"); - check_lax_sig!("3045022100bf8e050c85ffa1c313108ad8c482c4849027937916374617af3f2e9a881861c9022023f65814222cab09d5ec41032ce9c72ca96a5676020736614de7b78a4e55325a"); - check_lax_sig!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); - check_lax_sig!("3046022100eaa5f90483eb20224616775891397d47efa64c68b969db1dacb1c30acdfc50aa022100cf9903bbefb1c8000cf482b0aeeb5af19287af20bd794de11d82716f9bae3db1"); - check_lax_sig!("3045022047d512bc85842ac463ca3b669b62666ab8672ee60725b6c06759e476cebdc6c102210083805e93bd941770109bcc797784a71db9e48913f702c56e60b1c3e2ff379a60"); - check_lax_sig!("3044022023ee4e95151b2fbbb08a72f35babe02830d14d54bd7ed1320e4751751d1baa4802206235245254f58fd1be6ff19ca291817da76da65c2f6d81d654b5185dd86b8acf"); - } + check_lax_sig!("304402204c2dd8a9b6f8d425fcd8ee9a20ac73b619906a6367eac6cb93e70375225ec0160220356878eff111ff3663d7e6bf08947f94443845e0dcc54961664d922f7660b80c"); + check_lax_sig!("304402202ea9d51c7173b1d96d331bd41b3d1b4e78e66148e64ed5992abd6ca66290321c0220628c47517e049b3e41509e9d71e480a0cdc766f8cdec265ef0017711c1b5336f"); + check_lax_sig!("3045022100bf8e050c85ffa1c313108ad8c482c4849027937916374617af3f2e9a881861c9022023f65814222cab09d5ec41032ce9c72ca96a5676020736614de7b78a4e55325a"); + check_lax_sig!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); + check_lax_sig!("3046022100eaa5f90483eb20224616775891397d47efa64c68b969db1dacb1c30acdfc50aa022100cf9903bbefb1c8000cf482b0aeeb5af19287af20bd794de11d82716f9bae3db1"); + check_lax_sig!("3045022047d512bc85842ac463ca3b669b62666ab8672ee60725b6c06759e476cebdc6c102210083805e93bd941770109bcc797784a71db9e48913f702c56e60b1c3e2ff379a60"); + check_lax_sig!("3044022023ee4e95151b2fbbb08a72f35babe02830d14d54bd7ed1320e4751751d1baa4802206235245254f58fd1be6ff19ca291817da76da65c2f6d81d654b5185dd86b8acf"); + } - #[test] - fn sign_and_verify() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn sign_and_verify() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0; 32]; - for _ in 0..100 { - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + 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(&mut thread_rng()).unwrap(); - let sig = s.sign(&msg, &sk).unwrap(); - assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); - } - } + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let sig = s.sign(&msg, &sk).unwrap(); + assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); + } + } - #[test] - fn sign_and_verify_extreme() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn sign_and_verify_extreme() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - // Wild keys: 1, CURVE_ORDER - 1 - // Wild msgs: 0, 1, CURVE_ORDER - 1, CURVE_ORDER - let mut wild_keys = [[0; 32]; 2]; - let mut wild_msgs = [[0; 32]; 4]; + // Wild keys: 1, CURVE_ORDER - 1 + // Wild msgs: 0, 1, CURVE_ORDER - 1, CURVE_ORDER + let mut wild_keys = [[0; 32]; 2]; + let mut wild_msgs = [[0; 32]; 4]; - wild_keys[0][0] = 1; - wild_msgs[1][0] = 1; - unsafe { - use constants; - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_keys[1].as_mut_ptr(), - 32); - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_msgs[1].as_mut_ptr(), - 32); - ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), - wild_msgs[2].as_mut_ptr(), - 32); - wild_keys[1][0] -= 1; - wild_msgs[1][0] -= 1; - } + wild_keys[0][0] = 1; + wild_msgs[1][0] = 1; + unsafe { + use constants; + ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), + wild_keys[1].as_mut_ptr(), + 32); + ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), + wild_msgs[1].as_mut_ptr(), + 32); + ptr::copy_nonoverlapping(constants::CURVE_ORDER.as_ptr(), + wild_msgs[2].as_mut_ptr(), + 32); + wild_keys[1][0] -= 1; + wild_msgs[1][0] -= 1; + } - for key in wild_keys.iter().map(|k| SecretKey::from_slice(&s, &k[..]).unwrap()) { - for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) { - let sig = s.sign(&msg, &key).unwrap(); - let pk = PublicKey::from_secret_key(&s, &key).unwrap(); - assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); - } - } - } + for key in wild_keys.iter().map(|k| SecretKey::from_slice(&s, &k[..]).unwrap()) { + for msg in wild_msgs.iter().map(|m| Message::from_slice(&m[..]).unwrap()) { + let sig = s.sign(&msg, &key).unwrap(); + let pk = PublicKey::from_secret_key(&s, &key).unwrap(); + assert_eq!(s.verify(&msg, &sig, &pk), Ok(())); + } + } + } - #[test] - fn sign_and_verify_fail() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn sign_and_verify_fail() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sigr = s.sign_recoverable(&msg, &sk).unwrap(); - let sig = sigr.to_standard(&s); + let sigr = s.sign_recoverable(&msg, &sk).unwrap(); + let sig = sigr.to_standard(&s); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - assert_eq!(s.verify(&msg, &sig, &pk), Err(IncorrectSignature)); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + assert_eq!(s.verify(&msg, &sig, &pk), Err(IncorrectSignature)); - let recovered_key = s.recover(&msg, &sigr).unwrap(); - assert!(recovered_key != pk); - } + let recovered_key = s.recover(&msg, &sigr).unwrap(); + assert!(recovered_key != pk); + } - #[test] - fn sign_with_recovery() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn sign_with_recovery() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign_recoverable(&msg, &sk).unwrap(); + let sig = s.sign_recoverable(&msg, &sk).unwrap(); - assert_eq!(s.recover(&msg, &sig), Ok(pk)); - } + assert_eq!(s.recover(&msg, &sig), Ok(pk)); + } - #[test] - fn bad_recovery() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn bad_recovery() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let msg = Message::from_slice(&[0x55; 32]).unwrap(); + let msg = Message::from_slice(&[0x55; 32]).unwrap(); - // Zero is not a valid sig - let sig = RecoverableSignature::from_compact(&s, &[0; 64], RecoveryId(0)).unwrap(); - assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature)); - // ...but 111..111 is - let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); - assert!(s.recover(&msg, &sig).is_ok()); - } + // Zero is not a valid sig + let sig = RecoverableSignature::from_compact(&s, &[0; 64], RecoveryId(0)).unwrap(); + assert_eq!(s.recover(&msg, &sig), Err(InvalidSignature)); + // ...but 111..111 is + let sig = RecoverableSignature::from_compact(&s, &[1; 64], RecoveryId(0)).unwrap(); + assert!(s.recover(&msg, &sig).is_ok()); + } - #[test] - fn test_bad_slice() { - let s = Secp256k1::new(); - assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE + 1]), + #[test] + fn test_bad_slice() { + let s = Secp256k1::new(); + assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE + 1]), Err(InvalidSignature)); - assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE]), + assert_eq!(Signature::from_der(&s, &[0; constants::MAX_SIGNATURE_SIZE]), Err(InvalidSignature)); - assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]), + assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]), Err(InvalidMessage)); - assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]), + assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]), Err(InvalidMessage)); - assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok()); - } + assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok()); + } - #[test] - fn test_debug_output() { - let s = Secp256k1::new(); - let sig = - RecoverableSignature::from_compact(&s, - &[0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, - 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, - 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, - 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, - 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, - 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, - 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, - 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], - RecoveryId(1)) - .unwrap(); - assert_eq!(&format!("{:?}", sig), "RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)"); + #[test] + fn test_debug_output() { + let s = Secp256k1::new(); + let sig = + RecoverableSignature::from_compact(&s, + &[0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, + 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, + 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, + 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, + 0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8, + 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, + 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, + 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89], + RecoveryId(1)) + .unwrap(); + assert_eq!(&format!("{:?}", sig), "RecoverableSignature(98882e09f4ed6dc3659e43fc771e0cafa60b1f926f2b77041f744721adff7366898cb609d0ee128d06ae9aa3c48020ff9f705e02f80e1280a8ade05216971a4c01)"); - let msg = Message([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 255]); - assert_eq!(&format!("{:?}", msg), "Message(0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fff)"); - } + let msg = Message([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 255]); + assert_eq!(&format!("{:?}", msg), "Message(0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1fff)"); + } - #[test] - fn test_recov_sig_serialize_compact() { - let s = Secp256k1::new(); + #[test] + fn test_recov_sig_serialize_compact() { + let s = Secp256k1::new(); - let recid_in = RecoveryId(1); - let bytes_in = &[0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x04, 0x77, 0x2b, 0x6f, - 0x92, 0x1f, 0x0b, 0xa6, 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, - 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 0x4c, 0x1a, 0x97, 0x16, - 0x52, 0xe0, 0xad, 0xa8, 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, - 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0x8d, 0x12, 0xee, 0xd0, - 0x09, 0xb6, 0x8c, 0x89]; - let sig = RecoverableSignature::from_compact(&s, bytes_in, recid_in).unwrap(); - let (recid_out, bytes_out) = sig.serialize_compact(&s); - assert_eq!(recid_in, recid_out); - assert_eq!(&bytes_in[..], &bytes_out[..]); - } + let recid_in = RecoveryId(1); + let bytes_in = &[0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x04, 0x77, 0x2b, 0x6f, + 0x92, 0x1f, 0x0b, 0xa6, 0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65, + 0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98, 0x4c, 0x1a, 0x97, 0x16, + 0x52, 0xe0, 0xad, 0xa8, 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, + 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0x8d, 0x12, 0xee, 0xd0, + 0x09, 0xb6, 0x8c, 0x89]; + let sig = RecoverableSignature::from_compact(&s, bytes_in, recid_in).unwrap(); + let (recid_out, bytes_out) = sig.serialize_compact(&s); + assert_eq!(recid_in, recid_out); + assert_eq!(&bytes_in[..], &bytes_out[..]); + } - #[test] - fn test_recov_id_conversion_between_i32() { - assert!(RecoveryId::from_i32(-1).is_err()); - assert!(RecoveryId::from_i32(0).is_ok()); - assert!(RecoveryId::from_i32(1).is_ok()); - assert!(RecoveryId::from_i32(2).is_ok()); - assert!(RecoveryId::from_i32(3).is_ok()); - assert!(RecoveryId::from_i32(4).is_err()); - let id0 = RecoveryId::from_i32(0).unwrap(); - assert_eq!(id0.to_i32(), 0); - let id1 = RecoveryId(1); - assert_eq!(id1.to_i32(), 1); - } + #[test] + fn test_recov_id_conversion_between_i32() { + assert!(RecoveryId::from_i32(-1).is_err()); + assert!(RecoveryId::from_i32(0).is_ok()); + assert!(RecoveryId::from_i32(1).is_ok()); + assert!(RecoveryId::from_i32(2).is_ok()); + assert!(RecoveryId::from_i32(3).is_ok()); + assert!(RecoveryId::from_i32(4).is_err()); + let id0 = RecoveryId::from_i32(0).unwrap(); + assert_eq!(id0.to_i32(), 0); + let id1 = RecoveryId(1); + assert_eq!(id1.to_i32(), 1); + } - #[test] - fn test_low_s() { - // nb this is a transaction on testnet - // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 - // input number 3 - let sig = hex!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); - let pk = hex!("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43"); - let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); + #[test] + fn test_low_s() { + // nb this is a transaction on testnet + // txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9 + // input number 3 + let sig = hex!("3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"); + let pk = hex!("031ee99d2b786ab3b0991325f2de8489246a6a3fdb700f6d0511b1d80cf5f4cd43"); + let msg = hex!("a4965ca63b7d8562736ceec36dfa5a11bf426eb65be8ea3f7a49ae363032da0d"); - let secp = Secp256k1::new(); - let mut sig = Signature::from_der(&secp, &sig[..]).unwrap(); - let pk = PublicKey::from_slice(&secp, &pk[..]).unwrap(); - let msg = Message::from_slice(&msg[..]).unwrap(); + let secp = Secp256k1::new(); + let mut sig = Signature::from_der(&secp, &sig[..]).unwrap(); + let pk = PublicKey::from_slice(&secp, &pk[..]).unwrap(); + let msg = Message::from_slice(&msg[..]).unwrap(); - // without normalization we expect this will fail - assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature)); - // after normalization it should pass - sig.normalize_s(&secp); - assert_eq!(secp.verify(&msg, &sig, &pk), Ok(())); - } + // without normalization we expect this will fail + assert_eq!(secp.verify(&msg, &sig, &pk), Err(IncorrectSignature)); + // after normalization it should pass + sig.normalize_s(&secp); + assert_eq!(secp.verify(&msg, &sig, &pk), Ok(())); + } } #[cfg(all(test, feature = "unstable"))] mod benches { - use rand::{Rng, thread_rng}; - use test::{Bencher, black_box}; + use rand::{Rng, thread_rng}; + use test::{Bencher, black_box}; - use super::{Secp256k1, Message}; + use super::{Secp256k1, Message}; - #[bench] - pub fn generate(bh: &mut Bencher) { - struct CounterRng(u32); - impl Rng for CounterRng { - fn next_u32(&mut self) -> u32 { - self.0 += 1; - self.0 - } - } + #[bench] + pub fn generate(bh: &mut Bencher) { + 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(&mut r).unwrap(); - black_box(sk); - black_box(pk); - }); - } + let s = Secp256k1::new(); + let mut r = CounterRng(0); + bh.iter(|| { + let (sk, pk) = s.generate_keypair(&mut r).unwrap(); + black_box(sk); + black_box(pk); + }); + } - #[bench] - pub fn bench_sign(bh: &mut Bencher) { - let s = Secp256k1::new(); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); + #[bench] + pub fn bench_sign(bh: &mut Bencher) { + let s = Secp256k1::new(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - bh.iter(|| { - let sig = s.sign(&msg, &sk).unwrap(); - black_box(sig); - }); - } + bh.iter(|| { + let sig = s.sign(&msg, &sk).unwrap(); + black_box(sig); + }); + } - #[bench] - pub fn bench_verify(bh: &mut Bencher) { - 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(&mut thread_rng()).unwrap(); - let sig = s.sign(&msg, &sk).unwrap(); + #[bench] + pub fn bench_verify(bh: &mut Bencher) { + 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(&mut thread_rng()).unwrap(); + let sig = s.sign(&msg, &sk).unwrap(); - bh.iter(|| { - let res = s.verify(&msg, &sig, &pk).unwrap(); - black_box(res); - }); - } + bh.iter(|| { + let res = s.verify(&msg, &sig, &pk).unwrap(); + black_box(res); + }); + } - #[bench] - pub fn bench_recover(bh: &mut Bencher) { - let s = Secp256k1::new(); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign_recoverable(&msg, &sk).unwrap(); + #[bench] + pub fn bench_recover(bh: &mut Bencher) { + let s = Secp256k1::new(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); + let sig = s.sign_recoverable(&msg, &sk).unwrap(); - bh.iter(|| { - let res = s.recover(&msg, &sig).unwrap(); - black_box(res); - }); - } + bh.iter(|| { + let res = s.recover(&msg, &sig).unwrap(); + black_box(res); + }); + } } diff --git a/secp256k1zkp/src/macros.rs b/secp256k1zkp/src/macros.rs index 75295e54b..d2ed4d31e 100644 --- a/secp256k1zkp/src/macros.rs +++ b/secp256k1zkp/src/macros.rs @@ -20,25 +20,25 @@ macro_rules! impl_array_newtype { impl $thing { #[inline] - /// Converts the object to a raw pointer for FFI interfacing +/// Converts the object to a raw pointer for FFI interfacing pub fn as_ptr(&self) -> *const $ty { let &$thing(ref dat) = self; dat.as_ptr() } #[inline] - /// Converts the object to a mutable raw pointer for FFI interfacing +/// Converts the object to a mutable raw pointer for FFI interfacing pub fn as_mut_ptr(&mut self) -> *mut $ty { let &mut $thing(ref mut dat) = self; dat.as_mut_ptr() } #[inline] - /// Returns the length of the object as an array +/// Returns the length of the object as an array pub fn len(&self) -> usize { $len } #[inline] - /// Returns whether the object as an array is empty +/// Returns whether the object as an array is empty pub fn is_empty(&self) -> bool { false } } @@ -125,9 +125,9 @@ macro_rules! impl_array_newtype { impl ::std::hash::Hash for $thing { fn hash(&self, state: &mut H) { state.write(&self.0) - // for n in 0..self.len() { - // state.write_u8(self.0[n]); - // } +// for n in 0..self.len() { +// state.write_u8(self.0[n]); +// } } } @@ -159,45 +159,48 @@ macro_rules! impl_array_newtype { } } - impl ::serde::Deserialize for $thing { - fn deserialize(d: &mut D) -> Result<$thing, D::Error> - where D: ::serde::Deserializer + impl<'de> ::serde::Deserialize<'de> for $thing { + fn deserialize(d: D) -> Result<$thing, D::Error> + where D: ::serde::Deserializer<'de> { // We have to define the Visitor struct inside the function // to make it local ... all we really need is that it's // local to the macro, but this works too :) - struct Visitor { - marker: ::std::marker::PhantomData<$thing>, - } - impl ::serde::de::Visitor for Visitor { + struct Visitor; + + impl<'di> ::serde::de::Visitor<'di> for Visitor { type Value = $thing; + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("an array of bytes") + } + #[inline] - fn visit_seq(&mut self, mut v: V) -> Result<$thing, V::Error> - where V: ::serde::de::SeqVisitor + fn visit_seq(self, mut v: V) -> Result<$thing, V::Error> + where V: ::serde::de::SeqAccess<'di> { unsafe { use std::mem; let mut ret: [$ty; $len] = mem::uninitialized(); for i in 0..$len { - ret[i] = match try!(v.visit()) { + ret[i] = match try!(v.next_element()) { Some(c) => c, - None => return Err(::serde::de::Error::end_of_stream()) + None => return Err(::serde::de::Error::invalid_length(i, &self)) }; } - try!(v.end()); Ok($thing(ret)) } } } // Begin actual function - d.visit(Visitor { marker: ::std::marker::PhantomData }) + // d.visit(Visitor { marker: ::std::marker::PhantomData }) + d.deserialize_seq(Visitor) } } impl ::serde::Serialize for $thing { - fn serialize(&self, s: &mut S) -> Result<(), S::Error> + fn serialize(&self, s: S) -> Result where S: ::serde::Serializer { (&self.0[..]).serialize(s) diff --git a/secp256k1zkp/src/pedersen.rs b/secp256k1zkp/src/pedersen.rs index 91c58c7a4..c95a5e158 100644 --- a/secp256k1zkp/src/pedersen.rs +++ b/secp256k1zkp/src/pedersen.rs @@ -15,6 +15,8 @@ //! # Pedersen commitments and related range proofs +use std::cmp::min; +use std::fmt; use std::mem; use ContextFlag; @@ -26,6 +28,7 @@ use ffi; use key; use key::SecretKey; use rand::{Rng, OsRng}; +use serde::{ser, de}; /// A Pedersen commitment pub struct Commitment(pub [u8; constants::PEDERSEN_COMMITMENT_SIZE]); @@ -34,327 +37,392 @@ impl_pretty_debug!(Commitment); impl Commitment { - /// Uninitialized commitment, use with caution - unsafe fn blank() -> Commitment { - mem::uninitialized() - } - /// Converts a commitment to a public key - pub fn to_pubkey(&self, secp: &Secp256k1) -> Result { - key::PublicKey::from_slice(secp, &self.0) + /// Builds a Hash from a byte vector. If the vector is too short, it will be + /// completed by zeroes. If it's too long, it will be truncated. + pub fn from_vec(v: Vec) -> Commitment { + let mut h = [0; constants::PEDERSEN_COMMITMENT_SIZE]; + for i in 0..min(v.len(), constants::PEDERSEN_COMMITMENT_SIZE) { + h[i] = v[i]; } + Commitment(h) + } + /// Uninitialized commitment, use with caution + unsafe fn blank() -> Commitment { + mem::uninitialized() + } + /// Converts a commitment to a public key + pub fn to_pubkey(&self, secp: &Secp256k1) -> Result { + key::PublicKey::from_slice(secp, &self.0) + } } /// A range proof. Typically much larger in memory that the above (~5k). #[derive(Copy)] pub struct RangeProof { - /// The proof itself, at most 5134 bytes long - pub proof: [u8; constants::MAX_PROOF_SIZE], - /// The length of the proof - pub plen: usize, + /// The proof itself, at most 5134 bytes long + pub proof: [u8; constants::MAX_PROOF_SIZE], + /// The length of the proof + pub plen: usize, } impl PartialEq for RangeProof { - fn eq(&self, other: &Self) -> bool { - self.proof.as_ref() == other.proof.as_ref() - } + fn eq(&self, other: &Self) -> bool { + self.proof.as_ref() == other.proof.as_ref() + } } impl Clone for RangeProof { - #[inline] - fn clone(&self) -> RangeProof { - unsafe { - use std::intrinsics::copy_nonoverlapping; - use std::mem; - let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized(); - copy_nonoverlapping(self.proof.as_ptr(), - ret.as_mut_ptr(), - mem::size_of::()); - RangeProof { - proof: ret, - plen: self.plen, - } - } - } + #[inline] + fn clone(&self) -> RangeProof { + unsafe { + use std::intrinsics::copy_nonoverlapping; + use std::mem; + let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized(); + copy_nonoverlapping(self.proof.as_ptr(), + ret.as_mut_ptr(), + mem::size_of::()); + RangeProof { + proof: ret, + plen: self.plen, + } + } + } +} + +impl ser::Serialize for RangeProof { + fn serialize(&self, s: S) -> Result + where S: ser::Serializer + { + (&self.proof[..self.plen]).serialize(s) + } +} + +struct Visitor; + +impl<'di> de::Visitor<'di> for Visitor { + type Value = RangeProof; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("an array of bytes") + } + + #[inline] + fn visit_seq(self, mut v: V) -> Result + where V: de::SeqAccess<'di> + { + unsafe { + use std::mem; + let mut ret: [u8; constants::MAX_PROOF_SIZE] = mem::uninitialized(); + let mut i = 0; + while let Some(val) = v.next_element()? { + ret[i] = val; + i += 1; + } + Ok(RangeProof { + proof: ret, + plen: i, + }) + } + } +} + +impl<'de> de::Deserialize<'de> for RangeProof { + fn deserialize(d: D) -> Result + where D: de::Deserializer<'de> + { + + // Begin actual function + d.deserialize_seq(Visitor) + } } impl AsRef<[u8]> for RangeProof { - fn as_ref(&self) -> &[u8] { - &self.proof[..self.plen as usize] - } + fn as_ref(&self) -> &[u8] { + &self.proof[..self.plen as usize] + } } impl RangeProof { - /// The range proof as a byte slice. - pub fn bytes(&self) -> &[u8] { - &self.proof[..self.plen as usize] - } - /// Length of the range proof in bytes. - pub fn len(&self) -> usize { - self.plen - } + pub fn zero() -> RangeProof { + RangeProof { + proof: [0; constants::MAX_PROOF_SIZE], + plen: 0, + } + } + /// The range proof as a byte slice. + pub fn bytes(&self) -> &[u8] { + &self.proof[..self.plen as usize] + } + /// Length of the range proof in bytes. + pub fn len(&self) -> usize { + self.plen + } } /// The range that was proven pub struct ProofRange { - /// Min value that was proven - pub min: u64, - /// Max value that was proven - pub max: u64, + /// Min value that was proven + pub min: u64, + /// Max value that was proven + pub max: u64, } /// Information about a valid proof after rewinding it. pub struct ProofInfo { - /// Whether the proof is valid or not - pub success: bool, - /// Value that was used by the commitment - pub value: u64, - /// Message embedded in the proof - pub message: [u8; constants::PROOF_MSG_SIZE], - /// Length of the embedded message - pub mlen: i32, - /// Min value that was proven - pub min: u64, - /// Max value that was proven - pub max: u64, - /// Exponent used by the proof - pub exp: i32, - /// Mantissa used by the proof - pub mantissa: i32, + /// Whether the proof is valid or not + pub success: bool, + /// Value that was used by the commitment + pub value: u64, + /// Message embedded in the proof + pub message: [u8; constants::PROOF_MSG_SIZE], + /// Length of the embedded message + pub mlen: i32, + /// Min value that was proven + pub min: u64, + /// Max value that was proven + pub max: u64, + /// Exponent used by the proof + pub exp: i32, + /// Mantissa used by the proof + pub mantissa: i32, } impl ::std::fmt::Debug for RangeProof { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - try!(write!(f, "{}(", stringify!(RangeProof))); - for i in self.proof[..self.plen].iter().cloned() { - try!(write!(f, "{:02x}", i)); - } - write!(f, ")[{}]", self.plen) - } + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + try!(write!(f, "{}(", stringify!(RangeProof))); + for i in self.proof[..self.plen].iter().cloned() { + try!(write!(f, "{:02x}", i)); + } + write!(f, ")[{}]", self.plen) + } } impl Secp256k1 { - /// Creates a pedersen commitment from a value and a blinding factor - pub fn commit(&self, value: u64, blind: SecretKey) -> Result { + /// Creates a pedersen commitment from a value and a blinding factor + pub fn commit(&self, value: u64, blind: SecretKey) -> Result { - if self.caps != ContextFlag::Commit { - return Err(Error::IncapableContext); - } - let mut commit = [0; 33]; - unsafe { - ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), blind.as_ptr(), value) - }; - Ok(Commitment(commit)) - } + if self.caps != ContextFlag::Commit { + return Err(Error::IncapableContext); + } + let mut commit = [0; 33]; + unsafe { + ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), blind.as_ptr(), value) + }; + Ok(Commitment(commit)) + } - /// Convenience method to Create a pedersen commitment only from a value, with a zero blinding factor - pub fn commit_value(&self, value: u64) -> Result { + /// Convenience method to Create a pedersen commitment only from a value, + /// with a zero blinding factor + pub fn commit_value(&self, value: u64) -> Result { - if self.caps != ContextFlag::Commit { - return Err(Error::IncapableContext); - } - let mut commit = [0; 33]; - let zblind = [0; 32]; - unsafe { - ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), zblind.as_ptr(), value) - }; - Ok(Commitment(commit)) - } + if self.caps != ContextFlag::Commit { + return Err(Error::IncapableContext); + } + let mut commit = [0; 33]; + let zblind = [0; 32]; + unsafe { + ffi::secp256k1_pedersen_commit(self.ctx, commit.as_mut_ptr(), zblind.as_ptr(), value) + }; + Ok(Commitment(commit)) + } - /// Taking vectors of positive and negative commitments as well as an - /// expected excess, verifies that it all sums to zero. - pub fn verify_commit_sum(&self, - positive: Vec, - negative: Vec, - excess: i64) - -> bool { - let pos = map_vec!(positive, |p| p.0.as_ptr()); - let neg = map_vec!(negative, |n| n.0.as_ptr()); - unsafe { - ffi::secp256k1_pedersen_verify_tally(self.ctx, - pos.as_ptr(), - pos.len() as i32, - neg.as_ptr(), - neg.len() as i32, - excess) == 1 - } - } + /// Taking vectors of positive and negative commitments as well as an + /// expected excess, verifies that it all sums to zero. + pub fn verify_commit_sum(&self, + positive: Vec, + negative: Vec, + excess: i64) + -> bool { + let pos = map_vec!(positive, |p| p.0.as_ptr()); + let neg = map_vec!(negative, |n| n.0.as_ptr()); + unsafe { + ffi::secp256k1_pedersen_verify_tally(self.ctx, + pos.as_ptr(), + pos.len() as i32, + neg.as_ptr(), + neg.len() as i32, + excess) == 1 + } + } - /// Computes the sum of multiple positive and negative pedersen commitments. - pub fn commit_sum(&self, - positive: Vec, - negative: Vec) - -> Result { - let pos = map_vec!(positive, |p| p.0.as_ptr()); - let neg = map_vec!(negative, |n| n.0.as_ptr()); - let mut ret = unsafe { Commitment::blank() }; - let err = unsafe { - ffi::secp256k1_pedersen_commit_sum(self.ctx, - ret.as_mut_ptr(), - pos.as_ptr(), - pos.len() as i32, - neg.as_ptr(), - neg.len() as i32) - }; - if err == 1 { - Ok(ret) - } else { - Err(Error::IncorrectCommitSum) - } - } + /// Computes the sum of multiple positive and negative pedersen commitments. + pub fn commit_sum(&self, + positive: Vec, + negative: Vec) + -> Result { + let pos = map_vec!(positive, |p| p.0.as_ptr()); + let neg = map_vec!(negative, |n| n.0.as_ptr()); + let mut ret = unsafe { Commitment::blank() }; + let err = unsafe { + ffi::secp256k1_pedersen_commit_sum(self.ctx, + ret.as_mut_ptr(), + pos.as_ptr(), + pos.len() as i32, + neg.as_ptr(), + neg.len() as i32) + }; + if err == 1 { + Ok(ret) + } else { + Err(Error::IncorrectCommitSum) + } + } - /// Computes the sum of multiple positive and negative blinding factors. - pub fn blind_sum(&self, - positive: Vec, - negative: Vec) - -> Result { - let mut neg = map_vec!(negative, |n| n.as_ptr()); - let mut all = map_vec!(positive, |p| p.as_ptr()); - all.append(&mut neg); - let mut ret: [u8; 32] = unsafe { mem::uninitialized() }; - unsafe { - assert_eq!(ffi::secp256k1_pedersen_blind_sum(self.ctx, + /// Computes the sum of multiple positive and negative blinding factors. + pub fn blind_sum(&self, + positive: Vec, + negative: Vec) + -> Result { + let mut neg = map_vec!(negative, |n| n.as_ptr()); + let mut all = map_vec!(positive, |p| p.as_ptr()); + all.append(&mut neg); + let mut ret: [u8; 32] = unsafe { mem::uninitialized() }; + unsafe { + assert_eq!(ffi::secp256k1_pedersen_blind_sum(self.ctx, ret.as_mut_ptr(), all.as_ptr(), all.len() as i32, positive.len() as i32), 1) - } - // secp256k1 should never return an invalid private - SecretKey::from_slice(self, &ret) - } + } + // secp256k1 should never return an invalid private + SecretKey::from_slice(self, &ret) + } - /// Produces a range proof for the provided value, using min and max bounds, relying - /// on the blinding factor and commitment. - pub fn range_proof(&self, - min: u64, - value: u64, - blind: SecretKey, - commit: Commitment) - -> RangeProof { + /// Produces a range proof for the provided value, using min and max + /// bounds, relying + /// on the blinding factor and commitment. + pub fn range_proof(&self, + min: u64, + value: u64, + blind: SecretKey, + commit: Commitment) + -> RangeProof { - let mut rng = OsRng::new().unwrap(); - let mut nonce = [0u8; 32]; - rng.fill_bytes(&mut nonce); + let mut rng = OsRng::new().unwrap(); + let mut nonce = [0u8; 32]; + rng.fill_bytes(&mut nonce); - let mut retried = false; - let mut proof = [0; constants::MAX_PROOF_SIZE]; - let mut plen = constants::MAX_PROOF_SIZE as i32; - loop { - let err = unsafe { - // because: "This can randomly fail with probability around one in 2^100. - // If this happens, buy a lottery ticket and retry." - ffi::secp256k1_rangeproof_sign(self.ctx, - proof.as_mut_ptr(), - &mut plen, - min, - commit.as_ptr(), - blind.as_ptr(), - nonce.as_ptr(), - 0, - 64, - value) - }; - if retried { - break; - } - if err == 1 { - retried = true; - } - } - RangeProof { - proof: proof, - plen: plen as usize, - } - } + let mut retried = false; + let mut proof = [0; constants::MAX_PROOF_SIZE]; + let mut plen = constants::MAX_PROOF_SIZE as i32; + loop { + let err = unsafe { + // because: "This can randomly fail with probability around one in 2^100. + // If this happens, buy a lottery ticket and retry." + ffi::secp256k1_rangeproof_sign(self.ctx, + proof.as_mut_ptr(), + &mut plen, + min, + commit.as_ptr(), + blind.as_ptr(), + nonce.as_ptr(), + 0, + 64, + value) + }; + if retried { + break; + } + if err == 1 { + retried = true; + } + } + RangeProof { + proof: proof, + plen: plen as usize, + } + } - /// Verify a proof that a committed value is within a range. - pub fn verify_range_proof(&self, - commit: Commitment, - proof: RangeProof) - -> Result { - let mut min: u64 = 0; - let mut max: u64 = 0; + /// Verify a proof that a committed value is within a range. + pub fn verify_range_proof(&self, + commit: Commitment, + proof: RangeProof) + -> Result { + let mut min: u64 = 0; + let mut max: u64 = 0; - let success = unsafe { - ffi::secp256k1_rangeproof_verify(self.ctx, - &mut min, - &mut max, - commit.as_ptr(), - proof.proof.as_ptr(), - proof.plen as i32) == 1 - }; - if success { - Ok(ProofRange { - min: min, - max: max, - }) - } else { - Err(Error::InvalidRangeProof) - } - } + let success = unsafe { + ffi::secp256k1_rangeproof_verify(self.ctx, + &mut min, + &mut max, + commit.as_ptr(), + proof.proof.as_ptr(), + proof.plen as i32) == 1 + }; + if success { + Ok(ProofRange { + min: min, + max: max, + }) + } else { + Err(Error::InvalidRangeProof) + } + } - /// Verify a range proof proof and rewind the proof to recover information sent by its author. - pub fn rewind_range_proof(&self, - commit: Commitment, - proof: RangeProof, - nonce: [u8; 32]) - -> ProofInfo { - let mut value: u64 = 0; - let mut blind: [u8; 32] = unsafe { mem::uninitialized() }; - let mut message = [0u8; constants::PROOF_MSG_SIZE]; - let mut mlen: i32 = 0; - let mut min: u64 = 0; - let mut max: u64 = 0; - let success = unsafe { - ffi::secp256k1_rangeproof_rewind(self.ctx, - blind.as_mut_ptr(), - &mut value, - message.as_mut_ptr(), - &mut mlen, - nonce.as_ptr(), - &mut min, - &mut max, - commit.as_ptr(), - proof.proof.as_ptr(), - proof.plen as i32) == 1 - }; - ProofInfo { - success: success, - value: value, - message: message, - mlen: mlen, - min: min, - max: max, - exp: 0, - mantissa: 0, - } - } + /// Verify a range proof proof and rewind the proof to recover information + /// sent by its author. + pub fn rewind_range_proof(&self, + commit: Commitment, + proof: RangeProof, + nonce: [u8; 32]) + -> ProofInfo { + let mut value: u64 = 0; + let mut blind: [u8; 32] = unsafe { mem::uninitialized() }; + let mut message = [0u8; constants::PROOF_MSG_SIZE]; + let mut mlen: i32 = 0; + let mut min: u64 = 0; + let mut max: u64 = 0; + let success = unsafe { + ffi::secp256k1_rangeproof_rewind(self.ctx, + blind.as_mut_ptr(), + &mut value, + message.as_mut_ptr(), + &mut mlen, + nonce.as_ptr(), + &mut min, + &mut max, + commit.as_ptr(), + proof.proof.as_ptr(), + proof.plen as i32) == 1 + }; + ProofInfo { + success: success, + value: value, + message: message, + mlen: mlen, + min: min, + max: max, + exp: 0, + mantissa: 0, + } + } - /// General information extracted from a range proof. Does not provide any - /// information about the value or the message (see rewind). - pub fn range_proof_info(&self, proof: RangeProof) -> ProofInfo { - let mut exp: i32 = 0; - let mut mantissa: i32 = 0; - let mut min: u64 = 0; - let mut max: u64 = 0; - let success = unsafe { - ffi::secp256k1_rangeproof_info(self.ctx, - &mut exp, - &mut mantissa, - &mut min, - &mut max, - proof.proof.as_ptr(), - proof.plen as i32) == 1 - }; - ProofInfo { - success: success, - value: 0, - message: [0; 4096], - mlen: 0, - min: min, - max: max, - exp: exp, - mantissa: mantissa, - } - } + /// General information extracted from a range proof. Does not provide any + /// information about the value or the message (see rewind). + pub fn range_proof_info(&self, proof: RangeProof) -> ProofInfo { + let mut exp: i32 = 0; + let mut mantissa: i32 = 0; + let mut min: u64 = 0; + let mut max: u64 = 0; + let success = unsafe { + ffi::secp256k1_rangeproof_info(self.ctx, + &mut exp, + &mut mantissa, + &mut min, + &mut max, + proof.proof.as_ptr(), + proof.plen as i32) == 1 + }; + ProofInfo { + success: success, + value: 0, + message: [0; 4096], + mlen: 0, + min: min, + max: max, + exp: exp, + mantissa: mantissa, + } + } } diff --git a/secp256k1zkp/src/schnorr.rs b/secp256k1zkp/src/schnorr.rs index d8e69bae6..bd67c03cd 100644 --- a/secp256k1zkp/src/schnorr.rs +++ b/secp256k1zkp/src/schnorr.rs @@ -32,166 +32,166 @@ impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE); impl_pretty_debug!(Signature); impl Signature { - /// Deserializes a signature from a 64-byte vector - pub fn deserialize(data: &[u8]) -> Signature { - assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE); - unsafe { - let mut ret: Signature = mem::uninitialized(); - ptr::copy_nonoverlapping(data.as_ptr(), - ret.as_mut_ptr(), - constants::SCHNORR_SIGNATURE_SIZE); - ret - } - } + /// Deserializes a signature from a 64-byte vector + pub fn deserialize(data: &[u8]) -> Signature { + assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE); + unsafe { + let mut ret: Signature = mem::uninitialized(); + ptr::copy_nonoverlapping(data.as_ptr(), + ret.as_mut_ptr(), + constants::SCHNORR_SIGNATURE_SIZE); + ret + } + } - /// Serializes a signature to a 64-byte vector - pub fn serialize(&self) -> Vec { - let mut ret = Vec::with_capacity(constants::SCHNORR_SIGNATURE_SIZE); - unsafe { - ptr::copy_nonoverlapping(self.as_ptr(), - ret.as_mut_ptr(), - constants::SCHNORR_SIGNATURE_SIZE); - ret.set_len(constants::SCHNORR_SIGNATURE_SIZE); - } - ret - } + /// Serializes a signature to a 64-byte vector + pub fn serialize(&self) -> Vec { + let mut ret = Vec::with_capacity(constants::SCHNORR_SIGNATURE_SIZE); + unsafe { + ptr::copy_nonoverlapping(self.as_ptr(), + ret.as_mut_ptr(), + constants::SCHNORR_SIGNATURE_SIZE); + ret.set_len(constants::SCHNORR_SIGNATURE_SIZE); + } + ret + } } impl Secp256k1 { - /// Create a Schnorr signature - pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result { - if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Create a Schnorr signature + pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result { + if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - let mut ret: Signature = unsafe { mem::uninitialized() }; - unsafe { - // We can assume the return value because it's not possible to construct - // an invalid signature from a valid `Message` and `SecretKey` - let err = ffi::secp256k1_schnorr_sign(self.ctx, - ret.as_mut_ptr(), - msg.as_ptr(), - sk.as_ptr(), - ffi::secp256k1_nonce_function_rfc6979, - ptr::null()); - debug_assert_eq!(err, 1); - } - Ok(ret) - } + let mut ret: Signature = unsafe { mem::uninitialized() }; + unsafe { + // We can assume the return value because it's not possible to construct + // an invalid signature from a valid `Message` and `SecretKey` + let err = ffi::secp256k1_schnorr_sign(self.ctx, + ret.as_mut_ptr(), + msg.as_ptr(), + sk.as_ptr(), + ffi::secp256k1_nonce_function_rfc6979, + ptr::null()); + debug_assert_eq!(err, 1); + } + Ok(ret) + } - /// Verify a Schnorr signature - pub fn verify_schnorr(&self, - msg: &Message, - sig: &Signature, - pk: &PublicKey) - -> Result<(), Error> { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Verify a Schnorr signature + pub fn verify_schnorr(&self, + msg: &Message, + sig: &Signature, + pk: &PublicKey) + -> Result<(), Error> { + if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - if !pk.is_valid() { - Err(Error::InvalidPublicKey) - } else if unsafe { - ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr()) - } == 0 { - Err(Error::IncorrectSignature) - } else { - Ok(()) - } - } + if !pk.is_valid() { + Err(Error::InvalidPublicKey) + } else if unsafe { + ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(), pk.as_ptr()) + } == 0 { + Err(Error::IncorrectSignature) + } else { + Ok(()) + } + } - /// Retrieves the public key for which `sig` is a valid signature for `msg`. - /// Requires a verify-capable context. - pub fn recover_schnorr(&self, msg: &Message, sig: &Signature) -> Result { - if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { - return Err(Error::IncapableContext); - } + /// Retrieves the public key for which `sig` is a valid signature for `msg`. + /// Requires a verify-capable context. + pub fn recover_schnorr(&self, msg: &Message, sig: &Signature) -> Result { + if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None { + return Err(Error::IncapableContext); + } - let mut pk = unsafe { ffi::PublicKey::blank() }; - unsafe { - if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 { - return Err(Error::InvalidSignature); - } - }; - Ok(PublicKey::from(pk)) - } + let mut pk = unsafe { ffi::PublicKey::blank() }; + unsafe { + if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk, sig.as_ptr(), msg.as_ptr()) != 1 { + return Err(Error::InvalidSignature); + } + }; + Ok(PublicKey::from(pk)) + } } #[cfg(test)] mod tests { - use rand::{Rng, thread_rng}; - use ContextFlag; - use Message; - use Secp256k1; - use Error::IncapableContext; - use super::Signature; + use rand::{Rng, thread_rng}; + use ContextFlag; + use Message; + use Secp256k1; + use Error::IncapableContext; + use super::Signature; - #[test] - fn capabilities() { - let none = Secp256k1::with_caps(ContextFlag::None); - let sign = Secp256k1::with_caps(ContextFlag::SignOnly); - let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); - let full = Secp256k1::with_caps(ContextFlag::Full); + #[test] + fn capabilities() { + let none = Secp256k1::with_caps(ContextFlag::None); + let sign = Secp256k1::with_caps(ContextFlag::SignOnly); + let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly); + let full = Secp256k1::with_caps(ContextFlag::Full); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap(); - // Try signing - assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext)); - assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext)); - assert!(sign.sign_schnorr(&msg, &sk).is_ok()); - assert!(full.sign_schnorr(&msg, &sk).is_ok()); - assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk)); - let sig = full.sign_schnorr(&msg, &sk).unwrap(); + // Try signing + assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext)); + assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext)); + assert!(sign.sign_schnorr(&msg, &sk).is_ok()); + assert!(full.sign_schnorr(&msg, &sk).is_ok()); + assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk)); + let sig = full.sign_schnorr(&msg, &sk).unwrap(); - // Try verifying - assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); - assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); - assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok()); - assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok()); + // Try verifying + assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); + assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext)); + assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok()); + assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok()); - // Try pk recovery - assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext)); - assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext)); - assert!(vrfy.recover_schnorr(&msg, &sig).is_ok()); - assert!(full.recover_schnorr(&msg, &sig).is_ok()); + // Try pk recovery + assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext)); + assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext)); + assert!(vrfy.recover_schnorr(&msg, &sig).is_ok()); + assert!(full.recover_schnorr(&msg, &sig).is_ok()); - assert_eq!(vrfy.recover_schnorr(&msg, &sig), + assert_eq!(vrfy.recover_schnorr(&msg, &sig), full.recover_schnorr(&msg, &sig)); - assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk)); - } + assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk)); + } - #[test] - fn sign_verify() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn sign_verify() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig = s.sign_schnorr(&msg, &sk).unwrap(); - assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok()); - } + let sig = s.sign_schnorr(&msg, &sk).unwrap(); + assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok()); + } - #[test] - fn deserialize() { - let mut s = Secp256k1::new(); - s.randomize(&mut thread_rng()); + #[test] + fn deserialize() { + let mut s = Secp256k1::new(); + s.randomize(&mut thread_rng()); - let mut msg = [0u8; 32]; - thread_rng().fill_bytes(&mut msg); - let msg = Message::from_slice(&msg).unwrap(); + let mut msg = [0u8; 32]; + thread_rng().fill_bytes(&mut msg); + let msg = Message::from_slice(&msg).unwrap(); - let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); + let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap(); - let sig1 = s.sign_schnorr(&msg, &sk).unwrap(); - let sig2 = Signature::deserialize(&sig1.serialize()); - assert_eq!(sig1, sig2); - } + let sig1 = s.sign_schnorr(&msg, &sk).unwrap(); + let sig2 = Signature::deserialize(&sig1.serialize()); + assert_eq!(sig1, sig2); + } }