Merge pull request #264 from rust-bitcoin/2020-12--no-extsymb2
redo fuzz target
This commit is contained in:
commit
867b920aac
|
@ -33,12 +33,17 @@ if [ "$DO_FEATURE_MATRIX" = true ]; then
|
||||||
cargo test --all --features="$feature"
|
cargo test --all --features="$feature"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Other combos
|
# Other combos
|
||||||
RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --no-run --all
|
RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS=$RUSTFLAGS cargo test --all
|
||||||
RUSTFLAGS='--cfg=rust_secp_fuzz' cargo test --no-run --all --features="recovery"
|
RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS=$RUSTFLAGS cargo test --all --features="$FEATURES"
|
||||||
cargo test --all --features="rand rand-std"
|
cargo test --all --features="rand rand-std"
|
||||||
cargo test --all --features="rand serde"
|
cargo test --all --features="rand serde"
|
||||||
|
|
||||||
|
if [ "$DO_BENCH" = true ]; then # proxy for us having a nightly compiler
|
||||||
|
cargo test --all --all-features
|
||||||
|
RUSTFLAGS='--cfg=rust_secp_fuzz' RUSTDOCFLAGS='--cfg=rust_secp_fuzz' cargo test --all --all-features
|
||||||
|
fi
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
cargo run --example sign_verify
|
cargo run --example sign_verify
|
||||||
cargo run --example sign_verify_recovery --features=recovery
|
cargo run --example sign_verify_recovery --features=recovery
|
||||||
|
|
|
@ -58,36 +58,37 @@ pub const SECP256K1_SER_COMPRESSED: c_uint = (1 << 1) | (1 << 8);
|
||||||
/// around the FFI functions to use it. And it's an unsafe type.
|
/// around the FFI functions to use it. And it's an unsafe type.
|
||||||
/// Nonces are generated deterministically by RFC6979 by
|
/// Nonces are generated deterministically by RFC6979 by
|
||||||
/// default; there should be no need to ever change this.
|
/// default; there should be no need to ever change this.
|
||||||
pub type NonceFn = unsafe extern "C" fn(nonce32: *mut c_uchar,
|
pub type NonceFn = Option<unsafe extern "C" fn(
|
||||||
msg32: *const c_uchar,
|
nonce32: *mut c_uchar,
|
||||||
key32: *const c_uchar,
|
msg32: *const c_uchar,
|
||||||
algo16: *const c_uchar,
|
key32: *const c_uchar,
|
||||||
data: *mut c_void,
|
algo16: *const c_uchar,
|
||||||
attempt: c_uint,
|
data: *mut c_void,
|
||||||
) -> c_int;
|
attempt: c_uint,
|
||||||
|
) -> c_int>;
|
||||||
|
|
||||||
/// Hash function to use to post-process an ECDH point to get
|
/// Hash function to use to post-process an ECDH point to get
|
||||||
/// a shared secret.
|
/// a shared secret.
|
||||||
pub type EcdhHashFn = unsafe extern "C" fn(
|
pub type EcdhHashFn = Option<unsafe extern "C" fn(
|
||||||
output: *mut c_uchar,
|
output: *mut c_uchar,
|
||||||
x: *const c_uchar,
|
x: *const c_uchar,
|
||||||
y: *const c_uchar,
|
y: *const c_uchar,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
) -> c_int;
|
) -> c_int>;
|
||||||
|
|
||||||
/// Same as secp256k1_nonce function with the exception of accepting an
|
/// Same as secp256k1_nonce function with the exception of accepting an
|
||||||
/// additional pubkey argument and not requiring an attempt argument. The pubkey
|
/// additional pubkey argument and not requiring an attempt argument. The pubkey
|
||||||
/// argument can protect signature schemes with key-prefixed challenge hash
|
/// argument can protect signature schemes with key-prefixed challenge hash
|
||||||
/// inputs against reusing the nonce when signing with the wrong precomputed
|
/// inputs against reusing the nonce when signing with the wrong precomputed
|
||||||
/// pubkey.
|
/// pubkey.
|
||||||
pub type SchnorrNonceFn = unsafe extern "C" fn(
|
pub type SchnorrNonceFn = Option<unsafe extern "C" fn(
|
||||||
nonce32: *mut c_uchar,
|
nonce32: *mut c_uchar,
|
||||||
msg32: *const c_uchar,
|
msg32: *const c_uchar,
|
||||||
key32: *const c_uchar,
|
key32: *const c_uchar,
|
||||||
xonly_pk32: *const c_uchar,
|
xonly_pk32: *const c_uchar,
|
||||||
algo16: *const c_uchar,
|
algo16: *const c_uchar,
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
) -> c_int;
|
) -> c_int>;
|
||||||
|
|
||||||
/// A Secp256k1 context, containing various precomputed values and such
|
/// A Secp256k1 context, containing various precomputed values and such
|
||||||
/// needed to do elliptic curve computations. If you create one of these
|
/// needed to do elliptic curve computations. If you create one of these
|
||||||
|
@ -96,13 +97,6 @@ pub type SchnorrNonceFn = unsafe extern "C" fn(
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[repr(C)] pub struct Context(c_int);
|
#[repr(C)] pub struct Context(c_int);
|
||||||
|
|
||||||
#[cfg(rust_secp_fuzz)]
|
|
||||||
impl Context {
|
|
||||||
pub fn flags(&self) -> u32 {
|
|
||||||
self.0 as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Library-internal representation of a Secp256k1 public key
|
/// Library-internal representation of a Secp256k1 public key
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PublicKey([c_uchar; 64]);
|
pub struct PublicKey([c_uchar; 64]);
|
||||||
|
@ -263,7 +257,6 @@ impl hash::Hash for KeyPair {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(rust_secp_fuzz))]
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Default ECDH hash function
|
/// Default ECDH hash function
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh_hash_function_default")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh_hash_function_default")]
|
||||||
|
@ -275,6 +268,9 @@ extern "C" {
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_default")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_default")]
|
||||||
pub static secp256k1_nonce_function_default: NonceFn;
|
pub static secp256k1_nonce_function_default: NonceFn;
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")]
|
||||||
|
pub static secp256k1_nonce_function_bip340: SchnorrNonceFn;
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_context_no_precomp")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_context_no_precomp")]
|
||||||
pub static secp256k1_context_no_precomp: *const Context;
|
pub static secp256k1_context_no_precomp: *const Context;
|
||||||
|
|
||||||
|
@ -342,35 +338,10 @@ extern "C" {
|
||||||
in_sig: *const Signature)
|
in_sig: *const Signature)
|
||||||
-> c_int;
|
-> c_int;
|
||||||
|
|
||||||
// ECDSA
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_verify")]
|
|
||||||
pub fn secp256k1_ecdsa_verify(cx: *const Context,
|
|
||||||
sig: *const Signature,
|
|
||||||
msg32: *const c_uchar,
|
|
||||||
pk: *const PublicKey)
|
|
||||||
-> c_int;
|
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign")]
|
|
||||||
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;
|
|
||||||
|
|
||||||
// EC
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_seckey_verify")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_seckey_verify")]
|
||||||
pub fn secp256k1_ec_seckey_verify(cx: *const Context,
|
pub fn secp256k1_ec_seckey_verify(cx: *const Context,
|
||||||
sk: *const c_uchar) -> c_int;
|
sk: *const c_uchar) -> c_int;
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_create")]
|
|
||||||
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
|
|
||||||
|
|
||||||
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")]
|
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")]
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_negate")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_negate")]
|
||||||
pub fn secp256k1_ec_privkey_negate(cx: *const Context,
|
pub fn secp256k1_ec_privkey_negate(cx: *const Context,
|
||||||
|
@ -380,10 +351,6 @@ extern "C" {
|
||||||
pub fn secp256k1_ec_seckey_negate(cx: *const Context,
|
pub fn secp256k1_ec_seckey_negate(cx: *const Context,
|
||||||
sk: *mut c_uchar) -> c_int;
|
sk: *mut c_uchar) -> c_int;
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_negate")]
|
|
||||||
pub fn secp256k1_ec_pubkey_negate(cx: *const Context,
|
|
||||||
pk: *mut PublicKey) -> c_int;
|
|
||||||
|
|
||||||
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")]
|
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_add function instead")]
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_add")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_add")]
|
||||||
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
|
pub fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
|
||||||
|
@ -397,12 +364,6 @@ extern "C" {
|
||||||
tweak: *const c_uchar)
|
tweak: *const c_uchar)
|
||||||
-> c_int;
|
-> c_int;
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_add")]
|
|
||||||
pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
|
|
||||||
pk: *mut PublicKey,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int;
|
|
||||||
|
|
||||||
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_mul function instead")]
|
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_tweak_mul function instead")]
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_mul")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_privkey_tweak_mul")]
|
||||||
pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
|
pub fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
|
||||||
|
@ -416,6 +377,23 @@ extern "C" {
|
||||||
tweak: *const c_uchar)
|
tweak: *const c_uchar)
|
||||||
-> c_int;
|
-> c_int;
|
||||||
|
|
||||||
|
// EC
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_create")]
|
||||||
|
pub fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey,
|
||||||
|
sk: *const c_uchar) -> c_int;
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_negate")]
|
||||||
|
pub fn secp256k1_ec_pubkey_negate(cx: *const Context,
|
||||||
|
pk: *mut PublicKey) -> c_int;
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_add")]
|
||||||
|
pub fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
|
||||||
|
pk: *mut PublicKey,
|
||||||
|
tweak: *const c_uchar)
|
||||||
|
-> c_int;
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_mul")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ec_pubkey_tweak_mul")]
|
||||||
pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
|
pub fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
|
||||||
pk: *mut PublicKey,
|
pk: *mut PublicKey,
|
||||||
|
@ -439,31 +417,7 @@ extern "C" {
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
) -> c_int;
|
) -> c_int;
|
||||||
|
|
||||||
|
|
||||||
// Schnorr Signatures
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")]
|
|
||||||
pub static secp256k1_nonce_function_bip340: SchnorrNonceFn;
|
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_sign")]
|
|
||||||
pub fn secp256k1_schnorrsig_sign(
|
|
||||||
cx: *const Context,
|
|
||||||
sig: *mut c_uchar,
|
|
||||||
msg32: *const c_uchar,
|
|
||||||
keypair: *const KeyPair,
|
|
||||||
noncefp: SchnorrNonceFn,
|
|
||||||
noncedata: *const c_void
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_verify")]
|
|
||||||
pub fn secp256k1_schnorrsig_verify(
|
|
||||||
cx: *const Context,
|
|
||||||
sig64: *const c_uchar,
|
|
||||||
msg32: *const c_uchar,
|
|
||||||
pubkey: *const XOnlyPublicKey,
|
|
||||||
) -> c_int;
|
|
||||||
|
|
||||||
// Extra keys
|
// Extra keys
|
||||||
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_keypair_create")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_keypair_create")]
|
||||||
pub fn secp256k1_keypair_create(
|
pub fn secp256k1_keypair_create(
|
||||||
cx: *const Context,
|
cx: *const Context,
|
||||||
|
@ -526,6 +480,45 @@ extern "C" {
|
||||||
) -> c_int;
|
) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(rust_secp_fuzz))]
|
||||||
|
extern "C" {
|
||||||
|
// ECDSA
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_verify")]
|
||||||
|
pub fn secp256k1_ecdsa_verify(cx: *const Context,
|
||||||
|
sig: *const Signature,
|
||||||
|
msg32: *const c_uchar,
|
||||||
|
pk: *const PublicKey)
|
||||||
|
-> c_int;
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign")]
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Schnorr Signatures
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_sign")]
|
||||||
|
pub fn secp256k1_schnorrsig_sign(
|
||||||
|
cx: *const Context,
|
||||||
|
sig: *mut c_uchar,
|
||||||
|
msg32: *const c_uchar,
|
||||||
|
keypair: *const KeyPair,
|
||||||
|
noncefp: SchnorrNonceFn,
|
||||||
|
noncedata: *const c_void
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_schnorrsig_verify")]
|
||||||
|
pub fn secp256k1_schnorrsig_verify(
|
||||||
|
cx: *const Context,
|
||||||
|
sig64: *const c_uchar,
|
||||||
|
msg32: *const c_uchar,
|
||||||
|
pubkey: *const XOnlyPublicKey,
|
||||||
|
) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A reimplementation of the C function `secp256k1_context_create` in rust.
|
/// A reimplementation of the C function `secp256k1_context_create` in rust.
|
||||||
///
|
///
|
||||||
|
@ -674,221 +667,31 @@ impl<T> CPtr for [T] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(rust_secp_fuzz)]
|
#[cfg(rust_secp_fuzz)]
|
||||||
mod fuzz_dummy {
|
mod fuzz_dummy {
|
||||||
extern crate std;
|
use super::*;
|
||||||
use self::std::{ptr, mem};
|
|
||||||
use self::std::boxed::Box;
|
|
||||||
use types::*;
|
|
||||||
use {Signature, Context, NonceFn, EcdhHashFn, PublicKey,
|
|
||||||
SchnorrNonceFn, XOnlyPublicKey, KeyPair,
|
|
||||||
SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN,
|
|
||||||
SECP256K1_SER_COMPRESSED, SECP256K1_SER_UNCOMPRESSED};
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
pub static secp256k1_context_no_precomp: &Context = &Context(0);
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdh_hash_function_default")]
|
|
||||||
pub static secp256k1_ecdh_hash_function_default: EcdhHashFn;
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_rfc6979")]
|
|
||||||
pub static secp256k1_nonce_function_rfc6979: NonceFn;
|
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_nonce_function_bip340")]
|
|
||||||
pub static secp256k1_nonce_function_bip340: SchnorrNonceFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contexts
|
|
||||||
/// Creates a dummy context, tracking flags to ensure proper calling semantics
|
|
||||||
pub unsafe fn secp256k1_context_preallocated_create(_ptr: *mut c_void, flags: c_uint) -> *mut Context {
|
|
||||||
let b = Box::new(Context(flags as i32));
|
|
||||||
Box::into_raw(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return dummy size of context struct.
|
|
||||||
pub unsafe fn secp256k1_context_preallocated_size(_flags: c_uint) -> size_t {
|
|
||||||
mem::size_of::<Context>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return dummy size of context struct.
|
|
||||||
pub unsafe fn secp256k1_context_preallocated_clone_size(_cx: *mut Context) -> size_t {
|
|
||||||
mem::size_of::<Context>()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies a dummy context
|
|
||||||
pub unsafe fn secp256k1_context_preallocated_clone(cx: *const Context, prealloc: *mut c_void) -> *mut Context {
|
|
||||||
let ret = prealloc as *mut Context;
|
|
||||||
*ret = (*cx).clone();
|
|
||||||
ret
|
|
||||||
}
|
|
||||||
|
|
||||||
/// "Destroys" a dummy context
|
|
||||||
pub unsafe fn secp256k1_context_preallocated_destroy(cx: *mut Context) {
|
|
||||||
(*cx).0 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Asserts that cx is properly initialized
|
|
||||||
pub unsafe fn secp256k1_context_randomize(cx: *mut Context,
|
|
||||||
_seed32: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pubkeys
|
|
||||||
/// Parse 33/65 byte pubkey into PublicKey, losing compressed information
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_parse(cx: *const Context, pk: *mut PublicKey,
|
|
||||||
input: *const c_uchar, in_len: size_t)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
match in_len {
|
|
||||||
33 => {
|
|
||||||
if (*input.offset(1) > 0x7f && *input != 2) || (*input.offset(1) <= 0x7f && *input != 3) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
ptr::copy(input.offset(1), (*pk).0[0..32].as_mut_ptr(), 32);
|
|
||||||
ptr::copy(input.offset(1), (*pk).0[32..64].as_mut_ptr(), 32);
|
|
||||||
test_pk_validate(cx, pk)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
65 => {
|
|
||||||
if *input != 4 && *input != 6 && *input != 7 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
ptr::copy(input.offset(1), (*pk).0.as_mut_ptr(), 64);
|
|
||||||
test_pk_validate(cx, pk)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize PublicKey back to 33/65 byte pubkey
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_serialize(cx: *const Context, output: *mut c_uchar,
|
|
||||||
out_len: *mut size_t, pk: *const PublicKey,
|
|
||||||
compressed: c_uint)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if test_pk_validate(cx, pk) != 1 { return 0; }
|
|
||||||
if compressed == SECP256K1_SER_COMPRESSED {
|
|
||||||
assert_eq!(*out_len, 33);
|
|
||||||
if (*pk).0[0] > 0x7f {
|
|
||||||
*output = 2;
|
|
||||||
} else {
|
|
||||||
*output = 3;
|
|
||||||
}
|
|
||||||
ptr::copy((*pk).0.as_ptr(), output.offset(1), 32);
|
|
||||||
} else if compressed == SECP256K1_SER_UNCOMPRESSED {
|
|
||||||
assert_eq!(*out_len, 65);
|
|
||||||
*output = 4;
|
|
||||||
ptr::copy((*pk).0.as_ptr(), output.offset(1), 64);
|
|
||||||
} else {
|
|
||||||
panic!("Bad flags");
|
|
||||||
}
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signatures
|
|
||||||
pub unsafe fn secp256k1_ecdsa_signature_parse_der(_cx: *const Context, _sig: *mut Signature,
|
|
||||||
_input: *const c_uchar, _in_len: size_t)
|
|
||||||
-> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies input64 to sig, checking the pubkey part is valid
|
|
||||||
pub unsafe fn secp256k1_ecdsa_signature_parse_compact(cx: *const Context, sig: *mut Signature,
|
|
||||||
input64: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, input64.offset(32)) != 1 { return 0; } // sig should be msg32||sk
|
|
||||||
ptr::copy(input64, (*sig).0[..].as_mut_ptr(), 64);
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn ecdsa_signature_parse_der_lax(_cx: *const Context, _sig: *mut Signature,
|
|
||||||
_input: *const c_uchar, _in_len: size_t)
|
|
||||||
-> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies up to 72 bytes into output from sig
|
|
||||||
pub unsafe fn secp256k1_ecdsa_signature_serialize_der(cx: *const Context, output: *mut c_uchar,
|
|
||||||
out_len: *mut size_t, sig: *const Signature)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
|
|
||||||
let mut len_r = 33;
|
|
||||||
if *(*sig).0.as_ptr().offset(0) < 0x80 {
|
|
||||||
len_r -= 1;
|
|
||||||
}
|
|
||||||
let mut len_s = 33;
|
|
||||||
if *(*sig).0.as_ptr().offset(32) < 0x80 {
|
|
||||||
len_s -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(*out_len >= (6 + len_s + len_r) as usize);
|
|
||||||
|
|
||||||
*output.offset(0) = 0x30;
|
|
||||||
*output.offset(1) = 4 + len_r + len_s;
|
|
||||||
*output.offset(2) = 0x02;
|
|
||||||
*output.offset(3) = len_r;
|
|
||||||
if len_r == 33 {
|
|
||||||
*output.offset(4) = 0;
|
|
||||||
ptr::copy((*sig).0[..].as_ptr(), output.offset(5), 32);
|
|
||||||
} else {
|
|
||||||
ptr::copy((*sig).0[..].as_ptr(), output.offset(4), 32);
|
|
||||||
}
|
|
||||||
*output.offset(4 + len_r as isize) = 0x02;
|
|
||||||
*output.offset(5 + len_r as isize) = len_s;
|
|
||||||
if len_s == 33 {
|
|
||||||
*output.offset(6 + len_r as isize) = 0;
|
|
||||||
ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(7 + len_r as isize), 32);
|
|
||||||
} else {
|
|
||||||
ptr::copy((*sig).0[..].as_ptr().offset(32), output.offset(6 + len_r as isize), 32);
|
|
||||||
}
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies sig to output64
|
|
||||||
pub unsafe fn secp256k1_ecdsa_signature_serialize_compact(cx: *const Context, output64: *mut c_uchar,
|
|
||||||
sig: *const Signature)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
ptr::copy((*sig).0[..].as_ptr(), output64, 64);
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ecdsa_signature_normalize(_cx: *const Context, _out_sig: *mut Signature,
|
|
||||||
_in_sig: *const Signature)
|
|
||||||
-> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ECDSA
|
// ECDSA
|
||||||
/// Verifies that sig is msg32||pk[0..32]
|
/// Verifies that sig is msg32||pk[..32]
|
||||||
pub unsafe fn secp256k1_ecdsa_verify(cx: *const Context,
|
pub unsafe fn secp256k1_ecdsa_verify(cx: *const Context,
|
||||||
sig: *const Signature,
|
sig: *const Signature,
|
||||||
msg32: *const c_uchar,
|
msg32: *const c_uchar,
|
||||||
pk: *const PublicKey)
|
pk: *const PublicKey)
|
||||||
-> c_int {
|
-> c_int {
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
// Check context is built for verification
|
||||||
assert!((*cx).0 as u32 & SECP256K1_START_VERIFY == SECP256K1_START_VERIFY);
|
let mut new_pk = (*pk).clone();
|
||||||
if test_pk_validate(cx, pk) != 1 { return 0; }
|
let _ = secp256k1_ec_pubkey_tweak_add(cx, &mut new_pk, msg32);
|
||||||
for i in 0..32 {
|
// Actually verify
|
||||||
if (*sig).0[i] != *msg32.offset(i as isize) {
|
let sig_sl = slice::from_raw_parts(sig as *const u8, 64);
|
||||||
return 0;
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
}
|
if &sig_sl[..32] == msg_sl && sig_sl[32..] == (*pk).0[0..32] {
|
||||||
}
|
|
||||||
if (*sig).0[32..64] != (*pk).0[0..32] {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets sig to msg32||sk
|
/// Sets sig to msg32||pk[..32]
|
||||||
pub unsafe fn secp256k1_ecdsa_sign(cx: *const Context,
|
pub unsafe fn secp256k1_ecdsa_sign(cx: *const Context,
|
||||||
sig: *mut Signature,
|
sig: *mut Signature,
|
||||||
msg32: *const c_uchar,
|
msg32: *const c_uchar,
|
||||||
|
@ -896,274 +699,66 @@ mod fuzz_dummy {
|
||||||
_noncefn: NonceFn,
|
_noncefn: NonceFn,
|
||||||
_noncedata: *const c_void)
|
_noncedata: *const c_void)
|
||||||
-> c_int {
|
-> c_int {
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
// Check context is built for signing (and compute pk)
|
||||||
assert!((*cx).0 as u32 & SECP256K1_START_SIGN == SECP256K1_START_SIGN);
|
let mut new_pk = PublicKey::new();
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
if secp256k1_ec_pubkey_create(cx, &mut new_pk, sk) != 1 {
|
||||||
ptr::copy(msg32, (*sig).0[0..32].as_mut_ptr(), 32);
|
return 0;
|
||||||
ptr::copy(sk, (*sig).0[32..64].as_mut_ptr(), 32);
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
// EC
|
|
||||||
/// Checks that pk != 0xffff...ffff and pk[0..32] == pk[32..64]
|
|
||||||
pub unsafe fn test_pk_validate(cx: *const Context,
|
|
||||||
pk: *const PublicKey) -> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if (*pk).0[0..32] != (*pk).0[32..64] || secp256k1_ec_seckey_verify(cx, (*pk).0[0..32].as_ptr()) == 0 {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
}
|
||||||
}
|
// Sign
|
||||||
|
let sig_sl = slice::from_raw_parts_mut(sig as *mut u8, 64);
|
||||||
/// Checks that sk != 0xffff...ffff
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
pub unsafe fn secp256k1_ec_seckey_verify(cx: *const Context,
|
sig_sl[..32].copy_from_slice(msg_sl);
|
||||||
sk: *const c_uchar) -> c_int {
|
sig_sl[32..].copy_from_slice(&new_pk.0[..32]);
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
let mut res = 0;
|
|
||||||
for i in 0..32 {
|
|
||||||
if *sk.offset(i as isize) != 0xff { res = 1 };
|
|
||||||
}
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets pk to sk||sk
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_create(cx: *const Context, pk: *mut PublicKey,
|
|
||||||
sk: *const c_uchar) -> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
|
||||||
ptr::copy(sk, (*pk).0[0..32].as_mut_ptr(), 32);
|
|
||||||
ptr::copy(sk, (*pk).0[32..64].as_mut_ptr(), 32);
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO secp256k1_ec_privkey_export
|
/// Verifies that sig is msg32||pk[32..]
|
||||||
//TODO secp256k1_ec_privkey_import
|
|
||||||
|
|
||||||
#[deprecated(since = "0.2.0",note = "Please use the secp256k1_ec_seckey_negate function instead")]
|
|
||||||
pub unsafe fn secp256k1_ec_privkey_negate(cx: *const Context,
|
|
||||||
sk: *mut c_uchar) -> c_int {
|
|
||||||
secp256k1_ec_seckey_negate(cx, sk)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ec_seckey_negate(cx: *const Context,
|
|
||||||
sk: *mut c_uchar) -> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_negate(cx: *const Context,
|
|
||||||
pk: *mut PublicKey) -> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if test_pk_validate(cx, pk) != 1 { return 0; }
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies the first 16 bytes of tweak into the last 16 bytes of sk
|
|
||||||
pub unsafe fn secp256k1_ec_privkey_tweak_add(cx: *const Context,
|
|
||||||
sk: *mut c_uchar,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
secp256k1_ec_seckey_tweak_add(cx, sk, tweak)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ec_seckey_tweak_add(cx: *const Context,
|
|
||||||
sk: *mut c_uchar,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
|
||||||
ptr::copy(tweak.offset(16), sk.offset(16), 16);
|
|
||||||
*sk.offset(24) = 0x7f; // Ensure sk remains valid no matter what tweak was
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The PublicKey equivalent of secp256k1_ec_privkey_tweak_add
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_tweak_add(cx: *const Context,
|
|
||||||
pk: *mut PublicKey,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if test_pk_validate(cx, pk) != 1 { return 0; }
|
|
||||||
ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16);
|
|
||||||
ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16);
|
|
||||||
(*pk).0[24] = 0x7f; // Ensure pk remains valid no matter what tweak was
|
|
||||||
(*pk).0[24+32] = 0x7f; // Ensure pk remains valid no matter what tweak was
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies the last 16 bytes of tweak into the last 16 bytes of sk
|
|
||||||
pub unsafe fn secp256k1_ec_privkey_tweak_mul(cx: *const Context,
|
|
||||||
sk: *mut c_uchar,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
secp256k1_ec_seckey_tweak_mul(cx, sk, tweak)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copies the last 16 bytes of tweak into the last 16 bytes of sk
|
|
||||||
pub unsafe fn secp256k1_ec_seckey_tweak_mul(cx: *const Context,
|
|
||||||
sk: *mut c_uchar,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
|
||||||
ptr::copy(tweak.offset(16), sk.offset(16), 16);
|
|
||||||
*sk.offset(24) = 0x00; // Ensure sk remains valid no matter what tweak was
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The PublicKey equivalent of secp256k1_ec_privkey_tweak_mul
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_tweak_mul(cx: *const Context,
|
|
||||||
pk: *mut PublicKey,
|
|
||||||
tweak: *const c_uchar)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if test_pk_validate(cx, pk) != 1 { return 0; }
|
|
||||||
ptr::copy(tweak.offset(16), (*pk).0[16..32].as_mut_ptr(), 16);
|
|
||||||
ptr::copy(tweak.offset(16), (*pk).0[16+32..64].as_mut_ptr(), 16);
|
|
||||||
(*pk).0[24] = 0x00; // Ensure pk remains valid no matter what tweak was
|
|
||||||
(*pk).0[24+32] = 0x00; // Ensure pk remains valid no matter what tweak was
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ec_pubkey_combine(cx: *const Context,
|
|
||||||
out: *mut PublicKey,
|
|
||||||
ins: *const *const PublicKey,
|
|
||||||
n: c_int)
|
|
||||||
-> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
assert!(n <= 32 && n >= 0); //TODO: Remove this restriction?
|
|
||||||
for i in 0..n {
|
|
||||||
if test_pk_validate(cx, *ins.offset(i as isize)) != 1 { return 0; }
|
|
||||||
(*out).0[(i*32/n) as usize..((i+1)*32/n) as usize].copy_from_slice(&(**ins.offset(i as isize)).0[(i*32/n) as usize..((i+1)*32/n) as usize]);
|
|
||||||
}
|
|
||||||
ptr::copy((*out).0[0..32].as_ptr(), (*out).0[32..64].as_mut_ptr(), 32);
|
|
||||||
(*out).0[24] = 0x7f; // pk should always be valid
|
|
||||||
(*out).0[24+32] = 0x7f; // pk should always be valid
|
|
||||||
test_pk_validate(cx, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets out to point[0..16]||scalar[0..16]
|
|
||||||
pub unsafe fn secp256k1_ecdh(
|
|
||||||
cx: *const Context,
|
|
||||||
out: *mut c_uchar,
|
|
||||||
point: *const PublicKey,
|
|
||||||
scalar: *const c_uchar,
|
|
||||||
_hashfp: EcdhHashFn,
|
|
||||||
_data: *mut c_void,
|
|
||||||
) -> c_int {
|
|
||||||
assert!(!cx.is_null() && (*cx).0 as u32 & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, scalar) != 1 { return 0; }
|
|
||||||
|
|
||||||
let mut scalar_prefix = [0; 16];
|
|
||||||
ptr::copy(scalar, scalar_prefix[..].as_mut_ptr(), 16);
|
|
||||||
|
|
||||||
if (*point).0[0..16] > scalar_prefix[0..16] {
|
|
||||||
ptr::copy((*point).as_ptr(), out, 16);
|
|
||||||
ptr::copy(scalar, out.offset(16), 16);
|
|
||||||
} else {
|
|
||||||
ptr::copy(scalar, out, 16);
|
|
||||||
ptr::copy((*point).as_ptr(), out.offset(16), 16);
|
|
||||||
}
|
|
||||||
(*out.offset(16)) = 0x00; // result should always be a valid secret key
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_schnorrsig_sign(
|
|
||||||
_cx: *const Context,
|
|
||||||
_sig: *mut c_uchar,
|
|
||||||
_msg32: *const c_uchar,
|
|
||||||
_keypair: *const KeyPair,
|
|
||||||
_noncefp: SchnorrNonceFn,
|
|
||||||
_noncedata: *const c_void
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_schnorrsig_verify(
|
pub unsafe fn secp256k1_schnorrsig_verify(
|
||||||
_cx: *const Context,
|
cx: *const Context,
|
||||||
_sig64: *const c_uchar,
|
sig64: *const c_uchar,
|
||||||
_msg32: *const c_uchar,
|
msg32: *const c_uchar,
|
||||||
_pubkey: *const XOnlyPublicKey,
|
pubkey: *const XOnlyPublicKey,
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
unimplemented!();
|
// Check context is built for verification
|
||||||
|
let mut new_pk = PublicKey::new();
|
||||||
|
let _ = secp256k1_xonly_pubkey_tweak_add(cx, &mut new_pk, pubkey, msg32);
|
||||||
|
// Actually verify
|
||||||
|
let sig_sl = slice::from_raw_parts(sig64 as *const u8, 64);
|
||||||
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
|
if &sig_sl[..32] == msg_sl && sig_sl[32..] == (*pubkey).0[..32] {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn secp256k1_xonly_pubkey_parse(
|
/// Sets sig to msg32||pk[..32]
|
||||||
_cx: *const Context,
|
pub unsafe fn secp256k1_schnorrsig_sign(
|
||||||
_pubkey: *mut XOnlyPublicKey,
|
cx: *const Context,
|
||||||
_input32: *const c_uchar,
|
sig64: *mut c_uchar,
|
||||||
|
msg32: *const c_uchar,
|
||||||
|
keypair: *const KeyPair,
|
||||||
|
noncefp: SchnorrNonceFn,
|
||||||
|
noncedata: *const c_void
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
unimplemented!();
|
// Check context is built for signing
|
||||||
}
|
let mut new_kp = KeyPair::new();
|
||||||
|
if secp256k1_keypair_create(cx, &mut new_kp, (*keypair).0.as_ptr()) != 1 {
|
||||||
pub fn secp256k1_xonly_pubkey_serialize(
|
return 0;
|
||||||
_cx: *const Context,
|
}
|
||||||
_output32: *mut c_uchar,
|
assert_eq!(new_kp, *keypair);
|
||||||
_pubkey: *const XOnlyPublicKey,
|
// Sign
|
||||||
) -> c_int {
|
let sig_sl = slice::from_raw_parts_mut(sig64 as *mut u8, 64);
|
||||||
unimplemented!();
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
}
|
sig_sl[..32].copy_from_slice(msg_sl);
|
||||||
|
sig_sl[32..].copy_from_slice(&new_kp.0[32..64]);
|
||||||
pub unsafe fn secp256k1_xonly_pubkey_from_pubkey(
|
1
|
||||||
_cx: *const Context,
|
|
||||||
_xonly_pubkey: *mut XOnlyPublicKey,
|
|
||||||
_pk_parity: *mut c_int,
|
|
||||||
_pubkey: *const PublicKey,
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_keypair_create(
|
|
||||||
_cx: *const Context,
|
|
||||||
_keypair: *mut KeyPair,
|
|
||||||
_seckey: *const c_uchar,
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_xonly_pubkey_tweak_add(
|
|
||||||
_cx: *const Context,
|
|
||||||
_output_pubkey: *mut PublicKey,
|
|
||||||
_internal_pubkey: *const XOnlyPublicKey,
|
|
||||||
_tweak32: *const c_uchar,
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_keypair_xonly_pub(
|
|
||||||
_cx: *const Context,
|
|
||||||
_pubkey: *mut XOnlyPublicKey,
|
|
||||||
_pk_parity: *mut c_int,
|
|
||||||
_keypair: *const KeyPair
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_keypair_xonly_tweak_add(
|
|
||||||
_cx: *const Context,
|
|
||||||
_keypair: *mut KeyPair,
|
|
||||||
_tweak32: *const c_uchar,
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_xonly_pubkey_tweak_add_check(
|
|
||||||
_cx: *const Context,
|
|
||||||
_tweaked_pubkey32: *const c_uchar,
|
|
||||||
_tweaked_pubkey_parity: c_int,
|
|
||||||
_internal_pubkey: *const XOnlyPublicKey,
|
|
||||||
_tweak32: *const c_uchar,
|
|
||||||
) -> c_int {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(rust_secp_fuzz)]
|
#[cfg(rust_secp_fuzz)]
|
||||||
pub use self::fuzz_dummy::*;
|
pub use self::fuzz_dummy::*;
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
//! # FFI of the recovery module
|
//! # FFI of the recovery module
|
||||||
|
|
||||||
use ::types::*;
|
use ::types::*;
|
||||||
#[cfg(not(rust_secp_fuzz))]
|
use {Context, Signature, NonceFn, PublicKey};
|
||||||
use ::{Context, Signature, NonceFn, PublicKey};
|
|
||||||
|
|
||||||
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
/// Library-internal representation of a Secp256k1 signature + recovery ID
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -36,7 +35,6 @@ impl Default for RecoverableSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(rust_secp_fuzz))]
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_recoverable_signature_parse_compact")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_recoverable_signature_parse_compact")]
|
||||||
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature,
|
pub fn secp256k1_ecdsa_recoverable_signature_parse_compact(cx: *const Context, sig: *mut RecoverableSignature,
|
||||||
|
@ -52,6 +50,10 @@ extern "C" {
|
||||||
pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature,
|
pub fn secp256k1_ecdsa_recoverable_signature_convert(cx: *const Context, sig: *mut Signature,
|
||||||
input: *const RecoverableSignature)
|
input: *const RecoverableSignature)
|
||||||
-> c_int;
|
-> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(rust_secp_fuzz))]
|
||||||
|
extern "C" {
|
||||||
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign_recoverable")]
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_3_1_ecdsa_sign_recoverable")]
|
||||||
pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context,
|
pub fn secp256k1_ecdsa_sign_recoverable(cx: *const Context,
|
||||||
sig: *mut RecoverableSignature,
|
sig: *mut RecoverableSignature,
|
||||||
|
@ -72,58 +74,76 @@ extern "C" {
|
||||||
|
|
||||||
#[cfg(rust_secp_fuzz)]
|
#[cfg(rust_secp_fuzz)]
|
||||||
mod fuzz_dummy {
|
mod fuzz_dummy {
|
||||||
extern crate std;
|
use super::*;
|
||||||
use self::std::ptr;
|
use std::slice;
|
||||||
use super::RecoverableSignature;
|
|
||||||
use types::*;
|
|
||||||
use ::{Signature, Context, PublicKey, NonceFn, secp256k1_ec_seckey_verify,
|
|
||||||
SECP256K1_START_NONE, SECP256K1_START_VERIFY, SECP256K1_START_SIGN};
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ecdsa_recoverable_signature_parse_compact(_cx: *const Context, _sig: *mut RecoverableSignature,
|
use secp256k1_ec_pubkey_create;
|
||||||
_input64: *const c_uchar, _recid: c_int)
|
use secp256k1_ec_pubkey_parse;
|
||||||
-> c_int {
|
use secp256k1_ec_pubkey_serialize;
|
||||||
unimplemented!();
|
use SECP256K1_SER_COMPRESSED;
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ecdsa_recoverable_signature_serialize_compact(_cx: *const Context, _output64: *mut c_uchar,
|
/// Sets sig to msg32||full pk
|
||||||
_recid: *mut c_int, _sig: *const RecoverableSignature)
|
pub unsafe fn secp256k1_ecdsa_sign_recoverable(
|
||||||
-> c_int {
|
cx: *const Context,
|
||||||
unimplemented!();
|
sig: *mut RecoverableSignature,
|
||||||
}
|
msg32: *const c_uchar,
|
||||||
|
sk: *const c_uchar,
|
||||||
pub unsafe fn secp256k1_ecdsa_recoverable_signature_convert(_cx: *const Context, _sig: *mut Signature,
|
_noncefn: NonceFn,
|
||||||
_input: *const RecoverableSignature)
|
_noncedata: *const c_void,
|
||||||
-> c_int {
|
) -> c_int {
|
||||||
unimplemented!();
|
// Check context is built for signing (and compute pk)
|
||||||
}
|
let mut new_pk = PublicKey::new();
|
||||||
|
if secp256k1_ec_pubkey_create(cx, &mut new_pk, sk) != 1 {
|
||||||
/// Sets sig to (2|3)||msg32||sk
|
return 0;
|
||||||
pub unsafe 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 {
|
|
||||||
assert!(!cx.is_null() && (*cx).flags() & !(SECP256K1_START_NONE | SECP256K1_START_VERIFY | SECP256K1_START_SIGN) == 0);
|
|
||||||
assert!((*cx).flags() & SECP256K1_START_SIGN == SECP256K1_START_SIGN);
|
|
||||||
if secp256k1_ec_seckey_verify(cx, sk) != 1 { return 0; }
|
|
||||||
if *sk.offset(0) > 0x7f {
|
|
||||||
(*sig).0[0] = 2;
|
|
||||||
} else {
|
|
||||||
(*sig).0[0] = 3;
|
|
||||||
}
|
}
|
||||||
ptr::copy(msg32, (*sig).0[1..33].as_mut_ptr(), 32);
|
// Sign
|
||||||
ptr::copy(sk, (*sig).0[33..65].as_mut_ptr(), 32);
|
let sig_sl = slice::from_raw_parts_mut(sig as *mut u8, 65);
|
||||||
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
|
sig_sl[..32].copy_from_slice(msg_sl);
|
||||||
|
let mut out_len: size_t = 33;
|
||||||
|
secp256k1_ec_pubkey_serialize(cx, sig_sl[32..].as_mut_ptr(), &mut out_len, &new_pk, SECP256K1_SER_COMPRESSED);
|
||||||
|
// Encode the parity of the pubkey in the final byte as 0/1,
|
||||||
|
// which is the same encoding (though the parity is computed
|
||||||
|
// differently) as real recoverable signatures.
|
||||||
|
sig_sl.swap(32, 64);
|
||||||
|
sig_sl[64] -= 2;
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn secp256k1_ecdsa_recover(_cx: *const Context,
|
pub unsafe fn secp256k1_ecdsa_recover(
|
||||||
_pk: *mut PublicKey,
|
cx: *const Context,
|
||||||
_sig: *const RecoverableSignature,
|
pk: *mut PublicKey,
|
||||||
_msg32: *const c_uchar)
|
sig: *const RecoverableSignature,
|
||||||
-> c_int {
|
msg32: *const c_uchar
|
||||||
unimplemented!();
|
) -> c_int {
|
||||||
|
let sig_sl = slice::from_raw_parts(sig as *const u8, 65);
|
||||||
|
let msg_sl = slice::from_raw_parts(msg32 as *const u8, 32);
|
||||||
|
|
||||||
|
if sig_sl[64] >= 4 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Pull the original pk out of the siganture
|
||||||
|
let mut pk_ser = [0; 33];
|
||||||
|
pk_ser.copy_from_slice(&sig_sl[32..]);
|
||||||
|
pk_ser.swap(0, 32);
|
||||||
|
pk_ser[0] += 2;
|
||||||
|
// Check that it parses (in a real sig, this would be the R value,
|
||||||
|
// so it is actually required to be a valid point)
|
||||||
|
if secp256k1_ec_pubkey_parse(cx, pk, pk_ser.as_ptr(), 33) == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Munge it up so that a different message will give a different pk
|
||||||
|
for i in 0..32 {
|
||||||
|
pk_ser[i + 1] ^= sig_sl[i] ^ msg_sl[i];
|
||||||
|
}
|
||||||
|
// If any munging happened, this will fail parsing half the time, so
|
||||||
|
// tweak-and-loop until we find a key that works.
|
||||||
|
let mut idx = 0;
|
||||||
|
while secp256k1_ec_pubkey_parse(cx, pk, pk_ser.as_ptr(), 33) == 0 {
|
||||||
|
pk_ser[1 + idx / 8] ^= 1 << (idx % 8);
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(rust_secp_fuzz)]
|
#[cfg(rust_secp_fuzz)]
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl SharedSecret {
|
||||||
xy.as_mut_ptr(),
|
xy.as_mut_ptr(),
|
||||||
point.as_ptr(),
|
point.as_ptr(),
|
||||||
scalar.as_ptr(),
|
scalar.as_ptr(),
|
||||||
c_callback,
|
Some(c_callback),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -103,6 +103,7 @@
|
||||||
//! 0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2,
|
//! 0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2,
|
||||||
//! ]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes");
|
//! ]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes");
|
||||||
//!
|
//!
|
||||||
|
//! # #[cfg(not(rust_secp_fuzz))]
|
||||||
//! assert!(secp.verify(&message, &sig, &public_key).is_ok());
|
//! assert!(secp.verify(&message, &sig, &public_key).is_ok());
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
@ -735,6 +736,10 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
entropy_p = extra_entropy.as_ptr() as *const ffi::types::c_void;
|
entropy_p = extra_entropy.as_ptr() as *const ffi::types::c_void;
|
||||||
|
|
||||||
|
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
|
||||||
|
#[cfg(rust_secp_fuzz)]
|
||||||
|
return Signature::from(ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1097,9 +1102,12 @@ mod tests {
|
||||||
if compact[0] < 0x80 {
|
if compact[0] < 0x80 {
|
||||||
assert_eq!(sig, low_r_sig);
|
assert_eq!(sig, low_r_sig);
|
||||||
} else {
|
} else {
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs
|
||||||
assert_ne!(sig, low_r_sig);
|
assert_ne!(sig, low_r_sig);
|
||||||
}
|
}
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs
|
||||||
assert!(super::compact_sig_has_zero_first_bit(&low_r_sig.0));
|
assert!(super::compact_sig_has_zero_first_bit(&low_r_sig.0));
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // mocked sig generation doesn't produce low-R sigs
|
||||||
assert!(super::der_length_check(&grind_r_sig.0, 70));
|
assert!(super::der_length_check(&grind_r_sig.0, 70));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1172,6 +1180,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
fn test_low_s() {
|
fn test_low_s() {
|
||||||
// nb this is a transaction on testnet
|
// nb this is a transaction on testnet
|
||||||
// txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9
|
// txid 8ccc87b72d766ab3128f03176bb1c98293f2d1f85ebfaf07b82cc81ea6891fa9
|
||||||
|
@ -1193,6 +1202,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fuzz-sigs have fixed size/format
|
||||||
fn test_low_r() {
|
fn test_low_r() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
||||||
|
@ -1207,6 +1217,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fuzz-sigs have fixed size/format
|
||||||
fn test_grind_r() {
|
fn test_grind_r() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
|
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
|
||||||
|
@ -1220,6 +1231,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[test]
|
#[test]
|
||||||
fn test_signature_serde() {
|
fn test_signature_serde() {
|
||||||
use serde_test::{Configure, Token, assert_tokens};
|
use serde_test::{Configure, Token, assert_tokens};
|
||||||
|
|
|
@ -235,6 +235,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
fn sign() {
|
fn sign() {
|
||||||
let mut s = Secp256k1::new();
|
let mut s = Secp256k1::new();
|
||||||
s.randomize(&mut thread_rng());
|
s.randomize(&mut thread_rng());
|
||||||
|
|
|
@ -561,6 +561,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
fn test_schnorrsig_sign() {
|
fn test_schnorrsig_sign() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -582,6 +583,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
fn test_schnorrsig_verify() {
|
fn test_schnorrsig_verify() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -720,6 +722,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
#[cfg(not(rust_secp_fuzz))] // fixed sig vectors can't work with fuzz-sigs
|
||||||
#[test]
|
#[test]
|
||||||
fn test_signature_serde() {
|
fn test_signature_serde() {
|
||||||
use serde_test::{assert_tokens, Configure, Token};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
Loading…
Reference in New Issue