Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP 0340 followups #253

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
130 changes: 100 additions & 30 deletions secp256k1-sys/src/lib.rs
Expand Up @@ -106,13 +106,32 @@ 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]) }
}
/// Creates an "uninitialized" FFI public key which is zeroed out
///
/// If you pass this to any FFI functions, except as an out-pointer,
/// the result is likely to be an assertation failure and process
/// termination.
pub unsafe fn new() -> Self {
Self::from_array_unchecked([0; 64])
}

/// Create a new public key usable for the FFI interface from raw bytes
///
/// Does not check the validity of the underlying representation. If it is
/// invalid the result may be assertation failures (and process aborts) from
/// the underlying library. You should not use this method except with data
/// that you obtained from the FFI interface of the same version of this
/// library.
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
PublicKey(data)
}

impl Default for PublicKey {
fn default() -> Self {
PublicKey::new()
/// Returns the underlying FFI opaque representation of the public key
///
/// You should not use this unless you really know what you are doing. It is
/// essentially only useful for extending the FFI interface itself.
pub fn underlying_bytes(self) -> [c_uchar; 64] {
self.0
}
}

Expand All @@ -129,13 +148,32 @@ impl_array_newtype!(Signature, c_uchar, 64);
impl_raw_debug!(Signature);

impl Signature {
/// Create a new (zeroed) signature usable for the FFI interface
pub fn new() -> Signature { Signature([0; 64]) }
}
/// Creates an "uninitialized" FFI signature which is zeroed out
///
/// If you pass this to any FFI functions, except as an out-pointer,
/// the result is likely to be an assertation failure and process
/// termination.
pub unsafe fn new() -> Self {
Self::from_array_unchecked([0; 64])
}

impl Default for Signature {
fn default() -> Self {
Signature::new()
/// Create a new signature usable for the FFI interface from raw bytes
///
/// Does not check the validity of the underlying representation. If it is
/// invalid the result may be assertation failures (and process aborts) from
/// the underlying library. You should not use this method except with data
/// that you obtained from the FFI interface of the same version of this
/// library.
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
Signature(data)
}

/// Returns the underlying FFI opaque representation of the signature
///
/// You should not use this unless you really know what you are doing. It is
/// essentially only useful for extending the FFI interface itself.
pub fn underlying_bytes(self) -> [c_uchar; 64] {
self.0
}
}

Expand All @@ -145,11 +183,33 @@ impl_array_newtype!(XOnlyPublicKey, c_uchar, 64);
impl_raw_debug!(XOnlyPublicKey);

impl XOnlyPublicKey {
/// Create a new (zeroed) x-only public key usable for the FFI interface
pub fn new() -> XOnlyPublicKey { XOnlyPublicKey([0; 64]) }
pub fn from_array(data: [c_uchar; 64]) -> XOnlyPublicKey {
/// Creates an "uninitialized" FFI x-only public key which is zeroed out
///
/// If you pass this to any FFI functions, except as an out-pointer,
/// the result is likely to be an assertation failure and process
/// termination.
pub unsafe fn new() -> Self {
Self::from_array_unchecked([0; 64])
}

/// Create a new x-only public key usable for the FFI interface from raw bytes
///
/// Does not check the validity of the underlying representation. If it is
/// invalid the result may be assertation failures (and process aborts) from
/// the underlying library. You should not use this method except with data
/// that you obtained from the FFI interface of the same version of this
/// library.
pub unsafe fn from_array_unchecked(data: [c_uchar; 64]) -> Self {
XOnlyPublicKey(data)
}

/// Returns the underlying FFI opaque representation of the x-only public key
///
/// You should not use this unless you really know what you are doing. It is
/// essentially only useful for extending the FFI interface itself.
pub fn underlying_bytes(self) -> [c_uchar; 64] {
self.0
}
}

impl hash::Hash for XOnlyPublicKey {
Expand All @@ -158,23 +218,39 @@ impl hash::Hash for XOnlyPublicKey {
}
}

impl Default for XOnlyPublicKey {
fn default() -> Self {
XOnlyPublicKey::new()
}
}

#[repr(C)]
pub struct KeyPair([c_uchar; 96]);
impl_array_newtype!(KeyPair, c_uchar, 96);
impl_raw_debug!(KeyPair);

impl KeyPair {
/// Create a new (zeroed) key pair usable for the FFI interface
pub fn new() -> KeyPair { KeyPair([0; 96]) }
pub fn from_array(data: [c_uchar; 96]) -> KeyPair {
/// Creates an "uninitialized" FFI keypair which is zeroed out
///
/// If you pass this to any FFI functions, except as an out-pointer,
/// the result is likely to be an assertation failure and process
/// termination.
pub unsafe fn new() -> Self {
Self::from_array_unchecked([0; 96])
}

/// Create a new keypair usable for the FFI interface from raw bytes
///
/// Does not check the validity of the underlying representation. If it is
/// invalid the result may be assertation failures (and process aborts) from
/// the underlying library. You should not use this method except with data
/// that you obtained from the FFI interface of the same version of this
/// library.
pub unsafe fn from_array_unchecked(data: [c_uchar; 96]) -> Self {
KeyPair(data)
}

/// Returns the underlying FFI opaque representation of the x-only public key
///
/// You should not use this unless you really know what you are doing. It is
/// essentially only useful for extending the FFI interface itself.
pub fn underlying_bytes(self) -> [c_uchar; 96] {
self.0
}
}

impl hash::Hash for KeyPair {
Expand All @@ -183,12 +259,6 @@ impl hash::Hash for KeyPair {
}
}

impl Default for KeyPair {
fn default() -> Self {
KeyPair::new()
}
}

#[cfg(not(feature = "fuzztarget"))]
extern "C" {
/// Default ECDH hash function
Expand Down
6 changes: 3 additions & 3 deletions src/key.rs
Expand Up @@ -233,23 +233,23 @@ impl PublicKey {
pub fn from_secret_key<C: Signing>(secp: &Secp256k1<C>,
sk: &SecretKey)
-> PublicKey {
let mut pk = ffi::PublicKey::new();
unsafe {
let mut pk = ffi::PublicKey::new();
// 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_c_ptr());
debug_assert_eq!(res, 1);
PublicKey(pk)
}
PublicKey(pk)
}

/// Creates a public key directly from a slice
#[inline]
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
if data.is_empty() {return Err(Error::InvalidPublicKey);}

let mut pk = ffi::PublicKey::new();
unsafe {
let mut pk = ffi::PublicKey::new();
if ffi::secp256k1_ec_pubkey_parse(
ffi::secp256k1_context_no_precomp,
&mut pk,
Expand Down
13 changes: 7 additions & 6 deletions src/lib.rs
Expand Up @@ -269,9 +269,8 @@ impl Signature {
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
if data.is_empty() {return Err(Error::InvalidSignature);}

let mut ret = ffi::Signature::new();

unsafe {
let mut ret = ffi::Signature::new();
if ffi::secp256k1_ecdsa_signature_parse_der(
ffi::secp256k1_context_no_precomp,
&mut ret,
Expand All @@ -288,12 +287,12 @@ impl Signature {

/// Converts a 64-byte compact-encoded byte slice to a signature
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
let mut ret = ffi::Signature::new();
if data.len() != 64 {
return Err(Error::InvalidSignature)
}

unsafe {
let mut ret = ffi::Signature::new();
if ffi::secp256k1_ecdsa_signature_parse_compact(
ffi::secp256k1_context_no_precomp,
&mut ret,
Expand Down Expand Up @@ -522,6 +521,8 @@ pub enum Error {
InvalidRecoveryId,
/// Invalid tweak for add_*_assign or mul_*_assign
InvalidTweak,
/// `tweak_add_check` failed on an xonly public key
TweakCheckFailed,
/// Didn't pass enough memory to context creation with preallocated memory
NotEnoughMemory,
}
Expand All @@ -536,6 +537,7 @@ impl Error {
Error::InvalidSecretKey => "secp: malformed or out-of-range secret key",
Error::InvalidRecoveryId => "secp: bad recovery id",
Error::InvalidTweak => "secp: bad tweak",
Error::TweakCheckFailed => "secp: xonly_pubkey_tewak_add_check failed",
Error::NotEnoughMemory => "secp: not enough memory allocated",
}
}
Expand Down Expand Up @@ -661,16 +663,15 @@ impl<C: Signing> Secp256k1<C> {
pub fn sign(&self, msg: &Message, sk: &key::SecretKey)
-> Signature {

let mut ret = ffi::Signature::new();
unsafe {
let mut ret = ffi::Signature::new();
// 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_c_ptr(),
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
ptr::null()), 1);
Signature::from(ret)
}

Signature::from(ret)
}

/// Generates a random keypair. Convenience function for `key::SecretKey::new`
Expand Down
11 changes: 5 additions & 6 deletions src/recovery.rs
Expand Up @@ -112,16 +112,16 @@ impl RecoverableSignature {
/// for verification
#[inline]
pub fn to_standard(&self) -> Signature {
let mut ret = super_ffi::Signature::new();
unsafe {
let mut ret = super_ffi::Signature::new();
let err = ffi::secp256k1_ecdsa_recoverable_signature_convert(
super_ffi::secp256k1_context_no_precomp,
&mut ret,
self.as_c_ptr(),
);
assert!(err == 1);
Signature(ret)
}
Signature(ret)
}
}

Expand Down Expand Up @@ -178,15 +178,14 @@ impl<C: Verification> Secp256k1<C> {
pub fn recover(&self, msg: &Message, sig: &RecoverableSignature)
-> Result<key::PublicKey, Error> {

let mut pk = super_ffi::PublicKey::new();

unsafe {
let mut pk = super_ffi::PublicKey::new();
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
sig.as_c_ptr(), msg.as_c_ptr()) != 1 {
return Err(Error::InvalidSignature);
}
};
Ok(key::PublicKey::from(pk))
Ok(key::PublicKey::from(pk))
}
}
}

Expand Down