Merge rust-bitcoin/rust-secp256k1#499: Introduce `rustfmt`

e0e575dde7 Run cargo fmt (Tobin C. Harding)
41449e455d Prepare codebase for formatting (Tobin C. Harding)
7e3c8935b6 Introduce rustfmt config file (Tobin C. Harding)

Pull request description:

  (Includes the patch from #504, I pulled it out of this to merge faster)

  Introduce `rustfmt` by doing:

  - Copy the `rustfmt` config file from `rust-bitcoin`
  - Prepare the codebase by adding `#[rustfmt::skip]` as needed and doing some manual format improvements.
  - Run the formatter: `cargo +nightly fmt`
  - Add formatting checks to CI and the pre-commit hook

  Thanks in advance for doing the painful review on patch 3.

ACKs for top commit:
  apoelstra:
    ACK e0e575dde7

Tree-SHA512: 1b6fdbaf81480c0446e660cc3f6ab7ac0697f272187f6fdfd6b95d894a418cde8cf1c423f1d18ebbe03ac5c43489630a35ad07912afaeb6107cfbe7338a9bed7
This commit is contained in:
Andrew Poelstra 2022-11-17 14:57:53 +00:00
commit a777942da1
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
17 changed files with 846 additions and 756 deletions

View File

@ -2,9 +2,14 @@ extern crate bitcoin_hashes;
extern crate secp256k1; extern crate secp256k1;
use bitcoin_hashes::{sha256, Hash}; use bitcoin_hashes::{sha256, Hash};
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, ecdsa, Signing, Verification}; use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
fn verify<C: Verification>(secp: &Secp256k1<C>, msg: &[u8], sig: [u8; 64], pubkey: [u8; 33]) -> Result<bool, Error> { fn verify<C: Verification>(
secp: &Secp256k1<C>,
msg: &[u8],
sig: [u8; 64],
pubkey: [u8; 33],
) -> Result<bool, Error> {
let msg = sha256::Hash::hash(msg); let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?; let msg = Message::from_slice(&msg)?;
let sig = ecdsa::Signature::from_compact(&sig)?; let sig = ecdsa::Signature::from_compact(&sig)?;
@ -13,7 +18,11 @@ fn verify<C: Verification>(secp: &Secp256k1<C>, msg: &[u8], sig: [u8; 64], pubke
Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok()) Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok())
} }
fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::Signature, Error> { fn sign<C: Signing>(
secp: &Secp256k1<C>,
msg: &[u8],
seckey: [u8; 32],
) -> Result<ecdsa::Signature, Error> {
let msg = sha256::Hash::hash(msg); let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?; let msg = Message::from_slice(&msg)?;
let seckey = SecretKey::from_slice(&seckey)?; let seckey = SecretKey::from_slice(&seckey)?;
@ -23,8 +32,14 @@ fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result
fn main() { fn main() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let seckey = [59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28]; let seckey = [
let pubkey = [2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54]; 59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253,
102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
];
let pubkey = [
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141,
134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
];
let msg = b"This is some message"; let msg = b"This is some message";
let signature = sign(&secp, msg, seckey).unwrap(); let signature = sign(&secp, msg, seckey).unwrap();

View File

@ -1,11 +1,15 @@
extern crate bitcoin_hashes; extern crate bitcoin_hashes;
extern crate secp256k1; extern crate secp256k1;
use bitcoin_hashes::{sha256, Hash}; use bitcoin_hashes::{sha256, Hash};
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification, ecdsa}; use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
fn recover<C: Verification>(secp: &Secp256k1<C>,msg: &[u8],sig: [u8; 64],recovery_id: u8) -> Result<PublicKey, Error> { fn recover<C: Verification>(
secp: &Secp256k1<C>,
msg: &[u8],
sig: [u8; 64],
recovery_id: u8,
) -> Result<PublicKey, Error> {
let msg = sha256::Hash::hash(msg); let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?; let msg = Message::from_slice(&msg)?;
let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?; let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?;
@ -14,7 +18,11 @@ fn recover<C: Verification>(secp: &Secp256k1<C>,msg: &[u8],sig: [u8; 64],recover
secp.recover_ecdsa(&msg, &sig) secp.recover_ecdsa(&msg, &sig)
} }
fn sign_recovery<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::RecoverableSignature, Error> { fn sign_recovery<C: Signing>(
secp: &Secp256k1<C>,
msg: &[u8],
seckey: [u8; 32],
) -> Result<ecdsa::RecoverableSignature, Error> {
let msg = sha256::Hash::hash(msg); let msg = sha256::Hash::hash(msg);
let msg = Message::from_slice(&msg)?; let msg = Message::from_slice(&msg)?;
let seckey = SecretKey::from_slice(&seckey)?; let seckey = SecretKey::from_slice(&seckey)?;
@ -25,22 +33,19 @@ fn main() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let seckey = [ let seckey = [
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253,
94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
]; ];
let pubkey = PublicKey::from_slice(&[ let pubkey = PublicKey::from_slice(&[
2, 2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141,
29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54, ])
]).unwrap(); .unwrap();
let msg = b"This is some message"; let msg = b"This is some message";
let signature = sign_recovery(&secp, msg, seckey).unwrap(); let signature = sign_recovery(&secp, msg, seckey).unwrap();
let (recovery_id, serialize_sig) = signature.serialize_compact(); let (recovery_id, serialize_sig) = signature.serialize_compact();
assert_eq!( assert_eq!(recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8), Ok(pubkey));
recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8),
Ok(pubkey)
);
} }

View File

@ -1 +1,82 @@
disable_all_formatting = true # Eventually this shoud be: ignore = []
ignore = [
"secp256k1-sys"
]
hard_tabs = false
tab_spaces = 4
newline_style = "Auto"
indent_style = "Block"
max_width = 100 # This is number of characters.
# `use_small_heuristics` is ignored if the granular width config values are explicitly set.
use_small_heuristics = "Max" # "Max" == All granular width settings same as `max_width`.
# # Granular width configuration settings. These are percentages of `max_width`.
# fn_call_width = 60
# attr_fn_like_width = 70
# struct_lit_width = 18
# struct_variant_width = 35
# array_width = 60
# chain_width = 60
# single_line_if_else_max_width = 50
wrap_comments = false
format_code_in_doc_comments = false
comment_width = 100 # Default 80
normalize_comments = false
normalize_doc_attributes = false
format_strings = false
format_macro_matchers = false
format_macro_bodies = true
hex_literal_case = "Preserve"
empty_item_single_line = true
struct_lit_single_line = true
fn_single_line = true # Default false
where_single_line = false
imports_indent = "Block"
imports_layout = "Mixed"
imports_granularity = "Module" # Default "Preserve"
group_imports = "StdExternalCrate" # Default "Preserve"
reorder_imports = true
reorder_modules = true
reorder_impl_items = false
type_punctuation_density = "Wide"
space_before_colon = false
space_after_colon = true
spaces_around_ranges = false
binop_separator = "Front"
remove_nested_parens = true
combine_control_expr = true
overflow_delimited_expr = false
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_blocks = false # Default true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
fn_args_layout = "Tall"
brace_style = "SameLineWhere"
control_brace_style = "AlwaysSameLine"
trailing_semicolon = true
trailing_comma = "Vertical"
match_block_trailing_comma = false
blank_lines_upper_bound = 1
blank_lines_lower_bound = 0
edition = "2018"
version = "One"
inline_attribute_width = 0
format_generated_files = true
merge_derives = true
use_try_shorthand = false
use_field_init_shorthand = false
force_explicit_abi = true
condense_wildcard_suffixes = false
color = "Auto"
required_version = "1.5.1"
unstable_features = false
disable_all_formatting = false
skip_children = false
hide_parse_errors = false
error_on_line_overflow = false
error_on_unformatted = false
emit_mode = "Files"
make_backup = false

View File

@ -44,6 +44,7 @@ pub const SCHNORR_PUBLIC_KEY_SIZE: usize = 32;
pub const KEY_PAIR_SIZE: usize = 96; pub const KEY_PAIR_SIZE: usize = 96;
/// The Prime for the secp256k1 field element. /// The Prime for the secp256k1 field element.
#[rustfmt::skip]
pub const FIELD_SIZE: [u8; 32] = [ pub const FIELD_SIZE: [u8; 32] = [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -52,6 +53,7 @@ pub const FIELD_SIZE: [u8; 32] = [
]; ];
/// The order of the secp256k1 curve. /// The order of the secp256k1 curve.
#[rustfmt::skip]
pub const CURVE_ORDER: [u8; 32] = [ pub const CURVE_ORDER: [u8; 32] = [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
@ -60,6 +62,7 @@ pub const CURVE_ORDER: [u8; 32] = [
]; ];
/// The X coordinate of the generator. /// The X coordinate of the generator.
#[rustfmt::skip]
pub const GENERATOR_X: [u8; 32] = [ pub const GENERATOR_X: [u8; 32] = [
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
@ -68,6 +71,7 @@ pub const GENERATOR_X: [u8; 32] = [
]; ];
/// The Y coordinate of the generator. /// The Y coordinate of the generator.
#[rustfmt::skip]
pub const GENERATOR_Y: [u8; 32] = [ pub const GENERATOR_Y: [u8; 32] = [
0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,

View File

@ -1,13 +1,12 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::ManuallyDrop; use core::mem::ManuallyDrop;
use crate::{Error, Secp256k1};
use crate::ffi::{self, CPtr, types::AlignedType};
use crate::ffi::types::{c_uint, c_void};
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
pub use self::alloc_only::*; pub use self::alloc_only::*;
use crate::ffi::types::{c_uint, c_void, AlignedType};
use crate::ffi::{self, CPtr};
use crate::{Error, Secp256k1};
#[cfg(all(feature = "global-context", feature = "std"))] #[cfg(all(feature = "global-context", feature = "std"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))] #[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))]
@ -41,13 +40,17 @@ pub mod global {
impl Deref for GlobalContext { impl Deref for GlobalContext {
type Target = Secp256k1<All>; type Target = Secp256k1<All>;
#[allow(unused_mut)] // Unused when `rand-std` is not enabled. #[allow(unused_mut)] // Unused when `rand-std` is not enabled.
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
static ONCE: Once = Once::new(); static ONCE: Once = Once::new();
static mut CONTEXT: Option<Secp256k1<All>> = None; static mut CONTEXT: Option<Secp256k1<All>> = None;
ONCE.call_once(|| unsafe { ONCE.call_once(|| unsafe {
let mut ctx = Secp256k1::new(); let mut ctx = Secp256k1::new();
#[cfg(all(not(target_arch = "wasm32"), feature = "rand-std", not(feature = "global-context-less-secure")))] #[cfg(all(
not(target_arch = "wasm32"),
feature = "rand-std",
not(feature = "global-context-less-secure")
))]
{ {
ctx.randomize(&mut rand::thread_rng()); ctx.randomize(&mut rand::thread_rng());
} }
@ -58,10 +61,9 @@ pub mod global {
} }
} }
/// A trait for all kinds of contexts that lets you define the exact flags and a function to /// A trait for all kinds of contexts that lets you define the exact flags and a function to
/// deallocate memory. It isn't possible to implement this for types outside this crate. /// deallocate memory. It isn't possible to implement this for types outside this crate.
pub unsafe trait Context : private::Sealed { pub unsafe trait Context: private::Sealed {
/// Flags for the ffi. /// Flags for the ffi.
const FLAGS: c_uint; const FLAGS: c_uint;
/// A constant description of the context. /// A constant description of the context.
@ -106,13 +108,13 @@ mod private {
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))] #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
mod alloc_only { mod alloc_only {
use crate::alloc::alloc;
use core::marker::PhantomData; use core::marker::PhantomData;
use super::private; use super::private;
use crate::ffi::{self, types::{c_uint, c_void}}; use crate::alloc::alloc;
use crate::{Secp256k1, Signing, Verification, Context, AlignedType}; use crate::ffi::types::{c_uint, c_void};
use crate::ffi::{self};
use crate::{AlignedType, Context, Secp256k1, Signing, Verification};
impl private::Sealed for SignOnly {} impl private::Sealed for SignOnly {}
impl private::Sealed for All {} impl private::Sealed for All {}
@ -192,16 +194,22 @@ mod alloc_only {
let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) }; let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap(); let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
let ptr = unsafe {alloc::alloc(layout)}; let ptr = unsafe { alloc::alloc(layout) };
#[allow(unused_mut)] // ctx is not mutated under some feature combinations. #[allow(unused_mut)] // ctx is not mutated under some feature combinations.
let mut ctx = Secp256k1 { let mut ctx = Secp256k1 {
ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS) }, ctx: unsafe {
ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS)
},
phantom: PhantomData, phantom: PhantomData,
size, size,
}; };
#[cfg(all(not(target_arch = "wasm32"), feature = "rand-std", not(feature = "global-context-less-secure")))] #[cfg(all(
not(target_arch = "wasm32"),
feature = "rand-std",
not(feature = "global-context-less-secure")
))]
{ {
ctx.randomize(&mut rand::thread_rng()); ctx.randomize(&mut rand::thread_rng());
} }
@ -217,9 +225,7 @@ mod alloc_only {
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`. /// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs /// If `rand-std` feature is not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`). /// for `Secp256k1::gen_new()`).
pub fn new() -> Secp256k1<All> { pub fn new() -> Secp256k1<All> { Secp256k1::gen_new() }
Secp256k1::gen_new()
}
} }
impl Secp256k1<SignOnly> { impl Secp256k1<SignOnly> {
@ -228,9 +234,7 @@ mod alloc_only {
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`. /// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs /// If `rand-std` feature is not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`). /// for `Secp256k1::gen_new()`).
pub fn signing_only() -> Secp256k1<SignOnly> { pub fn signing_only() -> Secp256k1<SignOnly> { Secp256k1::gen_new() }
Secp256k1::gen_new()
}
} }
impl Secp256k1<VerifyOnly> { impl Secp256k1<VerifyOnly> {
@ -239,24 +243,22 @@ mod alloc_only {
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`. /// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs /// If `rand-std` feature is not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`). /// for `Secp256k1::gen_new()`).
pub fn verification_only() -> Secp256k1<VerifyOnly> { pub fn verification_only() -> Secp256k1<VerifyOnly> { Secp256k1::gen_new() }
Secp256k1::gen_new()
}
} }
impl Default for Secp256k1<All> { impl Default for Secp256k1<All> {
fn default() -> Self { fn default() -> Self { Self::new() }
Self::new()
}
} }
impl<C: Context> Clone for Secp256k1<C> { impl<C: Context> Clone for Secp256k1<C> {
fn clone(&self) -> Secp256k1<C> { fn clone(&self) -> Secp256k1<C> {
let size = unsafe {ffi::secp256k1_context_preallocated_clone_size(self.ctx as _)}; let size = unsafe { ffi::secp256k1_context_preallocated_clone_size(self.ctx as _) };
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap(); let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
let ptr = unsafe {alloc::alloc(layout)}; let ptr = unsafe { alloc::alloc(layout) };
Secp256k1 { Secp256k1 {
ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void) }, ctx: unsafe {
ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void)
},
phantom: PhantomData, phantom: PhantomData,
size, size,
} }
@ -310,7 +312,8 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
ctx: unsafe { ctx: unsafe {
ffi::secp256k1_context_preallocated_create( ffi::secp256k1_context_preallocated_create(
buf.as_mut_c_ptr() as *mut c_void, buf.as_mut_c_ptr() as *mut c_void,
C::FLAGS) C::FLAGS,
)
}, },
phantom: PhantomData, phantom: PhantomData,
size: 0, // We don't care about the size because it's the caller responsibility to deallocate. size: 0, // We don't care about the size because it's the caller responsibility to deallocate.
@ -320,13 +323,13 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
impl<'buf> Secp256k1<AllPreallocated<'buf>> { impl<'buf> Secp256k1<AllPreallocated<'buf>> {
/// Creates a new Secp256k1 context with all capabilities /// Creates a new Secp256k1 context with all capabilities
pub fn preallocated_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> { pub fn preallocated_new(
buf: &'buf mut [AlignedType],
) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
Secp256k1::preallocated_gen_new(buf) Secp256k1::preallocated_gen_new(buf)
} }
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context. /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
pub fn preallocate_size() -> usize { pub fn preallocate_size() -> usize { Self::preallocate_size_gen() }
Self::preallocate_size_gen()
}
/// Create a context from a raw context. /// Create a context from a raw context.
/// ///
@ -339,7 +342,9 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
/// * The user must handle the freeing of the context(using the correct functions) by himself. /// * The user must handle the freeing of the context(using the correct functions) by himself.
/// * Violating these may lead to Undefined Behavior. /// * Violating these may lead to Undefined Behavior.
/// ///
pub unsafe fn from_raw_all(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> { pub unsafe fn from_raw_all(
raw_ctx: *mut ffi::Context,
) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
ManuallyDrop::new(Secp256k1 { ManuallyDrop::new(Secp256k1 {
ctx: raw_ctx, ctx: raw_ctx,
phantom: PhantomData, phantom: PhantomData,
@ -350,15 +355,15 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> { impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
/// Creates a new Secp256k1 context that can only be used for signing. /// Creates a new Secp256k1 context that can only be used for signing.
pub fn preallocated_signing_only(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> { pub fn preallocated_signing_only(
buf: &'buf mut [AlignedType],
) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
Secp256k1::preallocated_gen_new(buf) Secp256k1::preallocated_gen_new(buf)
} }
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context. /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
#[inline] #[inline]
pub fn preallocate_signing_size() -> usize { pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() }
Self::preallocate_size_gen()
}
/// Create a context from a raw context. /// Create a context from a raw context.
/// ///
@ -371,7 +376,9 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
/// * The user must handle the freeing of the context(using the correct functions) by himself. /// * The user must handle the freeing of the context(using the correct functions) by himself.
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior. /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
/// ///
pub unsafe fn from_raw_signing_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> { pub unsafe fn from_raw_signing_only(
raw_ctx: *mut ffi::Context,
) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
ManuallyDrop::new(Secp256k1 { ManuallyDrop::new(Secp256k1 {
ctx: raw_ctx, ctx: raw_ctx,
phantom: PhantomData, phantom: PhantomData,
@ -382,15 +389,15 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> { impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
/// Creates a new Secp256k1 context that can only be used for verification /// Creates a new Secp256k1 context that can only be used for verification
pub fn preallocated_verification_only(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> { pub fn preallocated_verification_only(
buf: &'buf mut [AlignedType],
) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
Secp256k1::preallocated_gen_new(buf) Secp256k1::preallocated_gen_new(buf)
} }
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context. /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
#[inline] #[inline]
pub fn preallocate_verification_size() -> usize { pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() }
Self::preallocate_size_gen()
}
/// Create a context from a raw context. /// Create a context from a raw context.
/// ///
@ -403,7 +410,9 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
/// * The user must handle the freeing of the context(using the correct functions) by himself. /// * The user must handle the freeing of the context(using the correct functions) by himself.
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior. /// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
/// ///
pub unsafe fn from_raw_verification_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> { pub unsafe fn from_raw_verification_only(
raw_ctx: *mut ffi::Context,
) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
ManuallyDrop::new(Secp256k1 { ManuallyDrop::new(Secp256k1 {
ctx: raw_ctx, ctx: raw_ctx,
phantom: PhantomData, phantom: PhantomData,

View File

@ -15,11 +15,14 @@
//! Support for shared secret computations. //! Support for shared secret computations.
//! //!
use core::{borrow::Borrow, ptr, str}; use core::borrow::Borrow;
use core::{ptr, str};
use secp256k1_sys::types::{c_int, c_uchar, c_void}; use secp256k1_sys::types::{c_int, c_uchar, c_void};
use crate::{constants, Error, ffi::{self, CPtr}, key::{PublicKey, SecretKey}}; use crate::ffi::{self, CPtr};
use crate::key::{PublicKey, SecretKey};
use crate::{constants, Error};
// The logic for displaying shared secrets relies on this (see `secret.rs`). // The logic for displaying shared secrets relies on this (see `secret.rs`).
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE; const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
@ -51,7 +54,7 @@ impl SharedSecret {
pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret { pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
let mut buf = [0u8; SHARED_SECRET_SIZE]; let mut buf = [0u8; SHARED_SECRET_SIZE];
let res = unsafe { let res = unsafe {
ffi::secp256k1_ecdh( ffi::secp256k1_ecdh(
ffi::secp256k1_context_no_precomp, ffi::secp256k1_context_no_precomp,
buf.as_mut_ptr(), buf.as_mut_ptr(),
point.as_c_ptr(), point.as_c_ptr(),
@ -66,15 +69,11 @@ impl SharedSecret {
/// Returns the shared secret as a byte value. /// Returns the shared secret as a byte value.
#[inline] #[inline]
pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] { pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] { self.0 }
self.0
}
/// Creates a shared secret from `bytes` array. /// Creates a shared secret from `bytes` array.
#[inline] #[inline]
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret { pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret { SharedSecret(bytes) }
SharedSecret(bytes)
}
/// Creates a shared secret from `bytes` slice. /// Creates a shared secret from `bytes` slice.
#[inline] #[inline]
@ -85,7 +84,7 @@ impl SharedSecret {
ret[..].copy_from_slice(bytes); ret[..].copy_from_slice(bytes);
Ok(SharedSecret(ret)) Ok(SharedSecret(ret))
} }
_ => Err(Error::InvalidSharedSecret) _ => Err(Error::InvalidSharedSecret),
} }
} }
} }
@ -96,21 +95,17 @@ impl str::FromStr for SharedSecret {
let mut res = [0u8; SHARED_SECRET_SIZE]; let mut res = [0u8; SHARED_SECRET_SIZE];
match crate::from_hex(s, &mut res) { match crate::from_hex(s, &mut res) {
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)), Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
_ => Err(Error::InvalidSharedSecret) _ => Err(Error::InvalidSharedSecret),
} }
} }
} }
impl Borrow<[u8]> for SharedSecret { impl Borrow<[u8]> for SharedSecret {
fn borrow(&self) -> &[u8] { fn borrow(&self) -> &[u8] { &self.0 }
&self.0
}
} }
impl AsRef<[u8]> for SharedSecret { impl AsRef<[u8]> for SharedSecret {
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] { &self.0 }
&self.0
}
} }
/// Creates a shared point from public key and secret key. /// Creates a shared point from public key and secret key.
@ -162,7 +157,12 @@ pub fn shared_secret_point(point: &PublicKey, scalar: &SecretKey) -> [u8; 64] {
xy xy
} }
unsafe extern "C" fn c_callback(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, _data: *mut c_void) -> c_int { unsafe extern "C" fn c_callback(
output: *mut c_uchar,
x: *const c_uchar,
y: *const c_uchar,
_data: *mut c_void,
) -> c_int {
ptr::copy_nonoverlapping(x, output, 32); ptr::copy_nonoverlapping(x, output, 32);
ptr::copy_nonoverlapping(y, output.offset(32), 32); ptr::copy_nonoverlapping(y, output.offset(32), 32);
1 1
@ -187,12 +187,12 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> { fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() { if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new( d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte SharedSecret" "a hex string representing 32 byte SharedSecret",
)) ))
} else { } else {
d.deserialize_bytes(super::serde_util::BytesVisitor::new( d.deserialize_bytes(super::serde_util::BytesVisitor::new(
"raw 32 bytes SharedSecret", "raw 32 bytes SharedSecret",
SharedSecret::from_slice SharedSecret::from_slice,
)) ))
} }
} }
@ -205,11 +205,11 @@ mod tests {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test; use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::Secp256k1;
use super::SharedSecret; use super::SharedSecret;
use crate::Secp256k1;
#[test] #[test]
#[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))] #[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))]
fn ecdh() { fn ecdh() {
let s = Secp256k1::signing_only(); let s = Secp256k1::signing_only();
let (sk1, pk1) = s.generate_keypair(&mut thread_rng()); let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
@ -227,7 +227,9 @@ mod tests {
let x = [5u8; 32]; let x = [5u8; 32];
let y = [7u8; 32]; let y = [7u8; 32];
let mut output = [0u8; 64]; let mut output = [0u8; 64];
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), core::ptr::null_mut()) }; let res = unsafe {
super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), core::ptr::null_mut())
};
assert_eq!(res, 1); assert_eq!(res, 1);
let mut new_x = [0u8; 32]; let mut new_x = [0u8; 32];
let mut new_y = [0u8; 32]; let mut new_y = [0u8; 32];
@ -239,9 +241,10 @@ mod tests {
#[test] #[test]
#[cfg(not(fuzzing))] #[cfg(not(fuzzing))]
#[cfg(all(feature="std", feature = "rand-std", feature = "bitcoin-hashes-std"))] #[cfg(all(feature = "std", feature = "rand-std", feature = "bitcoin-hashes-std"))]
fn bitcoin_hashes_and_sys_generate_same_secret() { fn bitcoin_hashes_and_sys_generate_same_secret() {
use bitcoin_hashes::{sha256, Hash, HashEngine}; use bitcoin_hashes::{sha256, Hash, HashEngine};
use crate::ecdh::shared_secret_point; use crate::ecdh::shared_secret_point;
let s = Secp256k1::signing_only(); let s = Secp256k1::signing_only();
@ -265,7 +268,8 @@ mod tests {
#[test] #[test]
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))] #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
fn serde() { fn serde() {
use serde_test::{Configure, Token, assert_tokens}; use serde_test::{assert_tokens, Configure, Token};
#[rustfmt::skip]
static BYTES: [u8; 32] = [ static BYTES: [u8; 32] = [
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
@ -288,23 +292,20 @@ mod tests {
#[cfg(bench)] #[cfg(bench)]
mod benches { mod benches {
use test::{Bencher, black_box};
use rand::thread_rng; use rand::thread_rng;
use test::{black_box, Bencher};
use crate::Secp256k1;
use super::SharedSecret; use super::SharedSecret;
use crate::Secp256k1;
#[bench] #[bench]
pub fn bench_ecdh(bh: &mut Bencher) { pub fn bench_ecdh(bh: &mut Bencher) {
let s = Secp256k1::signing_only(); let s = Secp256k1::signing_only();
let (sk, pk) = s.generate_keypair(&mut thread_rng()); let (sk, pk) = s.generate_keypair(&mut thread_rng());
bh.iter( || { bh.iter(|| {
let res = SharedSecret::new(&pk, &sk); let res = SharedSecret::new(&pk, &sk);
black_box(res); black_box(res);
}); });
} }
} }

View File

@ -1,32 +1,28 @@
//! Structs and functionality related to the ECDSA signature algorithm. //! Structs and functionality related to the ECDSA signature algorithm.
use core::{fmt, str, ptr};
use crate::{Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
use crate::ffi::CPtr;
pub mod serialized_signature;
#[cfg(feature = "recovery")] #[cfg(feature = "recovery")]
mod recovery; mod recovery;
pub mod serialized_signature;
use core::{fmt, ptr, str};
#[cfg(feature = "recovery")] #[cfg(feature = "recovery")]
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))] #[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
pub use self::recovery::{RecoveryId, RecoverableSignature}; pub use self::recovery::{RecoverableSignature, RecoveryId};
pub use self::serialized_signature::SerializedSignature;
pub use serialized_signature::SerializedSignature; use crate::ffi::CPtr;
#[cfg(feature = "global-context")] #[cfg(feature = "global-context")]
use crate::SECP256K1; use crate::SECP256K1;
use crate::{
ffi, from_hex, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification,
};
/// An ECDSA signature /// An ECDSA signature
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Signature(pub(crate) ffi::Signature); pub struct Signature(pub(crate) ffi::Signature);
impl fmt::Debug for Signature { impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
fmt::Display::fmt(self, f)
}
} }
impl fmt::Display for Signature { impl fmt::Display for Signature {
@ -51,7 +47,9 @@ impl Signature {
#[inline] #[inline]
/// Converts a DER-encoded byte slice to a signature /// Converts a DER-encoded byte slice to a signature
pub fn from_der(data: &[u8]) -> Result<Signature, Error> { pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
if data.is_empty() {return Err(Error::InvalidSignature);} if data.is_empty() {
return Err(Error::InvalidSignature);
}
unsafe { unsafe {
let mut ret = ffi::Signature::new(); let mut ret = ffi::Signature::new();
@ -72,7 +70,7 @@ impl Signature {
/// Converts a 64-byte compact-encoded byte slice to a signature /// Converts a 64-byte compact-encoded byte slice to a signature
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> { pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
if data.len() != 64 { if data.len() != 64 {
return Err(Error::InvalidSignature) return Err(Error::InvalidSignature);
} }
unsafe { unsafe {
@ -95,7 +93,9 @@ impl Signature {
/// 2016. It should never be used in new applications. This library does not /// 2016. It should never be used in new applications. This library does not
/// support serializing to this "format" /// support serializing to this "format"
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> { pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
if data.is_empty() {return Err(Error::InvalidSignature);} if data.is_empty() {
return Err(Error::InvalidSignature);
}
unsafe { unsafe {
let mut ret = ffi::Signature::new(); let mut ret = ffi::Signature::new();
@ -145,16 +145,15 @@ impl Signature {
/// Obtains a raw pointer suitable for use with FFI functions /// Obtains a raw pointer suitable for use with FFI functions
#[inline] #[inline]
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")] #[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
pub fn as_ptr(&self) -> *const ffi::Signature { pub fn as_ptr(&self) -> *const ffi::Signature { self.as_c_ptr() }
self.as_c_ptr()
}
/// Obtains a raw mutable pointer suitable for use with FFI functions /// Obtains a raw mutable pointer suitable for use with FFI functions
#[inline] #[inline]
#[deprecated(since = "0.25.0", note = "Use Self::as_mut_c_ptr if you need to access the FFI layer")] #[deprecated(
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { since = "0.25.0",
self.as_mut_c_ptr() note = "Use Self::as_mut_c_ptr if you need to access the FFI layer"
} )]
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { self.as_mut_c_ptr() }
#[inline] #[inline]
/// Serializes the signature in DER format /// Serializes the signature in DER format
@ -200,21 +199,15 @@ impl Signature {
impl CPtr for Signature { impl CPtr for Signature {
type Target = ffi::Signature; type Target = ffi::Signature;
fn as_c_ptr(&self) -> *const Self::Target { fn as_c_ptr(&self) -> *const Self::Target { &self.0 }
&self.0
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target { fn as_mut_c_ptr(&mut self) -> *mut Self::Target { &mut self.0 }
&mut self.0
}
} }
/// Creates a new signature from a FFI signature /// Creates a new signature from a FFI signature
impl From<ffi::Signature> for Signature { impl From<ffi::Signature> for Signature {
#[inline] #[inline]
fn from(sig: ffi::Signature) -> Signature { fn from(sig: ffi::Signature) -> Signature { Signature(sig) }
Signature(sig)
}
} }
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -235,12 +228,12 @@ impl<'de> serde::Deserialize<'de> for Signature {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> { fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() { if d.is_human_readable() {
d.deserialize_str(crate::serde_util::FromStrVisitor::new( d.deserialize_str(crate::serde_util::FromStrVisitor::new(
"a hex string representing a DER encoded Signature" "a hex string representing a DER encoded Signature",
)) ))
} else { } else {
d.deserialize_bytes(crate::serde_util::BytesVisitor::new( d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"raw byte stream, that represents a DER encoded Signature", "raw byte stream, that represents a DER encoded Signature",
Signature::from_der Signature::from_der,
)) ))
} }
} }
@ -261,9 +254,17 @@ impl<C: Signing> Secp256k1<C> {
}; };
// We can assume the return value because it's not possible to construct // We can assume the return value because it's not possible to construct
// an invalid signature from a valid `Message` and `SecretKey` // an invalid signature from a valid `Message` and `SecretKey`
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(), assert_eq!(
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979, ffi::secp256k1_ecdsa_sign(
noncedata_ptr), 1); self.ctx,
&mut ret,
msg.as_c_ptr(),
sk.as_c_ptr(),
ffi::secp256k1_nonce_function_rfc6979,
noncedata_ptr
),
1
);
Signature::from(ret) Signature::from(ret)
} }
} }
@ -289,33 +290,43 @@ impl<C: Signing> Secp256k1<C> {
} }
fn sign_grind_with_check( fn sign_grind_with_check(
&self, msg: &Message, &self,
msg: &Message,
sk: &SecretKey, sk: &SecretKey,
check: impl Fn(&ffi::Signature) -> bool) -> Signature { check: impl Fn(&ffi::Signature) -> bool,
let mut entropy_p : *const ffi::types::c_void = ptr::null(); ) -> Signature {
let mut counter : u32 = 0; let mut entropy_p: *const ffi::types::c_void = ptr::null();
let mut extra_entropy = [0u8; 32]; let mut counter: u32 = 0;
loop { let mut extra_entropy = [0u8; 32];
unsafe { loop {
let mut ret = ffi::Signature::new(); unsafe {
// We can assume the return value because it's not possible to construct let mut ret = ffi::Signature::new();
// an invalid signature from a valid `Message` and `SecretKey` // We can assume the return value because it's not possible to construct
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(), // an invalid signature from a valid `Message` and `SecretKey`
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979, assert_eq!(
entropy_p), 1); ffi::secp256k1_ecdsa_sign(
if check(&ret) { self.ctx,
return Signature::from(ret); &mut ret,
} msg.as_c_ptr(),
sk.as_c_ptr(),
counter += 1; ffi::secp256k1_nonce_function_rfc6979,
extra_entropy[..4].copy_from_slice(&counter.to_le_bytes()); entropy_p
entropy_p = extra_entropy.as_c_ptr().cast::<ffi::types::c_void>(); ),
1
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them. );
#[cfg(fuzzing)] if check(&ret) {
return Signature::from(ret); return Signature::from(ret);
} }
counter += 1;
extra_entropy[..4].copy_from_slice(&counter.to_le_bytes());
entropy_p = extra_entropy.as_c_ptr().cast::<ffi::types::c_void>();
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
#[cfg(fuzzing)]
return Signature::from(ret);
} }
}
} }
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce /// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
@ -324,8 +335,13 @@ impl<C: Signing> Secp256k1<C> {
/// of signing operation performed by this function is exponential in the /// of signing operation performed by this function is exponential in the
/// number of bytes grinded. /// number of bytes grinded.
/// Requires a signing capable context. /// Requires a signing capable context.
pub fn sign_ecdsa_grind_r(&self, msg: &Message, sk: &SecretKey, bytes_to_grind: usize) -> Signature { pub fn sign_ecdsa_grind_r(
let len_check = |s : &ffi::Signature| der_length_check(s, 71 - bytes_to_grind); &self,
msg: &Message,
sk: &SecretKey,
bytes_to_grind: usize,
) -> Signature {
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
self.sign_grind_with_check(msg, sk, len_check) self.sign_grind_with_check(msg, sk, len_check)
} }
@ -364,9 +380,16 @@ impl<C: Verification> Secp256k1<C> {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
pub fn verify_ecdsa(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> { pub fn verify_ecdsa(
&self,
msg: &Message,
sig: &Signature,
pk: &PublicKey,
) -> Result<(), Error> {
unsafe { unsafe {
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr()) == 0 { if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr())
== 0
{
Err(Error::IncorrectSignature) Err(Error::IncorrectSignature)
} else { } else {
Ok(()) Ok(())

View File

@ -18,10 +18,12 @@
//! //!
use core::ptr; use core::ptr;
use crate::{key, Secp256k1, Message, Error, Verification, Signing, ecdsa::Signature};
use super::ffi as super_ffi;
use self::super_ffi::CPtr; use self::super_ffi::CPtr;
use super::ffi as super_ffi;
use crate::ecdsa::Signature;
use crate::ffi::recovery as ffi; use crate::ffi::recovery as ffi;
use crate::{key, Error, Message, Secp256k1, Signing, Verification};
/// A tag used for recovering the public key from a compact signature. /// A tag used for recovering the public key from a compact signature.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
@ -32,20 +34,18 @@ pub struct RecoveryId(i32);
pub struct RecoverableSignature(ffi::RecoverableSignature); pub struct RecoverableSignature(ffi::RecoverableSignature);
impl RecoveryId { impl RecoveryId {
#[inline] #[inline]
/// Allows library users to create valid recovery IDs from i32. /// Allows library users to create valid recovery IDs from i32.
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> { pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
match id { match id {
0..=3 => Ok(RecoveryId(id)), 0..=3 => Ok(RecoveryId(id)),
_ => Err(Error::InvalidRecoveryId) _ => Err(Error::InvalidRecoveryId),
}
} }
}
#[inline] #[inline]
/// Allows library users to convert recovery IDs to i32. /// Allows library users to convert recovery IDs to i32.
pub fn to_i32(self) -> i32 { pub fn to_i32(self) -> i32 { self.0 }
self.0
}
} }
impl RecoverableSignature { impl RecoverableSignature {
@ -53,7 +53,9 @@ impl RecoverableSignature {
/// Converts a compact-encoded byte slice to a signature. This /// Converts a compact-encoded byte slice to a signature. This
/// representation is nonstandard and defined by the libsecp256k1 library. /// representation is nonstandard and defined by the libsecp256k1 library.
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> { pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
if data.is_empty() {return Err(Error::InvalidSignature);} if data.is_empty() {
return Err(Error::InvalidSignature);
}
let mut ret = ffi::RecoverableSignature::new(); let mut ret = ffi::RecoverableSignature::new();
@ -77,16 +79,15 @@ impl RecoverableSignature {
/// Obtains a raw pointer suitable for use with FFI functions. /// Obtains a raw pointer suitable for use with FFI functions.
#[inline] #[inline]
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")] #[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { self.as_c_ptr() }
self.as_c_ptr()
}
/// Obtains a raw mutable pointer suitable for use with FFI functions. /// Obtains a raw mutable pointer suitable for use with FFI functions.
#[inline] #[inline]
#[deprecated(since = "0.25.0", note = "Use Self::as_mut_c_ptr if you need to access the FFI layer")] #[deprecated(
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature { since = "0.25.0",
self.as_mut_c_ptr() note = "Use Self::as_mut_c_ptr if you need to access the FFI layer"
} )]
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature { self.as_mut_c_ptr() }
#[inline] #[inline]
/// Serializes the recoverable signature in compact format. /// Serializes the recoverable signature in compact format.
@ -131,24 +132,17 @@ impl RecoverableSignature {
} }
} }
impl CPtr for RecoverableSignature { impl CPtr for RecoverableSignature {
type Target = ffi::RecoverableSignature; type Target = ffi::RecoverableSignature;
fn as_c_ptr(&self) -> *const Self::Target { fn as_c_ptr(&self) -> *const Self::Target { &self.0 }
&self.0
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target { fn as_mut_c_ptr(&mut self) -> *mut Self::Target { &mut self.0 }
&mut self.0
}
} }
/// Creates a new recoverable signature from a FFI one. /// Creates a new recoverable signature from a FFI one.
impl From<ffi::RecoverableSignature> for RecoverableSignature { impl From<ffi::RecoverableSignature> for RecoverableSignature {
#[inline] #[inline]
fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { RecoverableSignature(sig) }
RecoverableSignature(sig)
}
} }
impl<C: Signing> Secp256k1<C> { impl<C: Signing> Secp256k1<C> {
@ -180,7 +174,11 @@ impl<C: Signing> Secp256k1<C> {
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce /// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
/// Requires a signing-capable context. /// Requires a signing-capable context.
pub fn sign_ecdsa_recoverable(&self, msg: &Message, sk: &key::SecretKey) -> RecoverableSignature { pub fn sign_ecdsa_recoverable(
&self,
msg: &Message,
sk: &key::SecretKey,
) -> RecoverableSignature {
self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, ptr::null()) self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, ptr::null())
} }
@ -203,13 +201,15 @@ impl<C: Signing> Secp256k1<C> {
impl<C: Verification> Secp256k1<C> { impl<C: Verification> Secp256k1<C> {
/// Determines the public key for which `sig` is a valid signature for /// Determines the public key for which `sig` is a valid signature for
/// `msg`. Requires a verify-capable context. /// `msg`. Requires a verify-capable context.
pub fn recover_ecdsa(&self, msg: &Message, sig: &RecoverableSignature) pub fn recover_ecdsa(
-> Result<key::PublicKey, Error> { &self,
msg: &Message,
sig: &RecoverableSignature,
) -> Result<key::PublicKey, Error> {
unsafe { unsafe {
let mut pk = super_ffi::PublicKey::new(); let mut pk = super_ffi::PublicKey::new();
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_c_ptr(), msg.as_c_ptr()) != 1
sig.as_c_ptr(), msg.as_c_ptr()) != 1 { {
return Err(Error::InvalidSignature); return Err(Error::InvalidSignature);
} }
Ok(key::PublicKey::from(pk)) Ok(key::PublicKey::from(pk))
@ -217,21 +217,19 @@ impl<C: Verification> Secp256k1<C> {
} }
} }
#[cfg(test)] #[cfg(test)]
#[allow(unused_imports)] #[allow(unused_imports)]
mod tests { mod tests {
use rand::{RngCore, thread_rng}; use rand::{thread_rng, RngCore};
use crate::{Error, SecretKey, Secp256k1, Message};
use crate::constants::ONE;
use super::{RecoveryId, RecoverableSignature};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test; use wasm_bindgen_test::wasm_bindgen_test as test;
use super::{RecoverableSignature, RecoveryId};
use crate::constants::ONE;
use crate::{Error, Message, Secp256k1, SecretKey};
#[test] #[test]
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn capabilities() { fn capabilities() {
let sign = Secp256k1::signing_only(); let sign = Secp256k1::signing_only();
let vrfy = Secp256k1::verification_only(); let vrfy = Secp256k1::verification_only();
@ -252,8 +250,7 @@ mod tests {
assert!(vrfy.recover_ecdsa(&msg, &sigr).is_ok()); assert!(vrfy.recover_ecdsa(&msg, &sigr).is_ok());
assert!(full.recover_ecdsa(&msg, &sigr).is_ok()); assert!(full.recover_ecdsa(&msg, &sigr).is_ok());
assert_eq!(vrfy.recover_ecdsa(&msg, &sigr), assert_eq!(vrfy.recover_ecdsa(&msg, &sigr), full.recover_ecdsa(&msg, &sigr));
full.recover_ecdsa(&msg, &sigr));
assert_eq!(full.recover_ecdsa(&msg, &sigr), Ok(pk)); assert_eq!(full.recover_ecdsa(&msg, &sigr), Ok(pk));
} }
@ -266,6 +263,7 @@ mod tests {
#[test] #[test]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature="std", feature = "rand-std"))]
#[rustfmt::skip]
fn sign() { fn sign() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -290,6 +288,7 @@ mod tests {
#[test] #[test]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature="std", feature = "rand-std"))]
#[rustfmt::skip]
fn sign_with_noncedata() { fn sign_with_noncedata() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -313,7 +312,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn sign_and_verify_fail() { fn sign_and_verify_fail() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -337,7 +336,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn sign_with_recovery() { fn sign_with_recovery() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -354,7 +353,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn sign_with_recovery_and_noncedata() { fn sign_with_recovery_and_noncedata() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -373,7 +372,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(all(feature="std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn bad_recovery() { fn bad_recovery() {
let mut s = Secp256k1::new(); let mut s = Secp256k1::new();
s.randomize(&mut thread_rng()); s.randomize(&mut thread_rng());
@ -390,6 +389,7 @@ mod tests {
#[test] #[test]
fn test_debug_output() { fn test_debug_output() {
#[rustfmt::skip]
let sig = RecoverableSignature::from_compact(&[ let sig = RecoverableSignature::from_compact(&[
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
@ -406,6 +406,7 @@ mod tests {
#[test] #[test]
fn test_recov_sig_serialize_compact() { fn test_recov_sig_serialize_compact() {
let recid_in = RecoveryId(1); let recid_in = RecoveryId(1);
#[rustfmt::skip]
let bytes_in = &[ let bytes_in = &[
0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f, 0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6, 0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
@ -415,10 +416,7 @@ mod tests {
0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f, 0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f,
0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06, 0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89]; 0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89];
let sig = RecoverableSignature::from_compact( let sig = RecoverableSignature::from_compact(bytes_in, recid_in).unwrap();
bytes_in,
recid_in,
).unwrap();
let (recid_out, bytes_out) = sig.serialize_compact(); let (recid_out, bytes_out) = sig.serialize_compact();
assert_eq!(recid_in, recid_out); assert_eq!(recid_in, recid_out);
assert_eq!(&bytes_in[..], &bytes_out[..]); assert_eq!(&bytes_in[..], &bytes_out[..]);
@ -442,7 +440,8 @@ mod tests {
#[cfg(bench)] #[cfg(bench)]
mod benches { mod benches {
use rand::{thread_rng, RngCore}; use rand::{thread_rng, RngCore};
use test::{Bencher, black_box}; use test::{black_box, Bencher};
use super::{Message, Secp256k1}; use super::{Message, Secp256k1};
#[bench] #[bench]

View File

@ -5,11 +5,12 @@
//! unable to run on platforms without allocator. We implement a special type to encapsulate //! unable to run on platforms without allocator. We implement a special type to encapsulate
//! serialized signatures and since it's a bit more complicated it has its own module. //! serialized signatures and since it's a bit more complicated it has its own module.
use core::{fmt, ops};
pub use into_iter::IntoIter; pub use into_iter::IntoIter;
use core::{fmt, ops};
use crate::Error;
use super::Signature; use super::Signature;
use crate::Error;
pub(crate) const MAX_LEN: usize = 72; pub(crate) const MAX_LEN: usize = 72;
@ -21,9 +22,7 @@ pub struct SerializedSignature {
} }
impl fmt::Debug for SerializedSignature { impl fmt::Debug for SerializedSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
fmt::Display::fmt(self, f)
}
} }
impl fmt::Display for SerializedSignature { impl fmt::Display for SerializedSignature {
@ -37,25 +36,19 @@ impl fmt::Display for SerializedSignature {
impl PartialEq for SerializedSignature { impl PartialEq for SerializedSignature {
#[inline] #[inline]
fn eq(&self, other: &SerializedSignature) -> bool { fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
**self == **other
}
} }
impl AsRef<[u8]> for SerializedSignature { impl AsRef<[u8]> for SerializedSignature {
#[inline] #[inline]
fn as_ref(&self) -> &[u8] { fn as_ref(&self) -> &[u8] { self }
self
}
} }
impl ops::Deref for SerializedSignature { impl ops::Deref for SerializedSignature {
type Target = [u8]; type Target = [u8];
#[inline] #[inline]
fn deref(&self) -> &[u8] { fn deref(&self) -> &[u8] { &self.data[..self.len] }
&self.data[..self.len]
}
} }
impl Eq for SerializedSignature {} impl Eq for SerializedSignature {}
@ -65,9 +58,7 @@ impl IntoIterator for SerializedSignature {
type Item = u8; type Item = u8;
#[inline] #[inline]
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) }
IntoIter::new(self)
}
} }
impl<'a> IntoIterator for &'a SerializedSignature { impl<'a> IntoIterator for &'a SerializedSignature {
@ -75,9 +66,7 @@ impl<'a> IntoIterator for &'a SerializedSignature {
type Item = &'a u8; type Item = &'a u8;
#[inline] #[inline]
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter { self.iter() }
self.iter()
}
} }
impl SerializedSignature { impl SerializedSignature {
@ -89,43 +78,30 @@ impl SerializedSignature {
#[inline] #[inline]
pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self { pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN); assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
SerializedSignature { SerializedSignature { data, len }
data,
len,
}
} }
/// Get the capacity of the underlying data buffer. /// Get the capacity of the underlying data buffer.
#[inline] #[inline]
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize { self.data.len() }
self.data.len()
}
/// Get the len of the used data. /// Get the len of the used data.
#[inline] #[inline]
pub fn len(&self) -> usize { pub fn len(&self) -> usize { self.len }
self.len
}
/// Set the length of the object. /// Set the length of the object.
#[inline] #[inline]
pub(crate) fn set_len_unchecked(&mut self, len: usize) { pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
self.len = len;
}
/// Convert the serialized signature into the Signature struct. /// Convert the serialized signature into the Signature struct.
/// (This DER deserializes it) /// (This DER deserializes it)
#[inline] #[inline]
pub fn to_signature(&self) -> Result<Signature, Error> { pub fn to_signature(&self) -> Result<Signature, Error> { Signature::from_der(self) }
Signature::from_der(self)
}
/// Create a SerializedSignature from a Signature. /// Create a SerializedSignature from a Signature.
/// (this DER serializes it) /// (this DER serializes it)
#[inline] #[inline]
pub fn from_signature(sig: &Signature) -> SerializedSignature { pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize_der() }
sig.serialize_der()
}
/// Check if the space is zero. /// Check if the space is zero.
#[inline] #[inline]
@ -162,9 +138,7 @@ mod into_iter {
/// ///
/// This method is analogous to [`core::slice::Iter::as_slice`]. /// This method is analogous to [`core::slice::Iter::as_slice`].
#[inline] #[inline]
pub fn as_slice(&self) -> &[u8] { pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] }
&self.signature[self.pos..]
}
} }
impl Iterator for IntoIter { impl Iterator for IntoIter {

File diff suppressed because it is too large Load Diff

View File

@ -153,11 +153,8 @@
// Coding conventions // Coding conventions
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)] #![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)] #![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)] #![cfg_attr(all(not(test), not(feature = "std")), no_std)]
// Experimental features we need. // Experimental features we need.
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(bench, feature(test))] #![cfg_attr(bench, feature(test))]
@ -184,29 +181,30 @@ pub mod schnorr;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
mod serde_util; mod serde_util;
#[cfg(any(test, feature = "rand"))] use core::marker::PhantomData;
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))] use core::{fmt, mem, str};
pub use rand;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub use serde;
#[cfg(feature = "bitcoin-hashes")] #[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
pub use bitcoin_hashes as hashes; pub use bitcoin_hashes as hashes;
pub use secp256k1_sys as ffi;
pub use crate::key::{PublicKey, SecretKey};
pub use crate::context::*;
pub use crate::key::*;
pub use crate::scalar::Scalar;
#[cfg(feature = "global-context")] #[cfg(feature = "global-context")]
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))] #[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
pub use context::global::SECP256K1; pub use context::global::SECP256K1;
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub use rand;
pub use secp256k1_sys as ffi;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub use serde;
use core::{fmt, str, mem, marker::PhantomData}; pub use crate::context::*;
use crate::ffi::{CPtr, impl_array_newtype, types::AlignedType}; use crate::ffi::types::AlignedType;
use crate::ffi::{impl_array_newtype, CPtr};
#[cfg(feature = "bitcoin-hashes")] #[cfg(feature = "bitcoin-hashes")]
use crate::hashes::Hash; use crate::hashes::Hash;
pub use crate::key::{PublicKey, SecretKey, *};
pub use crate::scalar::Scalar;
/// Trait describing something that promises to be a 32-byte random number; in particular, /// Trait describing something that promises to be a 32-byte random number; in particular,
/// it has negligible probability of being zero or overflowing the group order. Such objects /// it has negligible probability of being zero or overflowing the group order. Such objects
@ -219,25 +217,19 @@ pub trait ThirtyTwoByteHash {
#[cfg(feature = "bitcoin-hashes")] #[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl ThirtyTwoByteHash for hashes::sha256::Hash { impl ThirtyTwoByteHash for hashes::sha256::Hash {
fn into_32(self) -> [u8; 32] { fn into_32(self) -> [u8; 32] { self.into_inner() }
self.into_inner()
}
} }
#[cfg(feature = "bitcoin-hashes")] #[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl ThirtyTwoByteHash for hashes::sha256d::Hash { impl ThirtyTwoByteHash for hashes::sha256d::Hash {
fn into_32(self) -> [u8; 32] { fn into_32(self) -> [u8; 32] { self.into_inner() }
self.into_inner()
}
} }
#[cfg(feature = "bitcoin-hashes")] #[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> { impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> {
fn into_32(self) -> [u8; 32] { fn into_32(self) -> [u8; 32] { self.into_inner() }
self.into_inner()
}
} }
/// A (hashed) message input to an ECDSA signature. /// A (hashed) message input to an ECDSA signature.
@ -260,7 +252,7 @@ impl Message {
ret[..].copy_from_slice(data); ret[..].copy_from_slice(data);
Ok(Message(ret)) Ok(Message(ret))
} }
_ => Err(Error::InvalidMessage) _ => Err(Error::InvalidMessage),
} }
} }
@ -291,9 +283,7 @@ impl Message {
impl<T: ThirtyTwoByteHash> From<T> for Message { impl<T: ThirtyTwoByteHash> From<T> for Message {
/// Converts a 32-byte hash directly to a message without error paths. /// Converts a 32-byte hash directly to a message without error paths.
fn from(t: T) -> Message { fn from(t: T) -> Message { Message(t.into_32()) }
Message(t.into_32())
}
} }
impl fmt::LowerHex for Message { impl fmt::LowerHex for Message {
@ -306,9 +296,7 @@ impl fmt::LowerHex for Message {
} }
impl fmt::Display for Message { impl fmt::Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
fmt::LowerHex::fmt(self, f)
}
} }
/// An ECDSA error /// An ECDSA error
@ -353,7 +341,9 @@ impl fmt::Display for Error {
InvalidRecoveryId => f.write_str("bad recovery id"), InvalidRecoveryId => f.write_str("bad recovery id"),
InvalidTweak => f.write_str("bad tweak"), InvalidTweak => f.write_str("bad tweak"),
NotEnoughMemory => f.write_str("not enough memory allocated"), NotEnoughMemory => f.write_str("not enough memory allocated"),
InvalidPublicKeySum => f.write_str("the sum of public keys was invalid or the input vector lengths was less than 1"), InvalidPublicKeySum => f.write_str(
"the sum of public keys was invalid or the input vector lengths was less than 1",
),
InvalidParityValue(e) => write_err!(f, "couldn't create parity"; e), InvalidParityValue(e) => write_err!(f, "couldn't create parity"; e),
} }
} }
@ -379,7 +369,6 @@ impl std::error::Error for Error {
} }
} }
/// The secp256k1 engine, used to execute all signature operations. /// The secp256k1 engine, used to execute all signature operations.
pub struct Secp256k1<C: Context> { pub struct Secp256k1<C: Context> {
ctx: *mut ffi::Context, ctx: *mut ffi::Context,
@ -396,7 +385,7 @@ impl<C: Context> PartialEq for Secp256k1<C> {
fn eq(&self, _other: &Secp256k1<C>) -> bool { true } fn eq(&self, _other: &Secp256k1<C>) -> bool { true }
} }
impl<C: Context> Eq for Secp256k1<C> { } impl<C: Context> Eq for Secp256k1<C> {}
impl<C: Context> Drop for Secp256k1<C> { impl<C: Context> Drop for Secp256k1<C> {
fn drop(&mut self) { fn drop(&mut self) {
@ -414,14 +403,11 @@ impl<C: Context> fmt::Debug for Secp256k1<C> {
} }
impl<C: Context> Secp256k1<C> { impl<C: Context> Secp256k1<C> {
/// Getter for the raw pointer to the underlying secp256k1 context. This /// Getter for the raw pointer to the underlying secp256k1 context. This
/// shouldn't be needed with normal usage of the library. It enables /// shouldn't be needed with normal usage of the library. It enables
/// extending the Secp256k1 with more cryptographic algorithms outside of /// extending the Secp256k1 with more cryptographic algorithms outside of
/// this crate. /// this crate.
pub fn ctx(&self) -> &*mut ffi::Context { pub fn ctx(&self) -> &*mut ffi::Context { &self.ctx }
&self.ctx
}
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all). /// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
pub fn preallocate_size_gen() -> usize { pub fn preallocate_size_gen() -> usize {
@ -468,8 +454,10 @@ impl<C: Signing> Secp256k1<C> {
#[inline] #[inline]
#[cfg(any(test, feature = "rand"))] #[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))] #[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn generate_keypair<R: rand::Rng + ?Sized>(&self, rng: &mut R) pub fn generate_keypair<R: rand::Rng + ?Sized>(
-> (key::SecretKey, key::PublicKey) { &self,
rng: &mut R,
) -> (key::SecretKey, key::PublicKey) {
let sk = key::SecretKey::new(rng); let sk = key::SecretKey::new(rng);
let pk = key::PublicKey::from_secret_key(self, &sk); let pk = key::PublicKey::from_secret_key(self, &sk);
(sk, pk) (sk, pk)
@ -525,38 +513,38 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
let mut i = 0; let mut i = 0;
for &b in src { for &b in src {
target[i] = HEX_TABLE[usize::from(b >> 4)]; target[i] = HEX_TABLE[usize::from(b >> 4)];
target[i+1] = HEX_TABLE[usize::from(b & 0b00001111)]; target[i + 1] = HEX_TABLE[usize::from(b & 0b00001111)];
i +=2 ; i += 2;
} }
let result = &target[..hex_len]; let result = &target[..hex_len];
debug_assert!(str::from_utf8(result).is_ok()); debug_assert!(str::from_utf8(result).is_ok());
return unsafe { Ok(str::from_utf8_unchecked(result)) }; return unsafe { Ok(str::from_utf8_unchecked(result)) };
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::FromStr; use std::str::FromStr;
use rand::{RngCore, thread_rng}; use rand::{thread_rng, RngCore};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test; use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::{constants, ecdsa, from_hex, to_hex, Message, PublicKey, Secp256k1, SecretKey, Error};
use crate::context::*; use crate::context::*;
use crate::ffi::{self, types::AlignedType}; use crate::ffi::types::AlignedType;
use crate::ffi::{self};
use crate::{
constants, ecdsa, from_hex, to_hex, Error, Message, PublicKey, Secp256k1, SecretKey,
};
macro_rules! hex { macro_rules! hex {
($hex:expr) => ({ ($hex:expr) => {{
let mut result = vec![0; $hex.len() / 2]; let mut result = vec![0; $hex.len() / 2];
from_hex($hex, &mut result).expect("valid hex string"); from_hex($hex, &mut result).expect("valid hex string");
result result
}); }};
} }
#[test] #[test]
#[cfg(feature = "std")] #[cfg(feature = "std")]
fn test_manual_create_destroy() { fn test_manual_create_destroy() {
@ -565,9 +553,12 @@ mod tests {
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) }; let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
let size = 0; let size = 0;
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, phantom: PhantomData, size}; let full: Secp256k1<AllPreallocated> =
let sign: Secp256k1<SignOnlyPreallocated> = Secp256k1{ctx: ctx_sign, phantom: PhantomData, size}; Secp256k1 { ctx: ctx_full, phantom: PhantomData, size };
let vrfy: Secp256k1<VerifyOnlyPreallocated> = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, size}; let sign: Secp256k1<SignOnlyPreallocated> =
Secp256k1 { ctx: ctx_sign, phantom: PhantomData, size };
let vrfy: Secp256k1<VerifyOnlyPreallocated> =
Secp256k1 { ctx: ctx_vrfy, phantom: PhantomData, size };
let (sk, pk) = full.generate_keypair(&mut thread_rng()); let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap(); let msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -579,7 +570,9 @@ mod tests {
assert!(vrfy.verify_ecdsa(&msg, &sig, &pk).is_ok()); assert!(vrfy.verify_ecdsa(&msg, &sig, &pk).is_ok());
assert!(full.verify_ecdsa(&msg, &sig, &pk).is_ok()); assert!(full.verify_ecdsa(&msg, &sig, &pk).is_ok());
drop(full);drop(sign);drop(vrfy); drop(full);
drop(sign);
drop(vrfy);
unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) }; unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) };
unsafe { ffi::secp256k1_context_destroy(ctx_sign) }; unsafe { ffi::secp256k1_context_destroy(ctx_sign) };
@ -595,9 +588,9 @@ mod tests {
let ctx_sign = Secp256k1::signing_only(); let ctx_sign = Secp256k1::signing_only();
let ctx_vrfy = Secp256k1::verification_only(); let ctx_vrfy = Secp256k1::verification_only();
let mut full = unsafe {Secp256k1::from_raw_all(ctx_full.ctx)}; let mut full = unsafe { Secp256k1::from_raw_all(ctx_full.ctx) };
let mut sign = unsafe {Secp256k1::from_raw_signing_only(ctx_sign.ctx)}; let mut sign = unsafe { Secp256k1::from_raw_signing_only(ctx_sign.ctx) };
let mut vrfy = unsafe {Secp256k1::from_raw_verification_only(ctx_vrfy.ctx)}; let mut vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
let (sk, pk) = full.generate_keypair(&mut thread_rng()); let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap(); let msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -613,7 +606,6 @@ mod tests {
ManuallyDrop::drop(&mut full); ManuallyDrop::drop(&mut full);
ManuallyDrop::drop(&mut sign); ManuallyDrop::drop(&mut sign);
ManuallyDrop::drop(&mut vrfy); ManuallyDrop::drop(&mut vrfy);
} }
drop(ctx_full); drop(ctx_full);
drop(ctx_sign); drop(ctx_sign);
@ -640,8 +632,8 @@ mod tests {
let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap(); let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap();
let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap(); let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap();
// drop(buf_vfy); // The buffer can't get dropped before the context. // drop(buf_vfy); // The buffer can't get dropped before the context.
// println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker. // println!("{:?}", buf_ful[5]); // Can't even read the data thanks to the borrow checker.
let (sk, pk) = full.generate_keypair(&mut thread_rng()); let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap(); let msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -709,7 +701,7 @@ mod tests {
assert!(ecdsa::Signature::from_compact(&compact[0..4]).is_err()); assert!(ecdsa::Signature::from_compact(&compact[0..4]).is_err());
assert!(ecdsa::Signature::from_der(&compact[..]).is_err()); assert!(ecdsa::Signature::from_der(&compact[..]).is_err());
assert!(ecdsa::Signature::from_der(&der[0..4]).is_err()); assert!(ecdsa::Signature::from_der(&der[0..4]).is_err());
} }
} }
#[test] #[test]
@ -729,15 +721,18 @@ mod tests {
assert!(ecdsa::Signature::from_str( assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4" 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
).is_err()); )
.is_err());
assert!(ecdsa::Signature::from_str( assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab" 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
).is_err()); )
.is_err());
assert!(ecdsa::Signature::from_str( assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx" 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
).is_err()); )
.is_err());
assert!(ecdsa::Signature::from_str( assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\ "3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
@ -745,7 +740,8 @@ mod tests {
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\ 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45" 72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
).is_err()); )
.is_err());
// 71 byte signature // 71 byte signature
let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776"; let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776";
@ -796,14 +792,14 @@ 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(fuzzing))] // mocked sig generation doesn't produce low-R sigs #[cfg(not(fuzzing))] // mocked sig generation doesn't produce low-R sigs
assert_ne!(sig, low_r_sig); assert_ne!(sig, low_r_sig);
} }
#[cfg(not(fuzzing))] // mocked sig generation doesn't produce low-R sigs #[cfg(not(fuzzing))] // mocked sig generation doesn't produce low-R sigs
assert!(ecdsa::compact_sig_has_zero_first_bit(&low_r_sig.0)); assert!(ecdsa::compact_sig_has_zero_first_bit(&low_r_sig.0));
#[cfg(not(fuzzing))] // mocked sig generation doesn't produce low-R sigs #[cfg(not(fuzzing))] // mocked sig generation doesn't produce low-R sigs
assert!(ecdsa::der_length_check(&grind_r_sig.0, 70)); assert!(ecdsa::der_length_check(&grind_r_sig.0, 70));
} }
} }
#[test] #[test]
@ -862,15 +858,23 @@ mod tests {
#[test] #[test]
fn test_bad_slice() { fn test_bad_slice() {
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]), assert_eq!(
Err(Error::InvalidSignature)); ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]), Err(Error::InvalidSignature)
Err(Error::InvalidSignature)); );
assert_eq!(
ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
Err(Error::InvalidSignature)
);
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]), assert_eq!(
Err(Error::InvalidMessage)); Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]), Err(Error::InvalidMessage)
Err(Error::InvalidMessage)); );
assert_eq!(
Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]),
Err(Error::InvalidMessage)
);
assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok()); assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok());
assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok()); assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok());
} }
@ -881,7 +885,7 @@ mod tests {
const AMOUNT: usize = 1024; const AMOUNT: usize = 1024;
for i in 0..AMOUNT { for i in 0..AMOUNT {
// 255 isn't a valid utf8 character. // 255 isn't a valid utf8 character.
let mut hex_buf = [255u8; AMOUNT*2]; let mut hex_buf = [255u8; AMOUNT * 2];
let mut src_buf = [0u8; AMOUNT]; let mut src_buf = [0u8; AMOUNT];
let mut result_buf = [0u8; AMOUNT]; let mut result_buf = [0u8; AMOUNT];
let src = &mut src_buf[0..i]; let src = &mut src_buf[0..i];
@ -892,9 +896,8 @@ mod tests {
assert_eq!(src, &result_buf[..i]); assert_eq!(src, &result_buf[..i]);
} }
assert!(to_hex(&[1; 2], &mut [0u8; 3]).is_err());
assert!(to_hex(&[1;2], &mut [0u8; 3]).is_err()); assert!(to_hex(&[1; 2], &mut [0u8; 4]).is_ok());
assert!(to_hex(&[1;2], &mut [0u8; 4]).is_ok());
assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err()); assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err());
assert!(from_hex("deadbeaf", &mut [0u8; 4]).is_ok()); assert!(from_hex("deadbeaf", &mut [0u8; 4]).is_ok());
assert!(from_hex("a", &mut [0u8; 4]).is_err()); assert!(from_hex("a", &mut [0u8; 4]).is_err());
@ -902,14 +905,16 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format #[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
fn test_noncedata() { fn test_noncedata() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac"); let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
let msg = Message::from_slice(&msg).unwrap(); let msg = Message::from_slice(&msg).unwrap();
let noncedata = [42u8; 32]; let noncedata = [42u8; 32];
let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap(); let sk =
SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
.unwrap();
let expected_sig = hex!("24861b3edd4e7da43319c635091405feced6efa4ec99c3c3c35f6c3ba0ed8816116772e84994084db85a6c20589f6a85af569d42275c2a5dd900da5776b99d5d"); let expected_sig = hex!("24861b3edd4e7da43319c635091405feced6efa4ec99c3c3c35f6c3ba0ed8816116772e84994084db85a6c20589f6a85af569d42275c2a5dd900da5776b99d5d");
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap(); let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
@ -919,7 +924,7 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
fn test_low_s() { fn test_low_s() {
// nb this is a transaction on testnet // nb this is a transaction on testnet
@ -942,13 +947,15 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format #[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
fn test_low_r() { fn test_low_r() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac"); let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
let msg = Message::from_slice(&msg).unwrap(); let msg = Message::from_slice(&msg).unwrap();
let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap(); let sk =
SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
.unwrap();
let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713"); let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713");
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap(); let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
@ -958,13 +965,15 @@ mod tests {
} }
#[test] #[test]
#[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format #[cfg(not(fuzzing))] // fuzz-sigs have fixed size/format
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
fn test_grind_r() { fn test_grind_r() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167"); let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
let msg = Message::from_slice(&msg).unwrap(); let msg = Message::from_slice(&msg).unwrap();
let sk = SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b").unwrap(); let sk =
SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b")
.unwrap();
let expected_sig = ecdsa::Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap(); let expected_sig = ecdsa::Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap();
let sig = secp.sign_ecdsa_grind_r(&msg, &sk, 2); let sig = secp.sign_ecdsa_grind_r(&msg, &sk, 2);
@ -973,11 +982,11 @@ mod tests {
} }
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
#[test] #[test]
fn test_serde() { fn test_serde() {
use serde_test::{Configure, Token, assert_tokens}; use serde_test::{assert_tokens, Configure, Token};
let s = Secp256k1::new(); let s = Secp256k1::new();
@ -985,11 +994,10 @@ mod tests {
let sk = SecretKey::from_slice(&[2; 32]).unwrap(); let sk = SecretKey::from_slice(&[2; 32]).unwrap();
let sig = s.sign_ecdsa(&msg, &sk); let sig = s.sign_ecdsa(&msg, &sk);
static SIG_BYTES: [u8; 71] = [ static SIG_BYTES: [u8; 71] = [
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, 48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, 179, 76, 119, 72,
179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, 8, 230, 206, 119, 75, 2, 32, 40,
8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254, 118, 231, 16, 47, 32, 79, 107, 254, 226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125,
226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225, 75, 1, 0, 98, 225, 147, 247, 99, 25, 15, 103, 118,
147, 247, 99, 25, 15, 103, 118
]; ];
static SIG_STR: &str = "\ static SIG_STR: &str = "\
30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\ 30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\
@ -1003,7 +1011,6 @@ mod tests {
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]); assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]); assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]); assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
} }
#[cfg(feature = "global-context")] #[cfg(feature = "global-context")]
@ -1033,37 +1040,29 @@ mod tests {
let hash = hashes::sha256::Hash::hash(test_bytes); let hash = hashes::sha256::Hash::hash(test_bytes);
let msg = Message::from(hash); let msg = Message::from(hash);
assert_eq!(msg.0, hash.into_inner()); assert_eq!(msg.0, hash.into_inner());
assert_eq!( assert_eq!(msg, Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes));
msg,
Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes)
);
let hash = hashes::sha256d::Hash::hash(test_bytes); let hash = hashes::sha256d::Hash::hash(test_bytes);
let msg = Message::from(hash); let msg = Message::from(hash);
assert_eq!(msg.0, hash.into_inner()); assert_eq!(msg.0, hash.into_inner());
assert_eq!( assert_eq!(msg, Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes));
msg,
Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes)
);
} }
} }
#[cfg(bench)] #[cfg(bench)]
mod benches { mod benches {
use test::{Bencher, black_box};
use rand::{RngCore, thread_rng};
use rand::rngs::mock::StepRng; use rand::rngs::mock::StepRng;
use rand::{thread_rng, RngCore};
use test::{black_box, Bencher};
use super::{Message, Secp256k1}; use super::{Message, Secp256k1};
#[bench] #[bench]
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
pub fn generate(bh: &mut Bencher) { pub fn generate(bh: &mut Bencher) {
let s = Secp256k1::new(); let s = Secp256k1::new();
let mut r = StepRng::new(1, 1); let mut r = StepRng::new(1, 1);
bh.iter( || { bh.iter(|| {
let (sk, pk) = s.generate_keypair(&mut r); let (sk, pk) = s.generate_keypair(&mut r);
black_box(sk); black_box(sk);
black_box(pk); black_box(pk);

View File

@ -24,7 +24,7 @@ macro_rules! impl_pretty_debug {
f.write_str(")") f.write_str(")")
} }
} }
} };
} }
/// Formats error. If `std` feature is OFF appends error source (delimited by `: `). We do this /// Formats error. If `std` feature is OFF appends error source (delimited by `: `). We do this

View File

@ -25,7 +25,7 @@ pub struct Scalar([u8; 32]);
const MAX_RAW: [u8; 32] = [ const MAX_RAW: [u8; 32] = [
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 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 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
]; ];
impl Scalar { impl Scalar {
@ -39,9 +39,7 @@ impl Scalar {
/// Generates a random scalar /// Generates a random scalar
#[cfg(any(test, feature = "rand-std"))] #[cfg(any(test, feature = "rand-std"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))] #[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
pub fn random() -> Self { pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }
Self::random_custom(rand::thread_rng())
}
/// Generates a random scalar using supplied RNG /// Generates a random scalar using supplied RNG
#[cfg(any(test, feature = "rand"))] #[cfg(any(test, feature = "rand"))]
@ -88,9 +86,7 @@ impl Scalar {
} }
/// Serializes to big endian bytes /// Serializes to big endian bytes
pub fn to_be_bytes(self) -> [u8; 32] { pub fn to_be_bytes(self) -> [u8; 32] { self.0 }
self.0
}
/// Serializes to little endian bytes /// Serializes to little endian bytes
pub fn to_le_bytes(self) -> [u8; 32] { pub fn to_le_bytes(self) -> [u8; 32] {
@ -101,9 +97,7 @@ impl Scalar {
// returns a reference to internal bytes // returns a reference to internal bytes
// non-public to not leak the internal representation // non-public to not leak the internal representation
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { &self.0 }
&self.0
}
pub(crate) fn as_c_ptr(&self) -> *const u8 { pub(crate) fn as_c_ptr(&self) -> *const u8 {
use secp256k1_sys::CPtr; use secp256k1_sys::CPtr;
@ -113,20 +107,16 @@ impl Scalar {
} }
impl From<crate::SecretKey> for Scalar { impl From<crate::SecretKey> for Scalar {
fn from(value: crate::SecretKey) -> Self { fn from(value: crate::SecretKey) -> Self { Scalar(value.secret_bytes()) }
Scalar(value.secret_bytes())
}
} }
/// Error returned when the value of scalar is invalid - larger than the curve order. /// Error returned when the value of scalar is invalid - larger than the curve order.
// Intentionally doesn't implement `Copy` to improve forward compatibility. // Intentionally doesn't implement `Copy` to improve forward compatibility.
// Same reason for `non_exhaustive`. // Same reason for `non_exhaustive`.
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[non_exhaustive] #[non_exhaustive]
pub struct OutOfRangeError { pub struct OutOfRangeError {}
}
impl fmt::Display for OutOfRangeError { impl fmt::Display for OutOfRangeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View File

@ -7,12 +7,11 @@ use core::{fmt, ptr, str};
#[cfg(any(test, feature = "rand"))] #[cfg(any(test, feature = "rand"))]
use rand::{CryptoRng, Rng}; use rand::{CryptoRng, Rng};
use crate::{constants, Error, from_hex, Message, Secp256k1, Signing, Verification}; use crate::ffi::{self, impl_array_newtype, CPtr};
use crate::key::{KeyPair, XOnlyPublicKey}; use crate::key::{KeyPair, XOnlyPublicKey};
use crate::ffi::{self, CPtr, impl_array_newtype}; #[cfg(all(feature = "global-context", feature = "rand-std"))]
#[cfg(all(feature = "global-context", feature = "rand-std"))]
use crate::SECP256K1; use crate::SECP256K1;
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
/// Represents a Schnorr signature. /// Represents a Schnorr signature.
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]); pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
@ -35,12 +34,12 @@ impl<'de> serde::Deserialize<'de> for Signature {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> { fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() { if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new( d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 64 byte schnorr signature" "a hex string representing 64 byte schnorr signature",
)) ))
} else { } else {
d.deserialize_bytes(super::serde_util::BytesVisitor::new( d.deserialize_bytes(super::serde_util::BytesVisitor::new(
"raw 64 bytes schnorr signature", "raw 64 bytes schnorr signature",
Signature::from_slice Signature::from_slice,
)) ))
} }
} }
@ -56,9 +55,7 @@ impl fmt::LowerHex for Signature {
} }
impl fmt::Display for Signature { impl fmt::Display for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
fmt::LowerHex::fmt(self, f)
}
} }
impl str::FromStr for Signature { impl str::FromStr for Signature {
@ -66,9 +63,8 @@ impl str::FromStr for Signature {
fn from_str(s: &str) -> Result<Signature, Error> { fn from_str(s: &str) -> Result<Signature, Error> {
let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE]; let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
match from_hex(s, &mut res) { match from_hex(s, &mut res) {
Ok(constants::SCHNORR_SIGNATURE_SIZE) => { Ok(constants::SCHNORR_SIGNATURE_SIZE) =>
Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE]) Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE]),
}
_ => Err(Error::InvalidSignature), _ => Err(Error::InvalidSignature),
} }
} }
@ -130,11 +126,7 @@ impl<C: Signing> Secp256k1<C> {
} }
/// Create a schnorr signature without using any auxiliary random data. /// Create a schnorr signature without using any auxiliary random data.
pub fn sign_schnorr_no_aux_rand( pub fn sign_schnorr_no_aux_rand(&self, msg: &Message, keypair: &KeyPair) -> Signature {
&self,
msg: &Message,
keypair: &KeyPair,
) -> Signature {
self.sign_schnorr_helper(msg, keypair, ptr::null()) self.sign_schnorr_helper(msg, keypair, ptr::null())
} }
@ -145,11 +137,7 @@ impl<C: Signing> Secp256k1<C> {
keypair: &KeyPair, keypair: &KeyPair,
aux_rand: &[u8; 32], aux_rand: &[u8; 32],
) -> Signature { ) -> Signature {
self.sign_schnorr_helper( self.sign_schnorr_helper(msg, keypair, aux_rand.as_c_ptr() as *const ffi::types::c_uchar)
msg,
keypair,
aux_rand.as_c_ptr() as *const ffi::types::c_uchar,
)
} }
/// Create a schnorr signature using the given random number generator to /// Create a schnorr signature using the given random number generator to
@ -199,15 +187,15 @@ impl<C: Verification> Secp256k1<C> {
mod tests { mod tests {
use core::str::FromStr; use core::str::FromStr;
use rand::{RngCore, rngs::ThreadRng, thread_rng}; use rand::rngs::ThreadRng;
use rand::{thread_rng, RngCore};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test; use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
use crate::schnorr::{KeyPair, XOnlyPublicKey, Signature};
use crate::Error::InvalidPublicKey;
use super::*; use super::*;
use crate::schnorr::{KeyPair, Signature, XOnlyPublicKey};
use crate::Error::InvalidPublicKey;
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))] #[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
macro_rules! hex_32 { macro_rules! hex_32 {
@ -231,25 +219,17 @@ mod tests {
#[test] #[test]
#[cfg(all(feature = "std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn schnor_sign_with_rng_verify() { fn schnor_sign_with_rng_verify() {
sign_helper(|secp, msg, seckey, mut rng| { sign_helper(|secp, msg, seckey, mut rng| secp.sign_schnorr_with_rng(msg, seckey, &mut rng))
secp.sign_schnorr_with_rng(msg, seckey, &mut rng)
})
} }
#[test] #[test]
#[cfg(all(feature = "std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn schnorr_sign_verify() { fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
sign_helper(|secp, msg, seckey, _| {
secp.sign_schnorr(msg, seckey)
})
}
#[test] #[test]
#[cfg(all(feature = "std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
fn schnorr_sign_no_aux_rand_verify() { fn schnorr_sign_no_aux_rand_verify() {
sign_helper(|secp, msg, seckey, _| { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
secp.sign_schnorr_no_aux_rand(msg, seckey)
})
} }
#[cfg(all(feature = "std", feature = "rand-std"))] #[cfg(all(feature = "std", feature = "rand-std"))]
@ -276,7 +256,7 @@ mod tests {
#[test] #[test]
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
fn schnorr_sign() { fn schnorr_sign() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
@ -291,14 +271,13 @@ mod tests {
hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB"); hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap(); let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
let sig = secp let sig = secp.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
assert_eq!(expected_sig, sig); assert_eq!(expected_sig, sig);
} }
#[test] #[test]
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[cfg(any(feature = "alloc", feature = "std"))] #[cfg(any(feature = "alloc", feature = "std"))]
fn schnorr_verify() { fn schnorr_verify() {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
@ -306,9 +285,10 @@ mod tests {
let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614"); let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
let msg = Message::from_slice(&hex_msg).unwrap(); let msg = Message::from_slice(&hex_msg).unwrap();
let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap(); let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
let pubkey = let pubkey = XOnlyPublicKey::from_str(
XOnlyPublicKey::from_str("B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390") "B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
.unwrap(); )
.unwrap();
assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok()); assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
} }
@ -398,15 +378,22 @@ mod tests {
pk pk
}; };
#[cfg(fuzzing)] #[cfg(fuzzing)]
let pk = XOnlyPublicKey::from_slice(&[0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66]).expect("pk"); let pk = XOnlyPublicKey::from_slice(&[
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92,
0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe,
0x91, 0xdd, 0xd1, 0x66,
])
.expect("pk");
assert_eq!( assert_eq!(
pk.to_string(), pk.to_string(),
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
); );
assert_eq!( assert_eq!(
XOnlyPublicKey::from_str("18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166") XOnlyPublicKey::from_str(
.unwrap(), "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
)
.unwrap(),
pk pk
); );
@ -454,7 +441,7 @@ mod tests {
); );
} }
#[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs #[cfg(not(fuzzing))] // fixed sig vectors can't work with fuzz-sigs
#[test] #[test]
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))] #[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
fn test_serde() { fn test_serde() {
@ -465,8 +452,7 @@ mod tests {
let msg = Message::from_slice(&[1; 32]).unwrap(); let msg = Message::from_slice(&[1; 32]).unwrap();
let keypair = KeyPair::from_seckey_slice(&s, &[2; 32]).unwrap(); let keypair = KeyPair::from_seckey_slice(&s, &[2; 32]).unwrap();
let aux = [3u8; 32]; let aux = [3u8; 32];
let sig = s let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [ static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41, 0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41,
0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e, 0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e,
@ -479,8 +465,8 @@ mod tests {
"; ";
static PK_BYTES: [u8; 32] = [ static PK_BYTES: [u8; 32] = [
24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 48,
48, 170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102 170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102,
]; ];
static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"; static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
let pk = XOnlyPublicKey::from_slice(&PK_BYTES).unwrap(); let pk = XOnlyPublicKey::from_slice(&PK_BYTES).unwrap();
@ -493,6 +479,7 @@ mod tests {
assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]); assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]); assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
#[rustfmt::skip]
assert_tokens(&pk.compact(), &[ assert_tokens(&pk.compact(), &[
Token::Tuple{ len: 32 }, Token::Tuple{ len: 32 },
Token::U8(24), Token::U8(132), Token::U8(87), Token::U8(129), Token::U8(246), Token::U8(49), Token::U8(196), Token::U8(143), Token::U8(24), Token::U8(132), Token::U8(87), Token::U8(129), Token::U8(246), Token::U8(49), Token::U8(196), Token::U8(143),

View File

@ -15,7 +15,11 @@
//! Helpers for displaying secret values //! Helpers for displaying secret values
use core::fmt; use core::fmt;
use crate::{to_hex, constants::SECRET_KEY_SIZE, key::{SecretKey, KeyPair}, ecdh::SharedSecret};
use crate::constants::SECRET_KEY_SIZE;
use crate::ecdh::SharedSecret;
use crate::key::{KeyPair, SecretKey};
use crate::to_hex;
macro_rules! impl_display_secret { macro_rules! impl_display_secret {
// Default hasher exists only in standard library and not alloc // Default hasher exists only in standard library and not alloc
($thing:ident) => { ($thing:ident) => {
@ -27,7 +31,7 @@ macro_rules! impl_display_secret {
const DEBUG_HASH_TAG: &[u8] = &[ const DEBUG_HASH_TAG: &[u8] = &[
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49, 0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79, 0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22 0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22,
]; // =SHA256(b"rust-secp256k1DEBUG"); ]; // =SHA256(b"rust-secp256k1DEBUG");
let mut hasher = std::collections::hash_map::DefaultHasher::new(); let mut hasher = std::collections::hash_map::DefaultHasher::new();
@ -37,9 +41,7 @@ macro_rules! impl_display_secret {
hasher.write(&self.secret_bytes()); hasher.write(&self.secret_bytes());
let hash = hasher.finish(); let hash = hasher.finish();
f.debug_tuple(stringify!($thing)) f.debug_tuple(stringify!($thing)).field(&format_args!("#{:016x}", hash)).finish()
.field(&format_args!("#{:016x}", hash))
.finish()
} }
} }
@ -57,9 +59,7 @@ macro_rules! impl_display_secret {
engine.input(&self.secret_bytes()); engine.input(&self.secret_bytes());
let hash = sha256::Hash::from_engine(engine); let hash = sha256::Hash::from_engine(engine);
f.debug_tuple(stringify!($thing)) f.debug_tuple(stringify!($thing)).field(&format_args!("#{:016x}", hash)).finish()
.field(&format_args!("#{:016x}", hash))
.finish()
} }
} }
@ -69,7 +69,7 @@ macro_rules! impl_display_secret {
write!(f, "<secret requires std or bitcoin_hashes feature to display>") write!(f, "<secret requires std or bitcoin_hashes feature to display>")
} }
} }
} };
} }
/// Helper struct for safely printing secrets (like [`SecretKey`] value). /// Helper struct for safely printing secrets (like [`SecretKey`] value).
@ -84,7 +84,7 @@ macro_rules! impl_display_secret {
/// [`Debug`]: fmt::Debug /// [`Debug`]: fmt::Debug
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DisplaySecret { pub struct DisplaySecret {
secret: [u8; SECRET_KEY_SIZE] secret: [u8; SECRET_KEY_SIZE],
} }
impl fmt::Debug for DisplaySecret { impl fmt::Debug for DisplaySecret {
@ -92,9 +92,7 @@ impl fmt::Debug for DisplaySecret {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut slice = [0u8; SECRET_KEY_SIZE * 2]; let mut slice = [0u8; SECRET_KEY_SIZE * 2];
let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed"); let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed");
f.debug_tuple("DisplaySecret") f.debug_tuple("DisplaySecret").field(&hex).finish()
.field(&hex)
.finish()
} }
} }
@ -138,9 +136,7 @@ impl SecretKey {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
pub fn display_secret(&self) -> DisplaySecret { pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
DisplaySecret { secret: self.secret_bytes() }
}
} }
impl KeyPair { impl KeyPair {
@ -173,9 +169,7 @@ impl KeyPair {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
pub fn display_secret(&self) -> DisplaySecret { pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
DisplaySecret { secret: self.secret_bytes() }
}
} }
impl SharedSecret { impl SharedSecret {
@ -211,7 +205,5 @@ impl SharedSecret {
/// # } /// # }
/// ``` /// ```
#[inline] #[inline]
pub fn display_secret(&self) -> DisplaySecret { pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
DisplaySecret { secret: self.secret_bytes() }
}
} }

View File

@ -1,6 +1,7 @@
use core::fmt; use core::fmt;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::str::{self, FromStr}; use core::str::{self, FromStr};
use serde::de; use serde::de;
/// A serde visitor that works for `T`s implementing `FromStr`. /// A serde visitor that works for `T`s implementing `FromStr`.
@ -11,10 +12,7 @@ pub struct FromStrVisitor<T> {
impl<T> FromStrVisitor<T> { impl<T> FromStrVisitor<T> {
pub fn new(expectation: &'static str) -> Self { pub fn new(expectation: &'static str) -> Self {
FromStrVisitor { FromStrVisitor { expectation, _pd: PhantomData }
expectation,
_pd: PhantomData,
}
} }
} }
@ -45,10 +43,7 @@ where
Err: fmt::Display, Err: fmt::Display,
{ {
pub fn new(expectation: &'static str, parse_fn: F) -> Self { pub fn new(expectation: &'static str, parse_fn: F) -> Self {
BytesVisitor { BytesVisitor { expectation, parse_fn }
expectation,
parse_fn,
}
} }
} }
@ -81,10 +76,7 @@ macro_rules! impl_tuple_visitor {
E: fmt::Display, E: fmt::Display,
{ {
pub fn new(expectation: &'static str, parse_fn: F) -> Self { pub fn new(expectation: &'static str, parse_fn: F) -> Self {
$thing { $thing { expectation, parse_fn }
expectation,
parse_fn,
}
} }
} }
@ -115,7 +107,7 @@ macro_rules! impl_tuple_visitor {
(self.parse_fn)(&bytes).map_err(de::Error::custom) (self.parse_fn)(&bytes).map_err(de::Error::custom)
} }
} }
} };
} }
impl_tuple_visitor!(Tuple32Visitor, 32); impl_tuple_visitor!(Tuple32Visitor, 32);

View File

@ -5,12 +5,13 @@ extern crate bincode;
extern crate cbor; extern crate cbor;
extern crate secp256k1; extern crate secp256k1;
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
#[cfg(feature = "global-context")] #[cfg(feature = "global-context")]
use secp256k1::{Secp256k1, KeyPair}; use secp256k1::{KeyPair, Secp256k1};
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
// Arbitrary key data. // Arbitrary key data.
#[rustfmt::skip]
static SK_BYTES: [u8; 32] = [ static SK_BYTES: [u8; 32] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23,
@ -18,6 +19,7 @@ static SK_BYTES: [u8; 32] = [
0x0f, 0x10, 0x1f, 0xa0, 0xa9, 0xaa, 0xaf, 0xff, 0x0f, 0x10, 0x1f, 0xa0, 0xa9, 0xaa, 0xaf, 0xff,
]; ];
#[rustfmt::skip]
static PK_BYTES: [u8; 33] = [ static PK_BYTES: [u8; 33] = [
0x02, 0x02,
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f,
@ -26,6 +28,7 @@ static PK_BYTES: [u8; 33] = [
0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66, 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66,
]; ];
#[rustfmt::skip]
static XONLY_PK_BYTES: [u8; 32] = [ static XONLY_PK_BYTES: [u8; 32] = [
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f,
0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d,
@ -67,7 +70,8 @@ fn bincode_key_pair() {
#[test] #[test]
fn bincode_x_only_public_key() { fn bincode_x_only_public_key() {
let pk = XOnlyPublicKey::from_slice(&XONLY_PK_BYTES).expect("failed to create xonly pk from slice"); let pk =
XOnlyPublicKey::from_slice(&XONLY_PK_BYTES).expect("failed to create xonly pk from slice");
let ser = bincode::serialize(&pk).unwrap(); let ser = bincode::serialize(&pk).unwrap();
assert_eq!(ser, XONLY_PK_BYTES); assert_eq!(ser, XONLY_PK_BYTES);