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;
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 = Message::from_slice(&msg)?;
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())
}
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 = Message::from_slice(&msg)?;
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() {
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 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 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 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 signature = sign(&secp, msg, seckey).unwrap();

View File

@ -1,11 +1,15 @@
extern crate bitcoin_hashes;
extern crate secp256k1;
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 = Message::from_slice(&msg)?;
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)
}
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 = Message::from_slice(&msg)?;
let seckey = SecretKey::from_slice(&seckey)?;
@ -25,22 +33,19 @@ fn main() {
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,
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 = PublicKey::from_slice(&[
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,
]).unwrap();
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,
])
.unwrap();
let msg = b"This is some message";
let signature = sign_recovery(&secp, msg, seckey).unwrap();
let (recovery_id, serialize_sig) = signature.serialize_compact();
assert_eq!(
recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8),
Ok(pubkey)
);
assert_eq!(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;
/// The Prime for the secp256k1 field element.
#[rustfmt::skip]
pub const FIELD_SIZE: [u8; 32] = [
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.
#[rustfmt::skip]
pub const CURVE_ORDER: [u8; 32] = [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
@ -60,6 +62,7 @@ pub const CURVE_ORDER: [u8; 32] = [
];
/// The X coordinate of the generator.
#[rustfmt::skip]
pub const GENERATOR_X: [u8; 32] = [
0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac,
0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07,
@ -68,6 +71,7 @@ pub const GENERATOR_X: [u8; 32] = [
];
/// The Y coordinate of the generator.
#[rustfmt::skip]
pub const GENERATOR_Y: [u8; 32] = [
0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65,
0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8,

View File

@ -1,13 +1,12 @@
use core::marker::PhantomData;
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_attr(docsrs, doc(cfg(feature = "alloc")))]
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_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))]
@ -47,7 +46,11 @@ pub mod global {
static mut CONTEXT: Option<Secp256k1<All>> = None;
ONCE.call_once(|| unsafe {
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());
}
@ -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
/// 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.
const FLAGS: c_uint;
/// A constant description of the context.
@ -106,13 +108,13 @@ mod private {
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
mod alloc_only {
use crate::alloc::alloc;
use core::marker::PhantomData;
use super::private;
use crate::ffi::{self, types::{c_uint, c_void}};
use crate::{Secp256k1, Signing, Verification, Context, AlignedType};
use crate::alloc::alloc;
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 All {}
@ -192,16 +194,22 @@ mod alloc_only {
let size = unsafe { ffi::secp256k1_context_preallocated_size(C::FLAGS) };
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.
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,
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());
}
@ -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 not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`).
pub fn new() -> Secp256k1<All> {
Secp256k1::gen_new()
}
pub fn new() -> Secp256k1<All> { Secp256k1::gen_new() }
}
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 not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`).
pub fn signing_only() -> Secp256k1<SignOnly> {
Secp256k1::gen_new()
}
pub fn signing_only() -> Secp256k1<SignOnly> { Secp256k1::gen_new() }
}
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 not enabled please consider randomizing the context (see docs
/// for `Secp256k1::gen_new()`).
pub fn verification_only() -> Secp256k1<VerifyOnly> {
Secp256k1::gen_new()
}
pub fn verification_only() -> Secp256k1<VerifyOnly> { Secp256k1::gen_new() }
}
impl Default for Secp256k1<All> {
fn default() -> Self {
Self::new()
}
fn default() -> Self { Self::new() }
}
impl<C: Context> Clone for 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 ptr = unsafe {alloc::alloc(layout)};
let ptr = unsafe { alloc::alloc(layout) };
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,
size,
}
@ -310,7 +312,8 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
ctx: unsafe {
ffi::secp256k1_context_preallocated_create(
buf.as_mut_c_ptr() as *mut c_void,
C::FLAGS)
C::FLAGS,
)
},
phantom: PhantomData,
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>> {
/// 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)
}
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
pub fn preallocate_size() -> usize {
Self::preallocate_size_gen()
}
pub fn preallocate_size() -> usize { Self::preallocate_size_gen() }
/// 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.
/// * 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 {
ctx: raw_ctx,
phantom: PhantomData,
@ -350,15 +355,15 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
/// 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)
}
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
#[inline]
pub fn preallocate_signing_size() -> usize {
Self::preallocate_size_gen()
}
pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() }
/// 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.
/// * 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 {
ctx: raw_ctx,
phantom: PhantomData,
@ -382,15 +389,15 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
/// 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)
}
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
#[inline]
pub fn preallocate_verification_size() -> usize {
Self::preallocate_size_gen()
}
pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() }
/// 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.
/// * 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 {
ctx: raw_ctx,
phantom: PhantomData,

View File

@ -15,11 +15,14 @@
//! 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 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`).
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
@ -66,15 +69,11 @@ impl SharedSecret {
/// Returns the shared secret as a byte value.
#[inline]
pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] {
self.0
}
pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] { self.0 }
/// Creates a shared secret from `bytes` array.
#[inline]
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret {
SharedSecret(bytes)
}
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret { SharedSecret(bytes) }
/// Creates a shared secret from `bytes` slice.
#[inline]
@ -85,7 +84,7 @@ impl SharedSecret {
ret[..].copy_from_slice(bytes);
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];
match crate::from_hex(s, &mut res) {
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
_ => Err(Error::InvalidSharedSecret)
_ => Err(Error::InvalidSharedSecret),
}
}
}
impl Borrow<[u8]> for SharedSecret {
fn borrow(&self) -> &[u8] {
&self.0
}
fn borrow(&self) -> &[u8] { &self.0 }
}
impl AsRef<[u8]> for SharedSecret {
fn as_ref(&self) -> &[u8] {
&self.0
}
fn as_ref(&self) -> &[u8] { &self.0 }
}
/// 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
}
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(y, output.offset(32), 32);
1
@ -187,12 +187,12 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
"a hex string representing 32 byte SharedSecret"
"a hex string representing 32 byte SharedSecret",
))
} else {
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
"raw 32 bytes SharedSecret",
SharedSecret::from_slice
SharedSecret::from_slice,
))
}
}
@ -205,11 +205,11 @@ mod tests {
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use crate::Secp256k1;
use super::SharedSecret;
use crate::Secp256k1;
#[test]
#[cfg(all(feature="rand-std", any(feature = "alloc", feature = "std")))]
#[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))]
fn ecdh() {
let s = Secp256k1::signing_only();
let (sk1, pk1) = s.generate_keypair(&mut thread_rng());
@ -227,7 +227,9 @@ mod tests {
let x = [5u8; 32];
let y = [7u8; 32];
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);
let mut new_x = [0u8; 32];
let mut new_y = [0u8; 32];
@ -239,9 +241,10 @@ mod tests {
#[test]
#[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() {
use bitcoin_hashes::{sha256, Hash, HashEngine};
use crate::ecdh::shared_secret_point;
let s = Secp256k1::signing_only();
@ -265,7 +268,8 @@ mod tests {
#[test]
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
fn serde() {
use serde_test::{Configure, Token, assert_tokens};
use serde_test::{assert_tokens, Configure, Token};
#[rustfmt::skip]
static BYTES: [u8; 32] = [
1, 1, 1, 1, 1, 1, 1, 1,
0, 1, 2, 3, 4, 5, 6, 7,
@ -288,23 +292,20 @@ mod tests {
#[cfg(bench)]
mod benches {
use test::{Bencher, black_box};
use rand::thread_rng;
use crate::Secp256k1;
use test::{black_box, Bencher};
use super::SharedSecret;
use crate::Secp256k1;
#[bench]
pub fn bench_ecdh(bh: &mut Bencher) {
let s = Secp256k1::signing_only();
let (sk, pk) = s.generate_keypair(&mut thread_rng());
bh.iter( || {
bh.iter(|| {
let res = SharedSecret::new(&pk, &sk);
black_box(res);
});
}
}

View File

@ -1,32 +1,28 @@
//! 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")]
mod recovery;
pub mod serialized_signature;
use core::{fmt, ptr, str};
#[cfg(feature = "recovery")]
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
pub use self::recovery::{RecoveryId, RecoverableSignature};
pub use serialized_signature::SerializedSignature;
pub use self::recovery::{RecoverableSignature, RecoveryId};
pub use self::serialized_signature::SerializedSignature;
use crate::ffi::CPtr;
#[cfg(feature = "global-context")]
use crate::SECP256K1;
use crate::{
ffi, from_hex, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification,
};
/// An ECDSA signature
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Signature(pub(crate) ffi::Signature);
impl fmt::Debug for Signature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
}
impl fmt::Display for Signature {
@ -51,7 +47,9 @@ impl Signature {
#[inline]
/// Converts a DER-encoded byte slice to a signature
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 {
let mut ret = ffi::Signature::new();
@ -72,7 +70,7 @@ impl Signature {
/// Converts a 64-byte compact-encoded byte slice to a signature
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
if data.len() != 64 {
return Err(Error::InvalidSignature)
return Err(Error::InvalidSignature);
}
unsafe {
@ -95,7 +93,9 @@ impl Signature {
/// 2016. It should never be used in new applications. This library does not
/// support serializing to this "format"
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 {
let mut ret = ffi::Signature::new();
@ -145,16 +145,15 @@ impl Signature {
/// Obtains a raw pointer suitable for use with FFI functions
#[inline]
#[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 {
self.as_c_ptr()
}
pub fn as_ptr(&self) -> *const ffi::Signature { self.as_c_ptr() }
/// Obtains a raw mutable pointer suitable for use with FFI functions
#[inline]
#[deprecated(since = "0.25.0", 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()
}
#[deprecated(
since = "0.25.0",
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]
/// Serializes the signature in DER format
@ -200,21 +199,15 @@ impl Signature {
impl CPtr for Signature {
type Target = ffi::Signature;
fn as_c_ptr(&self) -> *const Self::Target {
&self.0
}
fn as_c_ptr(&self) -> *const Self::Target { &self.0 }
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
&mut self.0
}
fn as_mut_c_ptr(&mut self) -> *mut Self::Target { &mut self.0 }
}
/// Creates a new signature from a FFI signature
impl From<ffi::Signature> for Signature {
#[inline]
fn from(sig: ffi::Signature) -> Signature {
Signature(sig)
}
fn from(sig: ffi::Signature) -> Signature { Signature(sig) }
}
#[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> {
if d.is_human_readable() {
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 {
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
"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
// an invalid signature from a valid `Message` and `SecretKey`
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
noncedata_ptr), 1);
assert_eq!(
ffi::secp256k1_ecdsa_sign(
self.ctx,
&mut ret,
msg.as_c_ptr(),
sk.as_c_ptr(),
ffi::secp256k1_nonce_function_rfc6979,
noncedata_ptr
),
1
);
Signature::from(ret)
}
}
@ -289,20 +290,30 @@ impl<C: Signing> Secp256k1<C> {
}
fn sign_grind_with_check(
&self, msg: &Message,
&self,
msg: &Message,
sk: &SecretKey,
check: impl Fn(&ffi::Signature) -> bool) -> Signature {
let mut entropy_p : *const ffi::types::c_void = ptr::null();
let mut counter : u32 = 0;
check: impl Fn(&ffi::Signature) -> bool,
) -> Signature {
let mut entropy_p: *const ffi::types::c_void = ptr::null();
let mut counter: u32 = 0;
let mut extra_entropy = [0u8; 32];
loop {
unsafe {
let mut ret = ffi::Signature::new();
// We can assume the return value because it's not possible to construct
// an invalid signature from a valid `Message` and `SecretKey`
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
entropy_p), 1);
assert_eq!(
ffi::secp256k1_ecdsa_sign(
self.ctx,
&mut ret,
msg.as_c_ptr(),
sk.as_c_ptr(),
ffi::secp256k1_nonce_function_rfc6979,
entropy_p
),
1
);
if check(&ret) {
return Signature::from(ret);
}
@ -324,8 +335,13 @@ impl<C: Signing> Secp256k1<C> {
/// of signing operation performed by this function is exponential in the
/// number of bytes grinded.
/// Requires a signing capable context.
pub fn sign_ecdsa_grind_r(&self, msg: &Message, sk: &SecretKey, bytes_to_grind: usize) -> Signature {
let len_check = |s : &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
pub fn sign_ecdsa_grind_r(
&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)
}
@ -364,9 +380,16 @@ impl<C: Verification> Secp256k1<C> {
/// # }
/// ```
#[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 {
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)
} else {
Ok(())

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -153,11 +153,8 @@
// Coding conventions
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
#![allow(clippy::missing_safety_doc)]
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
// Experimental features we need.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(bench, feature(test))]
@ -184,29 +181,30 @@ pub mod schnorr;
#[cfg(feature = "serde")]
mod serde_util;
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub use rand;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub use serde;
use core::marker::PhantomData;
use core::{fmt, mem, str};
#[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-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_attr(docsrs, doc(cfg(feature = "global-context")))]
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};
use crate::ffi::{CPtr, impl_array_newtype, types::AlignedType};
pub use crate::context::*;
use crate::ffi::types::AlignedType;
use crate::ffi::{impl_array_newtype, CPtr};
#[cfg(feature = "bitcoin-hashes")]
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,
/// 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_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl ThirtyTwoByteHash for hashes::sha256::Hash {
fn into_32(self) -> [u8; 32] {
self.into_inner()
}
fn into_32(self) -> [u8; 32] { self.into_inner() }
}
#[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl ThirtyTwoByteHash for hashes::sha256d::Hash {
fn into_32(self) -> [u8; 32] {
self.into_inner()
}
fn into_32(self) -> [u8; 32] { self.into_inner() }
}
#[cfg(feature = "bitcoin-hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> {
fn into_32(self) -> [u8; 32] {
self.into_inner()
}
fn into_32(self) -> [u8; 32] { self.into_inner() }
}
/// A (hashed) message input to an ECDSA signature.
@ -260,7 +252,7 @@ impl Message {
ret[..].copy_from_slice(data);
Ok(Message(ret))
}
_ => Err(Error::InvalidMessage)
_ => Err(Error::InvalidMessage),
}
}
@ -291,9 +283,7 @@ impl Message {
impl<T: ThirtyTwoByteHash> From<T> for Message {
/// Converts a 32-byte hash directly to a message without error paths.
fn from(t: T) -> Message {
Message(t.into_32())
}
fn from(t: T) -> Message { Message(t.into_32()) }
}
impl fmt::LowerHex for Message {
@ -306,9 +296,7 @@ impl fmt::LowerHex for Message {
}
impl fmt::Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(self, f)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
}
/// An ECDSA error
@ -353,7 +341,9 @@ impl fmt::Display for Error {
InvalidRecoveryId => f.write_str("bad recovery id"),
InvalidTweak => f.write_str("bad tweak"),
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),
}
}
@ -379,7 +369,6 @@ impl std::error::Error for Error {
}
}
/// The secp256k1 engine, used to execute all signature operations.
pub struct Secp256k1<C: Context> {
ctx: *mut ffi::Context,
@ -396,7 +385,7 @@ impl<C: Context> PartialEq for Secp256k1<C> {
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> {
fn drop(&mut self) {
@ -414,14 +403,11 @@ impl<C: Context> fmt::Debug for Secp256k1<C> {
}
impl<C: Context> Secp256k1<C> {
/// Getter for the raw pointer to the underlying secp256k1 context. This
/// shouldn't be needed with normal usage of the library. It enables
/// extending the Secp256k1 with more cryptographic algorithms outside of
/// this crate.
pub fn ctx(&self) -> &*mut ffi::Context {
&self.ctx
}
pub fn ctx(&self) -> &*mut ffi::Context { &self.ctx }
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
pub fn preallocate_size_gen() -> usize {
@ -468,8 +454,10 @@ impl<C: Signing> Secp256k1<C> {
#[inline]
#[cfg(any(test, feature = "rand"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
pub fn generate_keypair<R: rand::Rng + ?Sized>(&self, rng: &mut R)
-> (key::SecretKey, key::PublicKey) {
pub fn generate_keypair<R: rand::Rng + ?Sized>(
&self,
rng: &mut R,
) -> (key::SecretKey, key::PublicKey) {
let sk = key::SecretKey::new(rng);
let pk = key::PublicKey::from_secret_key(self, &sk);
(sk, pk)
@ -525,38 +513,38 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
let mut i = 0;
for &b in src {
target[i] = HEX_TABLE[usize::from(b >> 4)];
target[i+1] = HEX_TABLE[usize::from(b & 0b00001111)];
i +=2 ;
target[i + 1] = HEX_TABLE[usize::from(b & 0b00001111)];
i += 2;
}
let result = &target[..hex_len];
debug_assert!(str::from_utf8(result).is_ok());
return unsafe { Ok(str::from_utf8_unchecked(result)) };
}
#[cfg(test)]
mod tests {
use std::marker::PhantomData;
use std::str::FromStr;
use rand::{RngCore, thread_rng};
use rand::{thread_rng, RngCore};
#[cfg(target_arch = "wasm32")]
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::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 {
($hex:expr) => ({
($hex:expr) => {{
let mut result = vec![0; $hex.len() / 2];
from_hex($hex, &mut result).expect("valid hex string");
result
});
}};
}
#[test]
#[cfg(feature = "std")]
fn test_manual_create_destroy() {
@ -565,9 +553,12 @@ mod tests {
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
let size = 0;
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, 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 full: Secp256k1<AllPreallocated> =
Secp256k1 { ctx: ctx_full, 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 msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -579,7 +570,9 @@ mod tests {
assert!(vrfy.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_sign) };
@ -595,9 +588,9 @@ mod tests {
let ctx_sign = Secp256k1::signing_only();
let ctx_vrfy = Secp256k1::verification_only();
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 vrfy = unsafe {Secp256k1::from_raw_verification_only(ctx_vrfy.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 vrfy = unsafe { Secp256k1::from_raw_verification_only(ctx_vrfy.ctx) };
let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -613,7 +606,6 @@ mod tests {
ManuallyDrop::drop(&mut full);
ManuallyDrop::drop(&mut sign);
ManuallyDrop::drop(&mut vrfy);
}
drop(ctx_full);
drop(ctx_sign);
@ -640,8 +632,8 @@ mod tests {
let sign = Secp256k1::preallocated_signing_only(&mut buf_sign).unwrap();
let vrfy = Secp256k1::preallocated_verification_only(&mut buf_vfy).unwrap();
// 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.
// 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.
let (sk, pk) = full.generate_keypair(&mut thread_rng());
let msg = Message::from_slice(&[2u8; 32]).unwrap();
@ -729,15 +721,18 @@ mod tests {
assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
).is_err());
)
.is_err());
assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
).is_err());
)
.is_err());
assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
).is_err());
)
.is_err());
assert!(ecdsa::Signature::from_str(
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
@ -745,7 +740,8 @@ mod tests {
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
).is_err());
)
.is_err());
// 71 byte signature
let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776";
@ -862,15 +858,23 @@ mod tests {
#[test]
fn test_bad_slice() {
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
Err(Error::InvalidSignature));
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
Err(Error::InvalidSignature));
assert_eq!(
ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
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]),
Err(Error::InvalidMessage));
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]),
Err(Error::InvalidMessage));
assert_eq!(
Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
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(&[1; constants::MESSAGE_SIZE]).is_ok());
}
@ -881,7 +885,7 @@ mod tests {
const AMOUNT: usize = 1024;
for i in 0..AMOUNT {
// 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 result_buf = [0u8; AMOUNT];
let src = &mut src_buf[0..i];
@ -892,9 +896,8 @@ mod tests {
assert_eq!(src, &result_buf[..i]);
}
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; 3]).is_err());
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; 4]).is_ok());
assert!(from_hex("a", &mut [0u8; 4]).is_err());
@ -909,7 +912,9 @@ mod tests {
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
let msg = Message::from_slice(&msg).unwrap();
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 = ecdsa::Signature::from_compact(&expected_sig).unwrap();
@ -948,7 +953,9 @@ mod tests {
let secp = Secp256k1::new();
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
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 = ecdsa::Signature::from_compact(&expected_sig).unwrap();
@ -964,7 +971,9 @@ mod tests {
let secp = Secp256k1::new();
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
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 sig = secp.sign_ecdsa_grind_r(&msg, &sk, 2);
@ -977,7 +986,7 @@ mod tests {
#[cfg(any(feature = "alloc", feature = "std"))]
#[test]
fn test_serde() {
use serde_test::{Configure, Token, assert_tokens};
use serde_test::{assert_tokens, Configure, Token};
let s = Secp256k1::new();
@ -985,11 +994,10 @@ mod tests {
let sk = SecretKey::from_slice(&[2; 32]).unwrap();
let sig = s.sign_ecdsa(&msg, &sk);
static SIG_BYTES: [u8; 71] = [
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148,
8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254,
226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225,
147, 247, 99, 25, 15, 103, 118
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, 179, 76, 119, 72,
102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, 8, 230, 206, 119, 75, 2, 32, 40,
118, 231, 16, 47, 32, 79, 107, 254, 226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125,
75, 1, 0, 98, 225, 147, 247, 99, 25, 15, 103, 118,
];
static SIG_STR: &str = "\
30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\
@ -1003,7 +1011,6 @@ mod tests {
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
}
#[cfg(feature = "global-context")]
@ -1033,37 +1040,29 @@ mod tests {
let hash = hashes::sha256::Hash::hash(test_bytes);
let msg = Message::from(hash);
assert_eq!(msg.0, hash.into_inner());
assert_eq!(
msg,
Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes)
);
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes));
let hash = hashes::sha256d::Hash::hash(test_bytes);
let msg = Message::from(hash);
assert_eq!(msg.0, hash.into_inner());
assert_eq!(
msg,
Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes)
);
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes));
}
}
#[cfg(bench)]
mod benches {
use test::{Bencher, black_box};
use rand::{RngCore, thread_rng};
use rand::rngs::mock::StepRng;
use rand::{thread_rng, RngCore};
use test::{black_box, Bencher};
use super::{Message, Secp256k1};
#[bench]
#[cfg(any(feature = "alloc", feature = "std"))]
pub fn generate(bh: &mut Bencher) {
let s = Secp256k1::new();
let mut r = StepRng::new(1, 1);
bh.iter( || {
bh.iter(|| {
let (sk, pk) = s.generate_keypair(&mut r);
black_box(sk);
black_box(pk);

View File

@ -24,7 +24,7 @@ macro_rules! impl_pretty_debug {
f.write_str(")")
}
}
}
};
}
/// 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] = [
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 {
@ -39,9 +39,7 @@ impl Scalar {
/// Generates a random scalar
#[cfg(any(test, feature = "rand-std"))]
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
pub fn random() -> Self {
Self::random_custom(rand::thread_rng())
}
pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }
/// Generates a random scalar using supplied RNG
#[cfg(any(test, feature = "rand"))]
@ -88,9 +86,7 @@ impl Scalar {
}
/// Serializes to big endian bytes
pub fn to_be_bytes(self) -> [u8; 32] {
self.0
}
pub fn to_be_bytes(self) -> [u8; 32] { self.0 }
/// Serializes to little endian bytes
pub fn to_le_bytes(self) -> [u8; 32] {
@ -101,9 +97,7 @@ impl Scalar {
// returns a reference to internal bytes
// non-public to not leak the internal representation
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] {
&self.0
}
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { &self.0 }
pub(crate) fn as_c_ptr(&self) -> *const u8 {
use secp256k1_sys::CPtr;
@ -113,20 +107,16 @@ impl Scalar {
}
impl From<crate::SecretKey> for Scalar {
fn from(value: crate::SecretKey) -> Self {
Scalar(value.secret_bytes())
}
fn from(value: crate::SecretKey) -> Self { Scalar(value.secret_bytes()) }
}
/// Error returned when the value of scalar is invalid - larger than the curve order.
// Intentionally doesn't implement `Copy` to improve forward compatibility.
// Same reason for `non_exhaustive`.
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[non_exhaustive]
pub struct OutOfRangeError {
}
pub struct OutOfRangeError {}
impl fmt::Display for OutOfRangeError {
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"))]
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::ffi::{self, CPtr, impl_array_newtype};
#[cfg(all(feature = "global-context", feature = "rand-std"))]
use crate::SECP256K1;
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
/// Represents a Schnorr signature.
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> {
if d.is_human_readable() {
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 {
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
"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 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(self, f)
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
}
impl str::FromStr for Signature {
@ -66,9 +63,8 @@ impl str::FromStr for Signature {
fn from_str(s: &str) -> Result<Signature, Error> {
let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
match from_hex(s, &mut res) {
Ok(constants::SCHNORR_SIGNATURE_SIZE) => {
Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE])
}
Ok(constants::SCHNORR_SIGNATURE_SIZE) =>
Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE]),
_ => Err(Error::InvalidSignature),
}
}
@ -130,11 +126,7 @@ impl<C: Signing> Secp256k1<C> {
}
/// Create a schnorr signature without using any auxiliary random data.
pub fn sign_schnorr_no_aux_rand(
&self,
msg: &Message,
keypair: &KeyPair,
) -> Signature {
pub fn sign_schnorr_no_aux_rand(&self, msg: &Message, keypair: &KeyPair) -> Signature {
self.sign_schnorr_helper(msg, keypair, ptr::null())
}
@ -145,11 +137,7 @@ impl<C: Signing> Secp256k1<C> {
keypair: &KeyPair,
aux_rand: &[u8; 32],
) -> Signature {
self.sign_schnorr_helper(
msg,
keypair,
aux_rand.as_c_ptr() as *const ffi::types::c_uchar,
)
self.sign_schnorr_helper(msg, keypair, aux_rand.as_c_ptr() as *const ffi::types::c_uchar)
}
/// Create a schnorr signature using the given random number generator to
@ -199,15 +187,15 @@ impl<C: Verification> Secp256k1<C> {
mod tests {
use core::str::FromStr;
use rand::{RngCore, rngs::ThreadRng, thread_rng};
use rand::rngs::ThreadRng;
use rand::{thread_rng, RngCore};
#[cfg(target_arch = "wasm32")]
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 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")))]
macro_rules! hex_32 {
@ -231,25 +219,17 @@ mod tests {
#[test]
#[cfg(all(feature = "std", feature = "rand-std"))]
fn schnor_sign_with_rng_verify() {
sign_helper(|secp, msg, seckey, mut rng| {
secp.sign_schnorr_with_rng(msg, seckey, &mut rng)
})
sign_helper(|secp, msg, seckey, mut rng| secp.sign_schnorr_with_rng(msg, seckey, &mut rng))
}
#[test]
#[cfg(all(feature = "std", feature = "rand-std"))]
fn schnorr_sign_verify() {
sign_helper(|secp, msg, seckey, _| {
secp.sign_schnorr(msg, seckey)
})
}
fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
#[test]
#[cfg(all(feature = "std", feature = "rand-std"))]
fn schnorr_sign_no_aux_rand_verify() {
sign_helper(|secp, msg, seckey, _| {
secp.sign_schnorr_no_aux_rand(msg, seckey)
})
sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
}
#[cfg(all(feature = "std", feature = "rand-std"))]
@ -291,8 +271,7 @@ mod tests {
hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
let sig = secp
.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
let sig = secp.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
assert_eq!(expected_sig, sig);
}
@ -306,8 +285,9 @@ mod tests {
let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
let msg = Message::from_slice(&hex_msg).unwrap();
let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
let pubkey =
XOnlyPublicKey::from_str("B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390")
let pubkey = XOnlyPublicKey::from_str(
"B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
)
.unwrap();
assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
@ -398,14 +378,21 @@ mod tests {
pk
};
#[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!(
pk.to_string(),
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
);
assert_eq!(
XOnlyPublicKey::from_str("18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166")
XOnlyPublicKey::from_str(
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
)
.unwrap(),
pk
);
@ -465,8 +452,7 @@ mod tests {
let msg = Message::from_slice(&[1; 32]).unwrap();
let keypair = KeyPair::from_seckey_slice(&s, &[2; 32]).unwrap();
let aux = [3u8; 32];
let sig = s
.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
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,
@ -479,8 +465,8 @@ mod tests {
";
static PK_BYTES: [u8; 32] = [
24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127,
48, 170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102
24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 48,
170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102,
];
static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
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::String(SIG_STR)]);
#[rustfmt::skip]
assert_tokens(&pk.compact(), &[
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),

View File

@ -15,7 +15,11 @@
//! Helpers for displaying secret values
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 {
// Default hasher exists only in standard library and not alloc
($thing:ident) => {
@ -27,7 +31,7 @@ macro_rules! impl_display_secret {
const DEBUG_HASH_TAG: &[u8] = &[
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,
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22,
]; // =SHA256(b"rust-secp256k1DEBUG");
let mut hasher = std::collections::hash_map::DefaultHasher::new();
@ -37,9 +41,7 @@ macro_rules! impl_display_secret {
hasher.write(&self.secret_bytes());
let hash = hasher.finish();
f.debug_tuple(stringify!($thing))
.field(&format_args!("#{:016x}", hash))
.finish()
f.debug_tuple(stringify!($thing)).field(&format_args!("#{:016x}", hash)).finish()
}
}
@ -57,9 +59,7 @@ macro_rules! impl_display_secret {
engine.input(&self.secret_bytes());
let hash = sha256::Hash::from_engine(engine);
f.debug_tuple(stringify!($thing))
.field(&format_args!("#{:016x}", hash))
.finish()
f.debug_tuple(stringify!($thing)).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>")
}
}
}
};
}
/// Helper struct for safely printing secrets (like [`SecretKey`] value).
@ -84,7 +84,7 @@ macro_rules! impl_display_secret {
/// [`Debug`]: fmt::Debug
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DisplaySecret {
secret: [u8; SECRET_KEY_SIZE]
secret: [u8; SECRET_KEY_SIZE],
}
impl fmt::Debug for DisplaySecret {
@ -92,9 +92,7 @@ impl fmt::Debug for DisplaySecret {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut slice = [0u8; SECRET_KEY_SIZE * 2];
let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed");
f.debug_tuple("DisplaySecret")
.field(&hex)
.finish()
f.debug_tuple("DisplaySecret").field(&hex).finish()
}
}
@ -138,9 +136,7 @@ impl SecretKey {
/// # }
/// ```
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
}
impl KeyPair {
@ -173,9 +169,7 @@ impl KeyPair {
/// # }
/// ```
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
}
impl SharedSecret {
@ -211,7 +205,5 @@ impl SharedSecret {
/// # }
/// ```
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
}

View File

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

View File

@ -5,12 +5,13 @@ extern crate bincode;
extern crate cbor;
extern crate secp256k1;
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
#[cfg(feature = "global-context")]
use secp256k1::{Secp256k1, KeyPair};
use secp256k1::{KeyPair, Secp256k1};
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
// Arbitrary key data.
#[rustfmt::skip]
static SK_BYTES: [u8; 32] = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
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,
];
#[rustfmt::skip]
static PK_BYTES: [u8; 33] = [
0x02,
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,
];
#[rustfmt::skip]
static XONLY_PK_BYTES: [u8; 32] = [
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f,
0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d,
@ -67,7 +70,8 @@ fn bincode_key_pair() {
#[test]
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();
assert_eq!(ser, XONLY_PK_BYTES);