Skip to content

Commit 39febcb

Browse files
Create rust-bidings
Create bindings for all methods and static types in ellswift.h in secp256k1-sys and their respective safe-rust types. All methods are extensively commented and tested using BIP324's test vectors
1 parent da4f67b commit 39febcb

File tree

6 files changed

+822
-1
lines changed

6 files changed

+822
-1
lines changed

secp256k1-sys/build.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ fn main() {
2323
.define("SECP256K1_API", Some(""))
2424
.define("ENABLE_MODULE_ECDH", Some("1"))
2525
.define("ENABLE_MODULE_SCHNORRSIG", Some("1"))
26-
.define("ENABLE_MODULE_EXTRAKEYS", Some("1"));
26+
.define("ENABLE_MODULE_EXTRAKEYS", Some("1"))
27+
.define("ENABLE_MODULE_ELLSWIFT", Some("1"));
2728

2829
if cfg!(feature = "lowmemory") {
2930
base_config.define("ECMULT_WINDOW_SIZE", Some("4")); // A low-enough value to consume negligible memory

secp256k1-sys/src/lib.rs

+105
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ pub type SchnorrNonceFn = Option<unsafe extern "C" fn(
8282
data: *mut c_void,
8383
) -> c_int>;
8484

85+
/// A hash function used by `ellswift_ecdh` to hash the final ECDH shared secret.
86+
pub type EllswiftEcdhHashFn = Option<unsafe extern "C" fn(
87+
output: *mut c_uchar,
88+
x32: *const c_uchar,
89+
ell_a64: *const c_uchar,
90+
ell_b64: *const c_uchar,
91+
data: *mut c_void,
92+
) -> c_int>;
93+
8594
/// Data structure that contains additional arguments for schnorrsig_sign_custom.
8695
#[repr(C)]
8796
pub struct SchnorrSigExtraParams {
@@ -517,11 +526,32 @@ impl core::hash::Hash for Keypair {
517526
}
518527
}
519528

529+
/// Library-internal representation of a ElligatorSwift encoded group element.
530+
#[repr(C)]
531+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
532+
pub struct ElligatorSwift([u8; 64]);
533+
534+
impl ElligatorSwift {
535+
pub fn from_array(arr: [u8; 64]) -> Self {
536+
ElligatorSwift(arr)
537+
}
538+
pub fn to_array(self) -> [u8; 64] {
539+
self.0
540+
}
541+
}
542+
543+
impl_array_newtype!(ElligatorSwift, u8, 64);
544+
impl_raw_debug!(ElligatorSwift);
545+
520546
extern "C" {
521547
/// Default ECDH hash function
522548
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ecdh_hash_function_default")]
523549
pub static secp256k1_ecdh_hash_function_default: EcdhHashFn;
524550

551+
/// Default ECDH hash function for BIP324 key establishment
552+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ellswift_xdh_hash_function_bip324")]
553+
pub static secp256k1_ellswift_xdh_hash_function_bip324: EllswiftEcdhHashFn;
554+
525555
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_nonce_function_rfc6979")]
526556
pub static secp256k1_nonce_function_rfc6979: NonceFn;
527557

@@ -600,6 +630,34 @@ extern "C" {
600630
output_pubkey: *mut PublicKey,
601631
keypair: *const Keypair)
602632
-> c_int;
633+
// Elligator Swift
634+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ellswift_encode")]
635+
pub fn secp256k1_ellswift_encode(ctx: *const Context,
636+
ell64: *mut c_uchar,
637+
pubkey: *const PublicKey,
638+
rnd32: *const c_uchar)
639+
-> c_int;
640+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ellswift_decode")]
641+
pub fn secp256k1_ellswift_decode(ctx: *const Context,
642+
pubkey: *mut u8,
643+
ell64: *const c_uchar)
644+
-> c_int;
645+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ellswift_create")]
646+
pub fn secp256k1_ellswift_create(ctx: *const Context,
647+
ell64: *mut c_uchar,
648+
seckey32: *const c_uchar,
649+
aux_rand32: *const c_uchar)
650+
-> c_int;
651+
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_9_0_ellswift_xdh")]
652+
pub fn secp256k1_ellswift_xdh(ctx: *const Context,
653+
output: *mut c_uchar,
654+
ell_a64: *const c_uchar,
655+
ell_b64: *const c_uchar,
656+
seckey32: *const c_uchar,
657+
party: c_int,
658+
hashfp: EllswiftEcdhHashFn,
659+
data: *mut c_void)
660+
-> c_int;
603661
}
604662

605663
#[cfg(not(secp256k1_fuzz))]
@@ -979,6 +1037,53 @@ impl<T> CPtr for [T] {
9791037
}
9801038
}
9811039

1040+
impl<T> CPtr for &[T] {
1041+
type Target = T;
1042+
fn as_c_ptr(&self) -> *const Self::Target {
1043+
if self.is_empty() {
1044+
ptr::null()
1045+
} else {
1046+
self.as_ptr()
1047+
}
1048+
}
1049+
1050+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
1051+
if self.is_empty() {
1052+
ptr::null_mut()
1053+
} else {
1054+
self.as_ptr() as *mut Self::Target
1055+
}
1056+
}
1057+
1058+
}
1059+
1060+
impl CPtr for [u8; 32] {
1061+
type Target = u8;
1062+
fn as_c_ptr(&self) -> *const Self::Target {
1063+
self.as_ptr()
1064+
}
1065+
1066+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
1067+
self.as_mut_ptr()
1068+
}
1069+
}
1070+
1071+
impl <T: CPtr> CPtr for Option<T> {
1072+
type Target = T::Target;
1073+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
1074+
match self {
1075+
Some(contents) => contents.as_mut_c_ptr(),
1076+
None => ptr::null_mut(),
1077+
}
1078+
}
1079+
fn as_c_ptr(&self) -> *const Self::Target {
1080+
match self {
1081+
Some(content) => content.as_c_ptr(),
1082+
None => ptr::null(),
1083+
}
1084+
}
1085+
}
1086+
9821087
#[cfg(secp256k1_fuzz)]
9831088
mod fuzz_dummy {
9841089
use super::*;

src/constants.rs

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ pub const SCHNORR_PUBLIC_KEY_SIZE: usize = 32;
3030
/// The size of a key pair.
3131
pub const KEY_PAIR_SIZE: usize = 96;
3232

33+
/// The size of a full ElligatorSwift encoding.
34+
pub const ELLSWIFT_ENCODING_SIZE: usize = 64;
35+
3336
/// The Prime for the secp256k1 field element.
3437
#[rustfmt::skip]
3538
pub const FIELD_SIZE: [u8; 32] = [

0 commit comments

Comments
 (0)