Run cargo fmt
Run the command `cargo +nightly fmt` to fix formatting issues. The formatter got confused in one place, adding an incorrect indentation, this was manually fixed.
This commit is contained in:
parent
41449e455d
commit
e0e575dde7
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
101
src/context.rs
101
src/context.rs
|
@ -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"))))]
|
||||
|
@ -41,13 +40,17 @@ pub mod global {
|
|||
impl Deref for GlobalContext {
|
||||
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 {
|
||||
static ONCE: Once = Once::new();
|
||||
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 {}
|
||||
|
@ -195,16 +197,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());
|
||||
}
|
||||
|
@ -220,9 +228,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> {
|
||||
|
@ -231,9 +237,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> {
|
||||
|
@ -242,24 +246,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,
|
||||
}
|
||||
|
@ -313,7 +315,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.
|
||||
|
@ -323,13 +326,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.
|
||||
///
|
||||
|
@ -342,7 +345,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,
|
||||
|
@ -353,15 +358,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.
|
||||
///
|
||||
|
@ -374,7 +379,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,
|
||||
|
@ -385,15 +392,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.
|
||||
///
|
||||
|
@ -406,7 +413,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,
|
||||
|
|
62
src/ecdh.rs
62
src/ecdh.rs
|
@ -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;
|
||||
|
@ -51,7 +54,7 @@ impl SharedSecret {
|
|||
pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
|
||||
let mut buf = [0u8; SHARED_SECRET_SIZE];
|
||||
let res = unsafe {
|
||||
ffi::secp256k1_ecdh(
|
||||
ffi::secp256k1_ecdh(
|
||||
ffi::secp256k1_context_no_precomp,
|
||||
buf.as_mut_ptr(),
|
||||
point.as_c_ptr(),
|
||||
|
@ -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,7 @@ 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,
|
||||
|
@ -289,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
135
src/ecdsa/mod.rs
135
src/ecdsa/mod.rs
|
@ -4,7 +4,7 @@
|
|||
mod recovery;
|
||||
pub mod serialized_signature;
|
||||
|
||||
use core::{fmt, str, ptr};
|
||||
use core::{fmt, ptr, str};
|
||||
|
||||
#[cfg(feature = "recovery")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
|
||||
|
@ -22,9 +22,7 @@ use crate::{
|
|||
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 {
|
||||
|
@ -49,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();
|
||||
|
@ -70,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 {
|
||||
|
@ -93,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();
|
||||
|
@ -143,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
|
||||
|
@ -198,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")]
|
||||
|
@ -233,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,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -259,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)
|
||||
}
|
||||
}
|
||||
|
@ -287,33 +290,43 @@ 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;
|
||||
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);
|
||||
if check(&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)]
|
||||
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
|
||||
);
|
||||
if check(&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
|
||||
|
@ -322,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)
|
||||
}
|
||||
|
||||
|
@ -362,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(())
|
||||
|
|
|
@ -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> {
|
||||
match id {
|
||||
0..=3 => Ok(RecoveryId(id)),
|
||||
_ => Err(Error::InvalidRecoveryId)
|
||||
#[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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
|
||||
|
@ -315,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());
|
||||
|
@ -339,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());
|
||||
|
@ -356,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());
|
||||
|
@ -375,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());
|
||||
|
@ -419,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[..]);
|
||||
|
@ -446,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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
551
src/key.rs
551
src/key.rs
File diff suppressed because it is too large
Load Diff
221
src/lib.rs
221
src/lib.rs
|
@ -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();
|
||||
|
@ -709,7 +701,7 @@ mod tests {
|
|||
assert!(ecdsa::Signature::from_compact(&compact[0..4]).is_err());
|
||||
assert!(ecdsa::Signature::from_der(&compact[..]).is_err());
|
||||
assert!(ecdsa::Signature::from_der(&der[0..4]).is_err());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -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";
|
||||
|
@ -796,14 +792,14 @@ mod tests {
|
|||
if compact[0] < 0x80 {
|
||||
assert_eq!(sig, low_r_sig);
|
||||
} 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);
|
||||
}
|
||||
#[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));
|
||||
#[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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -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());
|
||||
|
@ -902,14 +905,16 @@ mod tests {
|
|||
}
|
||||
|
||||
#[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"))]
|
||||
fn test_noncedata() {
|
||||
let secp = Secp256k1::new();
|
||||
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();
|
||||
|
||||
|
@ -919,7 +924,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[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"))]
|
||||
fn test_low_s() {
|
||||
// nb this is a transaction on testnet
|
||||
|
@ -942,13 +947,15 @@ mod tests {
|
|||
}
|
||||
|
||||
#[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"))]
|
||||
fn test_low_r() {
|
||||
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();
|
||||
|
||||
|
@ -958,13 +965,15 @@ mod tests {
|
|||
}
|
||||
|
||||
#[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"))]
|
||||
fn test_grind_r() {
|
||||
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);
|
||||
|
@ -973,11 +982,11 @@ mod tests {
|
|||
}
|
||||
|
||||
#[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"))]
|
||||
#[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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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"))]
|
||||
#[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"))]
|
||||
|
@ -276,7 +256,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
#[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() {
|
||||
let secp = Secp256k1::new();
|
||||
|
||||
|
@ -291,14 +271,13 @@ 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);
|
||||
}
|
||||
|
||||
#[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"))]
|
||||
fn schnorr_verify() {
|
||||
let secp = Secp256k1::new();
|
||||
|
@ -306,9 +285,10 @@ 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")
|
||||
.unwrap();
|
||||
let pubkey = XOnlyPublicKey::from_str(
|
||||
"B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
|
||||
}
|
||||
|
@ -398,15 +378,22 @@ 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")
|
||||
.unwrap(),
|
||||
XOnlyPublicKey::from_str(
|
||||
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
|
||||
)
|
||||
.unwrap(),
|
||||
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]
|
||||
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
||||
fn test_serde() {
|
||||
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,9 +134,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 {
|
||||
|
@ -172,9 +168,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 {
|
||||
|
@ -210,7 +204,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() } }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -5,9 +5,9 @@ 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.
|
||||
|
||||
|
@ -70,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);
|
||||
|
|
Loading…
Reference in New Issue