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;
|
extern crate secp256k1;
|
||||||
|
|
||||||
use bitcoin_hashes::{sha256, Hash};
|
use bitcoin_hashes::{sha256, Hash};
|
||||||
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, ecdsa, Signing, Verification};
|
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
|
||||||
|
|
||||||
fn verify<C: Verification>(secp: &Secp256k1<C>, msg: &[u8], sig: [u8; 64], pubkey: [u8; 33]) -> Result<bool, Error> {
|
fn verify<C: Verification>(
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
msg: &[u8],
|
||||||
|
sig: [u8; 64],
|
||||||
|
pubkey: [u8; 33],
|
||||||
|
) -> Result<bool, Error> {
|
||||||
let msg = sha256::Hash::hash(msg);
|
let msg = sha256::Hash::hash(msg);
|
||||||
let msg = Message::from_slice(&msg)?;
|
let msg = Message::from_slice(&msg)?;
|
||||||
let sig = ecdsa::Signature::from_compact(&sig)?;
|
let sig = ecdsa::Signature::from_compact(&sig)?;
|
||||||
|
@ -13,7 +18,11 @@ fn verify<C: Verification>(secp: &Secp256k1<C>, msg: &[u8], sig: [u8; 64], pubke
|
||||||
Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok())
|
Ok(secp.verify_ecdsa(&msg, &sig, &pubkey).is_ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::Signature, Error> {
|
fn sign<C: Signing>(
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
msg: &[u8],
|
||||||
|
seckey: [u8; 32],
|
||||||
|
) -> Result<ecdsa::Signature, Error> {
|
||||||
let msg = sha256::Hash::hash(msg);
|
let msg = sha256::Hash::hash(msg);
|
||||||
let msg = Message::from_slice(&msg)?;
|
let msg = Message::from_slice(&msg)?;
|
||||||
let seckey = SecretKey::from_slice(&seckey)?;
|
let seckey = SecretKey::from_slice(&seckey)?;
|
||||||
|
@ -23,8 +32,14 @@ fn sign<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result
|
||||||
fn main() {
|
fn main() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let seckey = [59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28];
|
let seckey = [
|
||||||
let pubkey = [2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54];
|
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253,
|
||||||
|
102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
|
||||||
|
];
|
||||||
|
let pubkey = [
|
||||||
|
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141,
|
||||||
|
134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
|
||||||
|
];
|
||||||
let msg = b"This is some message";
|
let msg = b"This is some message";
|
||||||
|
|
||||||
let signature = sign(&secp, msg, seckey).unwrap();
|
let signature = sign(&secp, msg, seckey).unwrap();
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
|
|
||||||
extern crate bitcoin_hashes;
|
extern crate bitcoin_hashes;
|
||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
|
|
||||||
use bitcoin_hashes::{sha256, Hash};
|
use bitcoin_hashes::{sha256, Hash};
|
||||||
use secp256k1::{Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification, ecdsa};
|
use secp256k1::{ecdsa, Error, Message, PublicKey, Secp256k1, SecretKey, Signing, Verification};
|
||||||
|
|
||||||
fn recover<C: Verification>(secp: &Secp256k1<C>,msg: &[u8],sig: [u8; 64],recovery_id: u8) -> Result<PublicKey, Error> {
|
fn recover<C: Verification>(
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
msg: &[u8],
|
||||||
|
sig: [u8; 64],
|
||||||
|
recovery_id: u8,
|
||||||
|
) -> Result<PublicKey, Error> {
|
||||||
let msg = sha256::Hash::hash(msg);
|
let msg = sha256::Hash::hash(msg);
|
||||||
let msg = Message::from_slice(&msg)?;
|
let msg = Message::from_slice(&msg)?;
|
||||||
let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?;
|
let id = ecdsa::RecoveryId::from_i32(recovery_id as i32)?;
|
||||||
|
@ -14,7 +18,11 @@ fn recover<C: Verification>(secp: &Secp256k1<C>,msg: &[u8],sig: [u8; 64],recover
|
||||||
secp.recover_ecdsa(&msg, &sig)
|
secp.recover_ecdsa(&msg, &sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_recovery<C: Signing>(secp: &Secp256k1<C>, msg: &[u8], seckey: [u8; 32]) -> Result<ecdsa::RecoverableSignature, Error> {
|
fn sign_recovery<C: Signing>(
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
msg: &[u8],
|
||||||
|
seckey: [u8; 32],
|
||||||
|
) -> Result<ecdsa::RecoverableSignature, Error> {
|
||||||
let msg = sha256::Hash::hash(msg);
|
let msg = sha256::Hash::hash(msg);
|
||||||
let msg = Message::from_slice(&msg)?;
|
let msg = Message::from_slice(&msg)?;
|
||||||
let seckey = SecretKey::from_slice(&seckey)?;
|
let seckey = SecretKey::from_slice(&seckey)?;
|
||||||
|
@ -25,22 +33,19 @@ fn main() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
|
|
||||||
let seckey = [
|
let seckey = [
|
||||||
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107,
|
59, 148, 11, 85, 134, 130, 61, 253, 2, 174, 59, 70, 27, 180, 51, 107, 94, 203, 174, 253,
|
||||||
94, 203, 174, 253, 102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
|
102, 39, 170, 146, 46, 252, 4, 143, 236, 12, 136, 28,
|
||||||
];
|
];
|
||||||
let pubkey = PublicKey::from_slice(&[
|
let pubkey = PublicKey::from_slice(&[
|
||||||
2,
|
2, 29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231, 245, 41, 91, 141,
|
||||||
29, 21, 35, 7, 198, 183, 43, 14, 208, 65, 139, 14, 112, 205, 128, 231,
|
134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
|
||||||
245, 41, 91, 141, 134, 245, 114, 45, 63, 82, 19, 251, 210, 57, 79, 54,
|
])
|
||||||
]).unwrap();
|
.unwrap();
|
||||||
let msg = b"This is some message";
|
let msg = b"This is some message";
|
||||||
|
|
||||||
let signature = sign_recovery(&secp, msg, seckey).unwrap();
|
let signature = sign_recovery(&secp, msg, seckey).unwrap();
|
||||||
|
|
||||||
let (recovery_id, serialize_sig) = signature.serialize_compact();
|
let (recovery_id, serialize_sig) = signature.serialize_compact();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8), Ok(pubkey));
|
||||||
recover(&secp, msg, serialize_sig, recovery_id.to_i32() as u8),
|
|
||||||
Ok(pubkey)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::mem::ManuallyDrop;
|
use core::mem::ManuallyDrop;
|
||||||
|
|
||||||
use crate::{Error, Secp256k1};
|
|
||||||
use crate::ffi::{self, CPtr, types::AlignedType};
|
|
||||||
use crate::ffi::types::{c_uint, c_void};
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
|
||||||
pub use self::alloc_only::*;
|
pub use self::alloc_only::*;
|
||||||
|
use crate::ffi::types::{c_uint, c_void, AlignedType};
|
||||||
|
use crate::ffi::{self, CPtr};
|
||||||
|
use crate::{Error, Secp256k1};
|
||||||
|
|
||||||
#[cfg(all(feature = "global-context", feature = "std"))]
|
#[cfg(all(feature = "global-context", feature = "std"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))]
|
#[cfg_attr(docsrs, doc(cfg(all(feature = "global-context", feature = "std"))))]
|
||||||
|
@ -47,7 +46,11 @@ pub mod global {
|
||||||
static mut CONTEXT: Option<Secp256k1<All>> = None;
|
static mut CONTEXT: Option<Secp256k1<All>> = None;
|
||||||
ONCE.call_once(|| unsafe {
|
ONCE.call_once(|| unsafe {
|
||||||
let mut ctx = Secp256k1::new();
|
let mut ctx = Secp256k1::new();
|
||||||
#[cfg(all(not(target_arch = "wasm32"), feature = "rand-std", not(feature = "global-context-less-secure")))]
|
#[cfg(all(
|
||||||
|
not(target_arch = "wasm32"),
|
||||||
|
feature = "rand-std",
|
||||||
|
not(feature = "global-context-less-secure")
|
||||||
|
))]
|
||||||
{
|
{
|
||||||
ctx.randomize(&mut rand::thread_rng());
|
ctx.randomize(&mut rand::thread_rng());
|
||||||
}
|
}
|
||||||
|
@ -58,7 +61,6 @@ pub mod global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A trait for all kinds of contexts that lets you define the exact flags and a function to
|
/// A trait for all kinds of contexts that lets you define the exact flags and a function to
|
||||||
/// deallocate memory. It isn't possible to implement this for types outside this crate.
|
/// deallocate memory. It isn't possible to implement this for types outside this crate.
|
||||||
pub unsafe trait Context: private::Sealed {
|
pub unsafe trait Context: private::Sealed {
|
||||||
|
@ -106,13 +108,13 @@ mod private {
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc"))))]
|
||||||
mod alloc_only {
|
mod alloc_only {
|
||||||
use crate::alloc::alloc;
|
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use super::private;
|
use super::private;
|
||||||
use crate::ffi::{self, types::{c_uint, c_void}};
|
use crate::alloc::alloc;
|
||||||
use crate::{Secp256k1, Signing, Verification, Context, AlignedType};
|
use crate::ffi::types::{c_uint, c_void};
|
||||||
|
use crate::ffi::{self};
|
||||||
|
use crate::{AlignedType, Context, Secp256k1, Signing, Verification};
|
||||||
|
|
||||||
impl private::Sealed for SignOnly {}
|
impl private::Sealed for SignOnly {}
|
||||||
impl private::Sealed for All {}
|
impl private::Sealed for All {}
|
||||||
|
@ -199,12 +201,18 @@ mod alloc_only {
|
||||||
|
|
||||||
#[allow(unused_mut)] // ctx is not mutated under some feature combinations.
|
#[allow(unused_mut)] // ctx is not mutated under some feature combinations.
|
||||||
let mut ctx = Secp256k1 {
|
let mut ctx = Secp256k1 {
|
||||||
ctx: unsafe { ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS) },
|
ctx: unsafe {
|
||||||
|
ffi::secp256k1_context_preallocated_create(ptr as *mut c_void, C::FLAGS)
|
||||||
|
},
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
size,
|
size,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), feature = "rand-std", not(feature = "global-context-less-secure")))]
|
#[cfg(all(
|
||||||
|
not(target_arch = "wasm32"),
|
||||||
|
feature = "rand-std",
|
||||||
|
not(feature = "global-context-less-secure")
|
||||||
|
))]
|
||||||
{
|
{
|
||||||
ctx.randomize(&mut rand::thread_rng());
|
ctx.randomize(&mut rand::thread_rng());
|
||||||
}
|
}
|
||||||
|
@ -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 enabled, context will have been randomized using `thread_rng`.
|
||||||
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
||||||
/// for `Secp256k1::gen_new()`).
|
/// for `Secp256k1::gen_new()`).
|
||||||
pub fn new() -> Secp256k1<All> {
|
pub fn new() -> Secp256k1<All> { Secp256k1::gen_new() }
|
||||||
Secp256k1::gen_new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Secp256k1<SignOnly> {
|
impl Secp256k1<SignOnly> {
|
||||||
|
@ -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 enabled, context will have been randomized using `thread_rng`.
|
||||||
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
||||||
/// for `Secp256k1::gen_new()`).
|
/// for `Secp256k1::gen_new()`).
|
||||||
pub fn signing_only() -> Secp256k1<SignOnly> {
|
pub fn signing_only() -> Secp256k1<SignOnly> { Secp256k1::gen_new() }
|
||||||
Secp256k1::gen_new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Secp256k1<VerifyOnly> {
|
impl Secp256k1<VerifyOnly> {
|
||||||
|
@ -242,15 +246,11 @@ mod alloc_only {
|
||||||
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
|
/// If `rand-std` feature is enabled, context will have been randomized using `thread_rng`.
|
||||||
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
/// If `rand-std` feature is not enabled please consider randomizing the context (see docs
|
||||||
/// for `Secp256k1::gen_new()`).
|
/// for `Secp256k1::gen_new()`).
|
||||||
pub fn verification_only() -> Secp256k1<VerifyOnly> {
|
pub fn verification_only() -> Secp256k1<VerifyOnly> { Secp256k1::gen_new() }
|
||||||
Secp256k1::gen_new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Secp256k1<All> {
|
impl Default for Secp256k1<All> {
|
||||||
fn default() -> Self {
|
fn default() -> Self { Self::new() }
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> Clone for Secp256k1<C> {
|
impl<C: Context> Clone for Secp256k1<C> {
|
||||||
|
@ -259,7 +259,9 @@ mod alloc_only {
|
||||||
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
|
let layout = alloc::Layout::from_size_align(size, ALIGN_TO).unwrap();
|
||||||
let ptr = unsafe { alloc::alloc(layout) };
|
let ptr = unsafe { alloc::alloc(layout) };
|
||||||
Secp256k1 {
|
Secp256k1 {
|
||||||
ctx: unsafe { ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void) },
|
ctx: unsafe {
|
||||||
|
ffi::secp256k1_context_preallocated_clone(self.ctx, ptr as *mut c_void)
|
||||||
|
},
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
size,
|
size,
|
||||||
}
|
}
|
||||||
|
@ -313,7 +315,8 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
|
||||||
ctx: unsafe {
|
ctx: unsafe {
|
||||||
ffi::secp256k1_context_preallocated_create(
|
ffi::secp256k1_context_preallocated_create(
|
||||||
buf.as_mut_c_ptr() as *mut c_void,
|
buf.as_mut_c_ptr() as *mut c_void,
|
||||||
C::FLAGS)
|
C::FLAGS,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
size: 0, // We don't care about the size because it's the caller responsibility to deallocate.
|
size: 0, // We don't care about the size because it's the caller responsibility to deallocate.
|
||||||
|
@ -323,13 +326,13 @@ impl<'buf, C: Context + 'buf> Secp256k1<C> {
|
||||||
|
|
||||||
impl<'buf> Secp256k1<AllPreallocated<'buf>> {
|
impl<'buf> Secp256k1<AllPreallocated<'buf>> {
|
||||||
/// Creates a new Secp256k1 context with all capabilities
|
/// Creates a new Secp256k1 context with all capabilities
|
||||||
pub fn preallocated_new(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
|
pub fn preallocated_new(
|
||||||
|
buf: &'buf mut [AlignedType],
|
||||||
|
) -> Result<Secp256k1<AllPreallocated<'buf>>, Error> {
|
||||||
Secp256k1::preallocated_gen_new(buf)
|
Secp256k1::preallocated_gen_new(buf)
|
||||||
}
|
}
|
||||||
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
|
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
|
||||||
pub fn preallocate_size() -> usize {
|
pub fn preallocate_size() -> usize { Self::preallocate_size_gen() }
|
||||||
Self::preallocate_size_gen()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a context from a raw context.
|
/// Create a context from a raw context.
|
||||||
///
|
///
|
||||||
|
@ -342,7 +345,9 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
|
||||||
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
||||||
/// * Violating these may lead to Undefined Behavior.
|
/// * Violating these may lead to Undefined Behavior.
|
||||||
///
|
///
|
||||||
pub unsafe fn from_raw_all(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
|
pub unsafe fn from_raw_all(
|
||||||
|
raw_ctx: *mut ffi::Context,
|
||||||
|
) -> ManuallyDrop<Secp256k1<AllPreallocated<'buf>>> {
|
||||||
ManuallyDrop::new(Secp256k1 {
|
ManuallyDrop::new(Secp256k1 {
|
||||||
ctx: raw_ctx,
|
ctx: raw_ctx,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
@ -353,15 +358,15 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
|
||||||
|
|
||||||
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
|
impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
|
||||||
/// Creates a new Secp256k1 context that can only be used for signing.
|
/// Creates a new Secp256k1 context that can only be used for signing.
|
||||||
pub fn preallocated_signing_only(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
|
pub fn preallocated_signing_only(
|
||||||
|
buf: &'buf mut [AlignedType],
|
||||||
|
) -> Result<Secp256k1<SignOnlyPreallocated<'buf>>, Error> {
|
||||||
Secp256k1::preallocated_gen_new(buf)
|
Secp256k1::preallocated_gen_new(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
|
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn preallocate_signing_size() -> usize {
|
pub fn preallocate_signing_size() -> usize { Self::preallocate_size_gen() }
|
||||||
Self::preallocate_size_gen()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a context from a raw context.
|
/// Create a context from a raw context.
|
||||||
///
|
///
|
||||||
|
@ -374,7 +379,9 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
|
||||||
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
||||||
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
|
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
|
||||||
///
|
///
|
||||||
pub unsafe fn from_raw_signing_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
|
pub unsafe fn from_raw_signing_only(
|
||||||
|
raw_ctx: *mut ffi::Context,
|
||||||
|
) -> ManuallyDrop<Secp256k1<SignOnlyPreallocated<'buf>>> {
|
||||||
ManuallyDrop::new(Secp256k1 {
|
ManuallyDrop::new(Secp256k1 {
|
||||||
ctx: raw_ctx,
|
ctx: raw_ctx,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
@ -385,15 +392,15 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
|
||||||
|
|
||||||
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
|
impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
|
||||||
/// Creates a new Secp256k1 context that can only be used for verification
|
/// Creates a new Secp256k1 context that can only be used for verification
|
||||||
pub fn preallocated_verification_only(buf: &'buf mut [AlignedType]) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
|
pub fn preallocated_verification_only(
|
||||||
|
buf: &'buf mut [AlignedType],
|
||||||
|
) -> Result<Secp256k1<VerifyOnlyPreallocated<'buf>>, Error> {
|
||||||
Secp256k1::preallocated_gen_new(buf)
|
Secp256k1::preallocated_gen_new(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
|
/// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for the context.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn preallocate_verification_size() -> usize {
|
pub fn preallocate_verification_size() -> usize { Self::preallocate_size_gen() }
|
||||||
Self::preallocate_size_gen()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a context from a raw context.
|
/// Create a context from a raw context.
|
||||||
///
|
///
|
||||||
|
@ -406,7 +413,9 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
|
||||||
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
/// * The user must handle the freeing of the context(using the correct functions) by himself.
|
||||||
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
|
/// * This list *is not* exhaustive, and any violation may lead to Undefined Behavior.
|
||||||
///
|
///
|
||||||
pub unsafe fn from_raw_verification_only(raw_ctx: *mut ffi::Context) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
|
pub unsafe fn from_raw_verification_only(
|
||||||
|
raw_ctx: *mut ffi::Context,
|
||||||
|
) -> ManuallyDrop<Secp256k1<VerifyOnlyPreallocated<'buf>>> {
|
||||||
ManuallyDrop::new(Secp256k1 {
|
ManuallyDrop::new(Secp256k1 {
|
||||||
ctx: raw_ctx,
|
ctx: raw_ctx,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
|
|
54
src/ecdh.rs
54
src/ecdh.rs
|
@ -15,11 +15,14 @@
|
||||||
//! Support for shared secret computations.
|
//! Support for shared secret computations.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use core::{borrow::Borrow, ptr, str};
|
use core::borrow::Borrow;
|
||||||
|
use core::{ptr, str};
|
||||||
|
|
||||||
use secp256k1_sys::types::{c_int, c_uchar, c_void};
|
use secp256k1_sys::types::{c_int, c_uchar, c_void};
|
||||||
|
|
||||||
use crate::{constants, Error, ffi::{self, CPtr}, key::{PublicKey, SecretKey}};
|
use crate::ffi::{self, CPtr};
|
||||||
|
use crate::key::{PublicKey, SecretKey};
|
||||||
|
use crate::{constants, Error};
|
||||||
|
|
||||||
// The logic for displaying shared secrets relies on this (see `secret.rs`).
|
// The logic for displaying shared secrets relies on this (see `secret.rs`).
|
||||||
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
|
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
|
||||||
|
@ -66,15 +69,11 @@ impl SharedSecret {
|
||||||
|
|
||||||
/// Returns the shared secret as a byte value.
|
/// Returns the shared secret as a byte value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] {
|
pub fn secret_bytes(&self) -> [u8; SHARED_SECRET_SIZE] { self.0 }
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a shared secret from `bytes` array.
|
/// Creates a shared secret from `bytes` array.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret {
|
pub fn from_bytes(bytes: [u8; SHARED_SECRET_SIZE]) -> SharedSecret { SharedSecret(bytes) }
|
||||||
SharedSecret(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a shared secret from `bytes` slice.
|
/// Creates a shared secret from `bytes` slice.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -85,7 +84,7 @@ impl SharedSecret {
|
||||||
ret[..].copy_from_slice(bytes);
|
ret[..].copy_from_slice(bytes);
|
||||||
Ok(SharedSecret(ret))
|
Ok(SharedSecret(ret))
|
||||||
}
|
}
|
||||||
_ => Err(Error::InvalidSharedSecret)
|
_ => Err(Error::InvalidSharedSecret),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,21 +95,17 @@ impl str::FromStr for SharedSecret {
|
||||||
let mut res = [0u8; SHARED_SECRET_SIZE];
|
let mut res = [0u8; SHARED_SECRET_SIZE];
|
||||||
match crate::from_hex(s, &mut res) {
|
match crate::from_hex(s, &mut res) {
|
||||||
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
|
Ok(SHARED_SECRET_SIZE) => Ok(SharedSecret::from_bytes(res)),
|
||||||
_ => Err(Error::InvalidSharedSecret)
|
_ => Err(Error::InvalidSharedSecret),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Borrow<[u8]> for SharedSecret {
|
impl Borrow<[u8]> for SharedSecret {
|
||||||
fn borrow(&self) -> &[u8] {
|
fn borrow(&self) -> &[u8] { &self.0 }
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<[u8]> for SharedSecret {
|
impl AsRef<[u8]> for SharedSecret {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] { &self.0 }
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a shared point from public key and secret key.
|
/// Creates a shared point from public key and secret key.
|
||||||
|
@ -162,7 +157,12 @@ pub fn shared_secret_point(point: &PublicKey, scalar: &SecretKey) -> [u8; 64] {
|
||||||
xy
|
xy
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn c_callback(output: *mut c_uchar, x: *const c_uchar, y: *const c_uchar, _data: *mut c_void) -> c_int {
|
unsafe extern "C" fn c_callback(
|
||||||
|
output: *mut c_uchar,
|
||||||
|
x: *const c_uchar,
|
||||||
|
y: *const c_uchar,
|
||||||
|
_data: *mut c_void,
|
||||||
|
) -> c_int {
|
||||||
ptr::copy_nonoverlapping(x, output, 32);
|
ptr::copy_nonoverlapping(x, output, 32);
|
||||||
ptr::copy_nonoverlapping(y, output.offset(32), 32);
|
ptr::copy_nonoverlapping(y, output.offset(32), 32);
|
||||||
1
|
1
|
||||||
|
@ -187,12 +187,12 @@ impl<'de> ::serde::Deserialize<'de> for SharedSecret {
|
||||||
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 32 byte SharedSecret"
|
"a hex string representing 32 byte SharedSecret",
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
|
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
|
||||||
"raw 32 bytes SharedSecret",
|
"raw 32 bytes SharedSecret",
|
||||||
SharedSecret::from_slice
|
SharedSecret::from_slice,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ mod tests {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
use crate::Secp256k1;
|
|
||||||
use super::SharedSecret;
|
use super::SharedSecret;
|
||||||
|
use crate::Secp256k1;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "rand-std", any(feature = "alloc", feature = "std")))]
|
||||||
|
@ -227,7 +227,9 @@ mod tests {
|
||||||
let x = [5u8; 32];
|
let x = [5u8; 32];
|
||||||
let y = [7u8; 32];
|
let y = [7u8; 32];
|
||||||
let mut output = [0u8; 64];
|
let mut output = [0u8; 64];
|
||||||
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), core::ptr::null_mut()) };
|
let res = unsafe {
|
||||||
|
super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), core::ptr::null_mut())
|
||||||
|
};
|
||||||
assert_eq!(res, 1);
|
assert_eq!(res, 1);
|
||||||
let mut new_x = [0u8; 32];
|
let mut new_x = [0u8; 32];
|
||||||
let mut new_y = [0u8; 32];
|
let mut new_y = [0u8; 32];
|
||||||
|
@ -242,6 +244,7 @@ mod tests {
|
||||||
#[cfg(all(feature = "std", feature = "rand-std", feature = "bitcoin-hashes-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std", feature = "bitcoin-hashes-std"))]
|
||||||
fn bitcoin_hashes_and_sys_generate_same_secret() {
|
fn bitcoin_hashes_and_sys_generate_same_secret() {
|
||||||
use bitcoin_hashes::{sha256, Hash, HashEngine};
|
use bitcoin_hashes::{sha256, Hash, HashEngine};
|
||||||
|
|
||||||
use crate::ecdh::shared_secret_point;
|
use crate::ecdh::shared_secret_point;
|
||||||
|
|
||||||
let s = Secp256k1::signing_only();
|
let s = Secp256k1::signing_only();
|
||||||
|
@ -265,7 +268,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
#[cfg(all(feature = "serde", any(feature = "alloc", feature = "std")))]
|
||||||
fn serde() {
|
fn serde() {
|
||||||
use serde_test::{Configure, Token, assert_tokens};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
static BYTES: [u8; 32] = [
|
static BYTES: [u8; 32] = [
|
||||||
1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
@ -289,13 +292,11 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
mod benches {
|
mod benches {
|
||||||
use test::{Bencher, black_box};
|
|
||||||
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
|
use test::{black_box, Bencher};
|
||||||
use crate::Secp256k1;
|
|
||||||
|
|
||||||
use super::SharedSecret;
|
use super::SharedSecret;
|
||||||
|
use crate::Secp256k1;
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_ecdh(bh: &mut Bencher) {
|
pub fn bench_ecdh(bh: &mut Bencher) {
|
||||||
|
@ -308,4 +309,3 @@ mod benches {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
mod recovery;
|
mod recovery;
|
||||||
pub mod serialized_signature;
|
pub mod serialized_signature;
|
||||||
|
|
||||||
use core::{fmt, str, ptr};
|
use core::{fmt, ptr, str};
|
||||||
|
|
||||||
#[cfg(feature = "recovery")]
|
#[cfg(feature = "recovery")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "recovery")))]
|
||||||
|
@ -22,9 +22,7 @@ use crate::{
|
||||||
pub struct Signature(pub(crate) ffi::Signature);
|
pub struct Signature(pub(crate) ffi::Signature);
|
||||||
|
|
||||||
impl fmt::Debug for Signature {
|
impl fmt::Debug for Signature {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
|
||||||
fmt::Display::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Signature {
|
impl fmt::Display for Signature {
|
||||||
|
@ -49,7 +47,9 @@ impl Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Converts a DER-encoded byte slice to a signature
|
/// Converts a DER-encoded byte slice to a signature
|
||||||
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der(data: &[u8]) -> Result<Signature, Error> {
|
||||||
if data.is_empty() {return Err(Error::InvalidSignature);}
|
if data.is_empty() {
|
||||||
|
return Err(Error::InvalidSignature);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ffi::Signature::new();
|
let mut ret = ffi::Signature::new();
|
||||||
|
@ -70,7 +70,7 @@ impl Signature {
|
||||||
/// Converts a 64-byte compact-encoded byte slice to a signature
|
/// Converts a 64-byte compact-encoded byte slice to a signature
|
||||||
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_compact(data: &[u8]) -> Result<Signature, Error> {
|
||||||
if data.len() != 64 {
|
if data.len() != 64 {
|
||||||
return Err(Error::InvalidSignature)
|
return Err(Error::InvalidSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -93,7 +93,9 @@ impl Signature {
|
||||||
/// 2016. It should never be used in new applications. This library does not
|
/// 2016. It should never be used in new applications. This library does not
|
||||||
/// support serializing to this "format"
|
/// support serializing to this "format"
|
||||||
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
|
pub fn from_der_lax(data: &[u8]) -> Result<Signature, Error> {
|
||||||
if data.is_empty() {return Err(Error::InvalidSignature);}
|
if data.is_empty() {
|
||||||
|
return Err(Error::InvalidSignature);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ffi::Signature::new();
|
let mut ret = ffi::Signature::new();
|
||||||
|
@ -143,16 +145,15 @@ impl Signature {
|
||||||
/// Obtains a raw pointer suitable for use with FFI functions
|
/// Obtains a raw pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
|
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
|
||||||
pub fn as_ptr(&self) -> *const ffi::Signature {
|
pub fn as_ptr(&self) -> *const ffi::Signature { self.as_c_ptr() }
|
||||||
self.as_c_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
/// Obtains a raw mutable pointer suitable for use with FFI functions
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated(since = "0.25.0", note = "Use Self::as_mut_c_ptr if you need to access the FFI layer")]
|
#[deprecated(
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature {
|
since = "0.25.0",
|
||||||
self.as_mut_c_ptr()
|
note = "Use Self::as_mut_c_ptr if you need to access the FFI layer"
|
||||||
}
|
)]
|
||||||
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::Signature { self.as_mut_c_ptr() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the signature in DER format
|
/// Serializes the signature in DER format
|
||||||
|
@ -198,21 +199,15 @@ impl Signature {
|
||||||
impl CPtr for Signature {
|
impl CPtr for Signature {
|
||||||
type Target = ffi::Signature;
|
type Target = ffi::Signature;
|
||||||
|
|
||||||
fn as_c_ptr(&self) -> *const Self::Target {
|
fn as_c_ptr(&self) -> *const Self::Target { &self.0 }
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target { &mut self.0 }
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new signature from a FFI signature
|
/// Creates a new signature from a FFI signature
|
||||||
impl From<ffi::Signature> for Signature {
|
impl From<ffi::Signature> for Signature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(sig: ffi::Signature) -> Signature {
|
fn from(sig: ffi::Signature) -> Signature { Signature(sig) }
|
||||||
Signature(sig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
@ -233,12 +228,12 @@ impl<'de> serde::Deserialize<'de> for Signature {
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(crate::serde_util::FromStrVisitor::new(
|
d.deserialize_str(crate::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing a DER encoded Signature"
|
"a hex string representing a DER encoded Signature",
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
|
d.deserialize_bytes(crate::serde_util::BytesVisitor::new(
|
||||||
"raw byte stream, that represents a DER encoded Signature",
|
"raw byte stream, that represents a DER encoded Signature",
|
||||||
Signature::from_der
|
Signature::from_der,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,9 +254,17 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
};
|
};
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid signature from a valid `Message` and `SecretKey`
|
// an invalid signature from a valid `Message` and `SecretKey`
|
||||||
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
|
assert_eq!(
|
||||||
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
ffi::secp256k1_ecdsa_sign(
|
||||||
noncedata_ptr), 1);
|
self.ctx,
|
||||||
|
&mut ret,
|
||||||
|
msg.as_c_ptr(),
|
||||||
|
sk.as_c_ptr(),
|
||||||
|
ffi::secp256k1_nonce_function_rfc6979,
|
||||||
|
noncedata_ptr
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
Signature::from(ret)
|
Signature::from(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,9 +290,11 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_grind_with_check(
|
fn sign_grind_with_check(
|
||||||
&self, msg: &Message,
|
&self,
|
||||||
|
msg: &Message,
|
||||||
sk: &SecretKey,
|
sk: &SecretKey,
|
||||||
check: impl Fn(&ffi::Signature) -> bool) -> Signature {
|
check: impl Fn(&ffi::Signature) -> bool,
|
||||||
|
) -> Signature {
|
||||||
let mut entropy_p: *const ffi::types::c_void = ptr::null();
|
let mut entropy_p: *const ffi::types::c_void = ptr::null();
|
||||||
let mut counter: u32 = 0;
|
let mut counter: u32 = 0;
|
||||||
let mut extra_entropy = [0u8; 32];
|
let mut extra_entropy = [0u8; 32];
|
||||||
|
@ -298,9 +303,17 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
let mut ret = ffi::Signature::new();
|
let mut ret = ffi::Signature::new();
|
||||||
// We can assume the return value because it's not possible to construct
|
// We can assume the return value because it's not possible to construct
|
||||||
// an invalid signature from a valid `Message` and `SecretKey`
|
// an invalid signature from a valid `Message` and `SecretKey`
|
||||||
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
|
assert_eq!(
|
||||||
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
|
ffi::secp256k1_ecdsa_sign(
|
||||||
entropy_p), 1);
|
self.ctx,
|
||||||
|
&mut ret,
|
||||||
|
msg.as_c_ptr(),
|
||||||
|
sk.as_c_ptr(),
|
||||||
|
ffi::secp256k1_nonce_function_rfc6979,
|
||||||
|
entropy_p
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
if check(&ret) {
|
if check(&ret) {
|
||||||
return Signature::from(ret);
|
return Signature::from(ret);
|
||||||
}
|
}
|
||||||
|
@ -322,7 +335,12 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
/// of signing operation performed by this function is exponential in the
|
/// of signing operation performed by this function is exponential in the
|
||||||
/// number of bytes grinded.
|
/// number of bytes grinded.
|
||||||
/// Requires a signing capable context.
|
/// Requires a signing capable context.
|
||||||
pub fn sign_ecdsa_grind_r(&self, msg: &Message, sk: &SecretKey, bytes_to_grind: usize) -> Signature {
|
pub fn sign_ecdsa_grind_r(
|
||||||
|
&self,
|
||||||
|
msg: &Message,
|
||||||
|
sk: &SecretKey,
|
||||||
|
bytes_to_grind: usize,
|
||||||
|
) -> Signature {
|
||||||
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
|
let len_check = |s: &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
|
||||||
self.sign_grind_with_check(msg, sk, len_check)
|
self.sign_grind_with_check(msg, sk, len_check)
|
||||||
}
|
}
|
||||||
|
@ -362,9 +380,16 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn verify_ecdsa(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> {
|
pub fn verify_ecdsa(
|
||||||
|
&self,
|
||||||
|
msg: &Message,
|
||||||
|
sig: &Signature,
|
||||||
|
pk: &PublicKey,
|
||||||
|
) -> Result<(), Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr()) == 0 {
|
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr())
|
||||||
|
== 0
|
||||||
|
{
|
||||||
Err(Error::IncorrectSignature)
|
Err(Error::IncorrectSignature)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -18,10 +18,12 @@
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use crate::{key, Secp256k1, Message, Error, Verification, Signing, ecdsa::Signature};
|
|
||||||
use super::ffi as super_ffi;
|
|
||||||
use self::super_ffi::CPtr;
|
use self::super_ffi::CPtr;
|
||||||
|
use super::ffi as super_ffi;
|
||||||
|
use crate::ecdsa::Signature;
|
||||||
use crate::ffi::recovery as ffi;
|
use crate::ffi::recovery as ffi;
|
||||||
|
use crate::{key, Error, Message, Secp256k1, Signing, Verification};
|
||||||
|
|
||||||
/// A tag used for recovering the public key from a compact signature.
|
/// A tag used for recovering the public key from a compact signature.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -37,15 +39,13 @@ impl RecoveryId {
|
||||||
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
|
pub fn from_i32(id: i32) -> Result<RecoveryId, Error> {
|
||||||
match id {
|
match id {
|
||||||
0..=3 => Ok(RecoveryId(id)),
|
0..=3 => Ok(RecoveryId(id)),
|
||||||
_ => Err(Error::InvalidRecoveryId)
|
_ => Err(Error::InvalidRecoveryId),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Allows library users to convert recovery IDs to i32.
|
/// Allows library users to convert recovery IDs to i32.
|
||||||
pub fn to_i32(self) -> i32 {
|
pub fn to_i32(self) -> i32 { self.0 }
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecoverableSignature {
|
impl RecoverableSignature {
|
||||||
|
@ -53,7 +53,9 @@ impl RecoverableSignature {
|
||||||
/// Converts a compact-encoded byte slice to a signature. This
|
/// Converts a compact-encoded byte slice to a signature. This
|
||||||
/// representation is nonstandard and defined by the libsecp256k1 library.
|
/// representation is nonstandard and defined by the libsecp256k1 library.
|
||||||
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
pub fn from_compact(data: &[u8], recid: RecoveryId) -> Result<RecoverableSignature, Error> {
|
||||||
if data.is_empty() {return Err(Error::InvalidSignature);}
|
if data.is_empty() {
|
||||||
|
return Err(Error::InvalidSignature);
|
||||||
|
}
|
||||||
|
|
||||||
let mut ret = ffi::RecoverableSignature::new();
|
let mut ret = ffi::RecoverableSignature::new();
|
||||||
|
|
||||||
|
@ -77,16 +79,15 @@ impl RecoverableSignature {
|
||||||
/// Obtains a raw pointer suitable for use with FFI functions.
|
/// Obtains a raw pointer suitable for use with FFI functions.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
|
#[deprecated(since = "0.25.0", note = "Use Self::as_c_ptr if you need to access the FFI layer")]
|
||||||
pub fn as_ptr(&self) -> *const ffi::RecoverableSignature {
|
pub fn as_ptr(&self) -> *const ffi::RecoverableSignature { self.as_c_ptr() }
|
||||||
self.as_c_ptr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains a raw mutable pointer suitable for use with FFI functions.
|
/// Obtains a raw mutable pointer suitable for use with FFI functions.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated(since = "0.25.0", note = "Use Self::as_mut_c_ptr if you need to access the FFI layer")]
|
#[deprecated(
|
||||||
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature {
|
since = "0.25.0",
|
||||||
self.as_mut_c_ptr()
|
note = "Use Self::as_mut_c_ptr if you need to access the FFI layer"
|
||||||
}
|
)]
|
||||||
|
pub fn as_mut_ptr(&mut self) -> *mut ffi::RecoverableSignature { self.as_mut_c_ptr() }
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Serializes the recoverable signature in compact format.
|
/// Serializes the recoverable signature in compact format.
|
||||||
|
@ -131,24 +132,17 @@ impl RecoverableSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl CPtr for RecoverableSignature {
|
impl CPtr for RecoverableSignature {
|
||||||
type Target = ffi::RecoverableSignature;
|
type Target = ffi::RecoverableSignature;
|
||||||
fn as_c_ptr(&self) -> *const Self::Target {
|
fn as_c_ptr(&self) -> *const Self::Target { &self.0 }
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
|
fn as_mut_c_ptr(&mut self) -> *mut Self::Target { &mut self.0 }
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new recoverable signature from a FFI one.
|
/// Creates a new recoverable signature from a FFI one.
|
||||||
impl From<ffi::RecoverableSignature> for RecoverableSignature {
|
impl From<ffi::RecoverableSignature> for RecoverableSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature {
|
fn from(sig: ffi::RecoverableSignature) -> RecoverableSignature { RecoverableSignature(sig) }
|
||||||
RecoverableSignature(sig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Signing> Secp256k1<C> {
|
impl<C: Signing> Secp256k1<C> {
|
||||||
|
@ -180,7 +174,11 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
|
|
||||||
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
|
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
|
||||||
/// Requires a signing-capable context.
|
/// Requires a signing-capable context.
|
||||||
pub fn sign_ecdsa_recoverable(&self, msg: &Message, sk: &key::SecretKey) -> RecoverableSignature {
|
pub fn sign_ecdsa_recoverable(
|
||||||
|
&self,
|
||||||
|
msg: &Message,
|
||||||
|
sk: &key::SecretKey,
|
||||||
|
) -> RecoverableSignature {
|
||||||
self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, ptr::null())
|
self.sign_ecdsa_recoverable_with_noncedata_pointer(msg, sk, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,13 +201,15 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
impl<C: Verification> Secp256k1<C> {
|
impl<C: Verification> Secp256k1<C> {
|
||||||
/// Determines the public key for which `sig` is a valid signature for
|
/// Determines the public key for which `sig` is a valid signature for
|
||||||
/// `msg`. Requires a verify-capable context.
|
/// `msg`. Requires a verify-capable context.
|
||||||
pub fn recover_ecdsa(&self, msg: &Message, sig: &RecoverableSignature)
|
pub fn recover_ecdsa(
|
||||||
-> Result<key::PublicKey, Error> {
|
&self,
|
||||||
|
msg: &Message,
|
||||||
|
sig: &RecoverableSignature,
|
||||||
|
) -> Result<key::PublicKey, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut pk = super_ffi::PublicKey::new();
|
let mut pk = super_ffi::PublicKey::new();
|
||||||
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk,
|
if ffi::secp256k1_ecdsa_recover(self.ctx, &mut pk, sig.as_c_ptr(), msg.as_c_ptr()) != 1
|
||||||
sig.as_c_ptr(), msg.as_c_ptr()) != 1 {
|
{
|
||||||
return Err(Error::InvalidSignature);
|
return Err(Error::InvalidSignature);
|
||||||
}
|
}
|
||||||
Ok(key::PublicKey::from(pk))
|
Ok(key::PublicKey::from(pk))
|
||||||
|
@ -217,19 +217,17 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rand::{RngCore, thread_rng};
|
use rand::{thread_rng, RngCore};
|
||||||
|
|
||||||
use crate::{Error, SecretKey, Secp256k1, Message};
|
|
||||||
use crate::constants::ONE;
|
|
||||||
use super::{RecoveryId, RecoverableSignature};
|
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
|
use super::{RecoverableSignature, RecoveryId};
|
||||||
|
use crate::constants::ONE;
|
||||||
|
use crate::{Error, Message, Secp256k1, SecretKey};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
fn capabilities() {
|
fn capabilities() {
|
||||||
|
@ -252,8 +250,7 @@ mod tests {
|
||||||
assert!(vrfy.recover_ecdsa(&msg, &sigr).is_ok());
|
assert!(vrfy.recover_ecdsa(&msg, &sigr).is_ok());
|
||||||
assert!(full.recover_ecdsa(&msg, &sigr).is_ok());
|
assert!(full.recover_ecdsa(&msg, &sigr).is_ok());
|
||||||
|
|
||||||
assert_eq!(vrfy.recover_ecdsa(&msg, &sigr),
|
assert_eq!(vrfy.recover_ecdsa(&msg, &sigr), full.recover_ecdsa(&msg, &sigr));
|
||||||
full.recover_ecdsa(&msg, &sigr));
|
|
||||||
assert_eq!(full.recover_ecdsa(&msg, &sigr), Ok(pk));
|
assert_eq!(full.recover_ecdsa(&msg, &sigr), Ok(pk));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,10 +416,7 @@ mod tests {
|
||||||
0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f,
|
0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f,
|
||||||
0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
|
0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
|
||||||
0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89];
|
0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89];
|
||||||
let sig = RecoverableSignature::from_compact(
|
let sig = RecoverableSignature::from_compact(bytes_in, recid_in).unwrap();
|
||||||
bytes_in,
|
|
||||||
recid_in,
|
|
||||||
).unwrap();
|
|
||||||
let (recid_out, bytes_out) = sig.serialize_compact();
|
let (recid_out, bytes_out) = sig.serialize_compact();
|
||||||
assert_eq!(recid_in, recid_out);
|
assert_eq!(recid_in, recid_out);
|
||||||
assert_eq!(&bytes_in[..], &bytes_out[..]);
|
assert_eq!(&bytes_in[..], &bytes_out[..]);
|
||||||
|
@ -446,7 +440,8 @@ mod tests {
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
mod benches {
|
mod benches {
|
||||||
use rand::{thread_rng, RngCore};
|
use rand::{thread_rng, RngCore};
|
||||||
use test::{Bencher, black_box};
|
use test::{black_box, Bencher};
|
||||||
|
|
||||||
use super::{Message, Secp256k1};
|
use super::{Message, Secp256k1};
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
//! unable to run on platforms without allocator. We implement a special type to encapsulate
|
//! unable to run on platforms without allocator. We implement a special type to encapsulate
|
||||||
//! serialized signatures and since it's a bit more complicated it has its own module.
|
//! serialized signatures and since it's a bit more complicated it has its own module.
|
||||||
|
|
||||||
|
use core::{fmt, ops};
|
||||||
|
|
||||||
pub use into_iter::IntoIter;
|
pub use into_iter::IntoIter;
|
||||||
|
|
||||||
use core::{fmt, ops};
|
|
||||||
use crate::Error;
|
|
||||||
use super::Signature;
|
use super::Signature;
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
pub(crate) const MAX_LEN: usize = 72;
|
pub(crate) const MAX_LEN: usize = 72;
|
||||||
|
|
||||||
|
@ -21,9 +22,7 @@ pub struct SerializedSignature {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SerializedSignature {
|
impl fmt::Debug for SerializedSignature {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
|
||||||
fmt::Display::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SerializedSignature {
|
impl fmt::Display for SerializedSignature {
|
||||||
|
@ -37,25 +36,19 @@ impl fmt::Display for SerializedSignature {
|
||||||
|
|
||||||
impl PartialEq for SerializedSignature {
|
impl PartialEq for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &SerializedSignature) -> bool {
|
fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
|
||||||
**self == **other
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<[u8]> for SerializedSignature {
|
impl AsRef<[u8]> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Deref for SerializedSignature {
|
impl ops::Deref for SerializedSignature {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &[u8] {
|
fn deref(&self) -> &[u8] { &self.data[..self.len] }
|
||||||
&self.data[..self.len]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for SerializedSignature {}
|
impl Eq for SerializedSignature {}
|
||||||
|
@ -65,9 +58,7 @@ impl IntoIterator for SerializedSignature {
|
||||||
type Item = u8;
|
type Item = u8;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) }
|
||||||
IntoIter::new(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a SerializedSignature {
|
impl<'a> IntoIterator for &'a SerializedSignature {
|
||||||
|
@ -75,9 +66,7 @@ impl<'a> IntoIterator for &'a SerializedSignature {
|
||||||
type Item = &'a u8;
|
type Item = &'a u8;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter { self.iter() }
|
||||||
self.iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerializedSignature {
|
impl SerializedSignature {
|
||||||
|
@ -89,43 +78,30 @@ impl SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
|
pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
|
||||||
assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
|
assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
|
||||||
SerializedSignature {
|
SerializedSignature { data, len }
|
||||||
data,
|
|
||||||
len,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the capacity of the underlying data buffer.
|
/// Get the capacity of the underlying data buffer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn capacity(&self) -> usize {
|
pub fn capacity(&self) -> usize { self.data.len() }
|
||||||
self.data.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the len of the used data.
|
/// Get the len of the used data.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize { self.len }
|
||||||
self.len
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the length of the object.
|
/// Set the length of the object.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_len_unchecked(&mut self, len: usize) {
|
pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
|
||||||
self.len = len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert the serialized signature into the Signature struct.
|
/// Convert the serialized signature into the Signature struct.
|
||||||
/// (This DER deserializes it)
|
/// (This DER deserializes it)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_signature(&self) -> Result<Signature, Error> {
|
pub fn to_signature(&self) -> Result<Signature, Error> { Signature::from_der(self) }
|
||||||
Signature::from_der(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a SerializedSignature from a Signature.
|
/// Create a SerializedSignature from a Signature.
|
||||||
/// (this DER serializes it)
|
/// (this DER serializes it)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_signature(sig: &Signature) -> SerializedSignature {
|
pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize_der() }
|
||||||
sig.serialize_der()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the space is zero.
|
/// Check if the space is zero.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -162,9 +138,7 @@ mod into_iter {
|
||||||
///
|
///
|
||||||
/// This method is analogous to [`core::slice::Iter::as_slice`].
|
/// This method is analogous to [`core::slice::Iter::as_slice`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_slice(&self) -> &[u8] {
|
pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] }
|
||||||
&self.signature[self.pos..]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for IntoIter {
|
impl Iterator for IntoIter {
|
||||||
|
|
505
src/key.rs
505
src/key.rs
File diff suppressed because it is too large
Load Diff
177
src/lib.rs
177
src/lib.rs
|
@ -153,11 +153,8 @@
|
||||||
// Coding conventions
|
// Coding conventions
|
||||||
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
|
#![deny(non_upper_case_globals, non_camel_case_types, non_snake_case)]
|
||||||
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
|
#![warn(missing_docs, missing_copy_implementations, missing_debug_implementations)]
|
||||||
|
|
||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||||
|
|
||||||
// Experimental features we need.
|
// Experimental features we need.
|
||||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
#![cfg_attr(bench, feature(test))]
|
#![cfg_attr(bench, feature(test))]
|
||||||
|
@ -184,29 +181,30 @@ pub mod schnorr;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
mod serde_util;
|
mod serde_util;
|
||||||
|
|
||||||
#[cfg(any(test, feature = "rand"))]
|
use core::marker::PhantomData;
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
use core::{fmt, mem, str};
|
||||||
pub use rand;
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
|
||||||
pub use serde;
|
|
||||||
#[cfg(feature = "bitcoin-hashes")]
|
#[cfg(feature = "bitcoin-hashes")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
||||||
pub use bitcoin_hashes as hashes;
|
pub use bitcoin_hashes as hashes;
|
||||||
pub use secp256k1_sys as ffi;
|
|
||||||
pub use crate::key::{PublicKey, SecretKey};
|
|
||||||
pub use crate::context::*;
|
|
||||||
pub use crate::key::*;
|
|
||||||
pub use crate::scalar::Scalar;
|
|
||||||
|
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "global-context")))]
|
||||||
pub use context::global::SECP256K1;
|
pub use context::global::SECP256K1;
|
||||||
|
#[cfg(any(test, feature = "rand"))]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
|
pub use rand;
|
||||||
|
pub use secp256k1_sys as ffi;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
||||||
|
pub use serde;
|
||||||
|
|
||||||
use core::{fmt, str, mem, marker::PhantomData};
|
pub use crate::context::*;
|
||||||
use crate::ffi::{CPtr, impl_array_newtype, types::AlignedType};
|
use crate::ffi::types::AlignedType;
|
||||||
|
use crate::ffi::{impl_array_newtype, CPtr};
|
||||||
#[cfg(feature = "bitcoin-hashes")]
|
#[cfg(feature = "bitcoin-hashes")]
|
||||||
use crate::hashes::Hash;
|
use crate::hashes::Hash;
|
||||||
|
pub use crate::key::{PublicKey, SecretKey, *};
|
||||||
|
pub use crate::scalar::Scalar;
|
||||||
|
|
||||||
/// Trait describing something that promises to be a 32-byte random number; in particular,
|
/// Trait describing something that promises to be a 32-byte random number; in particular,
|
||||||
/// it has negligible probability of being zero or overflowing the group order. Such objects
|
/// it has negligible probability of being zero or overflowing the group order. Such objects
|
||||||
|
@ -219,25 +217,19 @@ pub trait ThirtyTwoByteHash {
|
||||||
#[cfg(feature = "bitcoin-hashes")]
|
#[cfg(feature = "bitcoin-hashes")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
||||||
impl ThirtyTwoByteHash for hashes::sha256::Hash {
|
impl ThirtyTwoByteHash for hashes::sha256::Hash {
|
||||||
fn into_32(self) -> [u8; 32] {
|
fn into_32(self) -> [u8; 32] { self.into_inner() }
|
||||||
self.into_inner()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bitcoin-hashes")]
|
#[cfg(feature = "bitcoin-hashes")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
||||||
impl ThirtyTwoByteHash for hashes::sha256d::Hash {
|
impl ThirtyTwoByteHash for hashes::sha256d::Hash {
|
||||||
fn into_32(self) -> [u8; 32] {
|
fn into_32(self) -> [u8; 32] { self.into_inner() }
|
||||||
self.into_inner()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "bitcoin-hashes")]
|
#[cfg(feature = "bitcoin-hashes")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin-hashes")))]
|
||||||
impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> {
|
impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> {
|
||||||
fn into_32(self) -> [u8; 32] {
|
fn into_32(self) -> [u8; 32] { self.into_inner() }
|
||||||
self.into_inner()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A (hashed) message input to an ECDSA signature.
|
/// A (hashed) message input to an ECDSA signature.
|
||||||
|
@ -260,7 +252,7 @@ impl Message {
|
||||||
ret[..].copy_from_slice(data);
|
ret[..].copy_from_slice(data);
|
||||||
Ok(Message(ret))
|
Ok(Message(ret))
|
||||||
}
|
}
|
||||||
_ => Err(Error::InvalidMessage)
|
_ => Err(Error::InvalidMessage),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,9 +283,7 @@ impl Message {
|
||||||
|
|
||||||
impl<T: ThirtyTwoByteHash> From<T> for Message {
|
impl<T: ThirtyTwoByteHash> From<T> for Message {
|
||||||
/// Converts a 32-byte hash directly to a message without error paths.
|
/// Converts a 32-byte hash directly to a message without error paths.
|
||||||
fn from(t: T) -> Message {
|
fn from(t: T) -> Message { Message(t.into_32()) }
|
||||||
Message(t.into_32())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::LowerHex for Message {
|
impl fmt::LowerHex for Message {
|
||||||
|
@ -306,9 +296,7 @@ impl fmt::LowerHex for Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Message {
|
impl fmt::Display for Message {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
|
||||||
fmt::LowerHex::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An ECDSA error
|
/// An ECDSA error
|
||||||
|
@ -353,7 +341,9 @@ impl fmt::Display for Error {
|
||||||
InvalidRecoveryId => f.write_str("bad recovery id"),
|
InvalidRecoveryId => f.write_str("bad recovery id"),
|
||||||
InvalidTweak => f.write_str("bad tweak"),
|
InvalidTweak => f.write_str("bad tweak"),
|
||||||
NotEnoughMemory => f.write_str("not enough memory allocated"),
|
NotEnoughMemory => f.write_str("not enough memory allocated"),
|
||||||
InvalidPublicKeySum => f.write_str("the sum of public keys was invalid or the input vector lengths was less than 1"),
|
InvalidPublicKeySum => f.write_str(
|
||||||
|
"the sum of public keys was invalid or the input vector lengths was less than 1",
|
||||||
|
),
|
||||||
InvalidParityValue(e) => write_err!(f, "couldn't create parity"; e),
|
InvalidParityValue(e) => write_err!(f, "couldn't create parity"; e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +369,6 @@ impl std::error::Error for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// The secp256k1 engine, used to execute all signature operations.
|
/// The secp256k1 engine, used to execute all signature operations.
|
||||||
pub struct Secp256k1<C: Context> {
|
pub struct Secp256k1<C: Context> {
|
||||||
ctx: *mut ffi::Context,
|
ctx: *mut ffi::Context,
|
||||||
|
@ -414,14 +403,11 @@ impl<C: Context> fmt::Debug for Secp256k1<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: Context> Secp256k1<C> {
|
impl<C: Context> Secp256k1<C> {
|
||||||
|
|
||||||
/// Getter for the raw pointer to the underlying secp256k1 context. This
|
/// Getter for the raw pointer to the underlying secp256k1 context. This
|
||||||
/// shouldn't be needed with normal usage of the library. It enables
|
/// shouldn't be needed with normal usage of the library. It enables
|
||||||
/// extending the Secp256k1 with more cryptographic algorithms outside of
|
/// extending the Secp256k1 with more cryptographic algorithms outside of
|
||||||
/// this crate.
|
/// this crate.
|
||||||
pub fn ctx(&self) -> &*mut ffi::Context {
|
pub fn ctx(&self) -> &*mut ffi::Context { &self.ctx }
|
||||||
&self.ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
|
/// Returns the required memory for a preallocated context buffer in a generic manner(sign/verify/all).
|
||||||
pub fn preallocate_size_gen() -> usize {
|
pub fn preallocate_size_gen() -> usize {
|
||||||
|
@ -468,8 +454,10 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||||
pub fn generate_keypair<R: rand::Rng + ?Sized>(&self, rng: &mut R)
|
pub fn generate_keypair<R: rand::Rng + ?Sized>(
|
||||||
-> (key::SecretKey, key::PublicKey) {
|
&self,
|
||||||
|
rng: &mut R,
|
||||||
|
) -> (key::SecretKey, key::PublicKey) {
|
||||||
let sk = key::SecretKey::new(rng);
|
let sk = key::SecretKey::new(rng);
|
||||||
let pk = key::PublicKey::from_secret_key(self, &sk);
|
let pk = key::PublicKey::from_secret_key(self, &sk);
|
||||||
(sk, pk)
|
(sk, pk)
|
||||||
|
@ -533,30 +521,30 @@ fn to_hex<'a>(src: &[u8], target: &'a mut [u8]) -> Result<&'a str, ()> {
|
||||||
return unsafe { Ok(str::from_utf8_unchecked(result)) };
|
return unsafe { Ok(str::from_utf8_unchecked(result)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rand::{RngCore, thread_rng};
|
use rand::{thread_rng, RngCore};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
use crate::{constants, ecdsa, from_hex, to_hex, Message, PublicKey, Secp256k1, SecretKey, Error};
|
|
||||||
use crate::context::*;
|
use crate::context::*;
|
||||||
use crate::ffi::{self, types::AlignedType};
|
use crate::ffi::types::AlignedType;
|
||||||
|
use crate::ffi::{self};
|
||||||
|
use crate::{
|
||||||
|
constants, ecdsa, from_hex, to_hex, Error, Message, PublicKey, Secp256k1, SecretKey,
|
||||||
|
};
|
||||||
|
|
||||||
macro_rules! hex {
|
macro_rules! hex {
|
||||||
($hex:expr) => ({
|
($hex:expr) => {{
|
||||||
let mut result = vec![0; $hex.len() / 2];
|
let mut result = vec![0; $hex.len() / 2];
|
||||||
from_hex($hex, &mut result).expect("valid hex string");
|
from_hex($hex, &mut result).expect("valid hex string");
|
||||||
result
|
result
|
||||||
});
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
fn test_manual_create_destroy() {
|
fn test_manual_create_destroy() {
|
||||||
|
@ -565,9 +553,12 @@ mod tests {
|
||||||
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
|
let ctx_vrfy = unsafe { ffi::secp256k1_context_create(VerifyOnlyPreallocated::FLAGS) };
|
||||||
|
|
||||||
let size = 0;
|
let size = 0;
|
||||||
let full: Secp256k1<AllPreallocated> = Secp256k1{ctx: ctx_full, phantom: PhantomData, size};
|
let full: Secp256k1<AllPreallocated> =
|
||||||
let sign: Secp256k1<SignOnlyPreallocated> = Secp256k1{ctx: ctx_sign, phantom: PhantomData, size};
|
Secp256k1 { ctx: ctx_full, phantom: PhantomData, size };
|
||||||
let vrfy: Secp256k1<VerifyOnlyPreallocated> = Secp256k1{ctx: ctx_vrfy, phantom: PhantomData, size};
|
let sign: Secp256k1<SignOnlyPreallocated> =
|
||||||
|
Secp256k1 { ctx: ctx_sign, phantom: PhantomData, size };
|
||||||
|
let vrfy: Secp256k1<VerifyOnlyPreallocated> =
|
||||||
|
Secp256k1 { ctx: ctx_vrfy, phantom: PhantomData, size };
|
||||||
|
|
||||||
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
let (sk, pk) = full.generate_keypair(&mut thread_rng());
|
||||||
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
let msg = Message::from_slice(&[2u8; 32]).unwrap();
|
||||||
|
@ -579,7 +570,9 @@ mod tests {
|
||||||
assert!(vrfy.verify_ecdsa(&msg, &sig, &pk).is_ok());
|
assert!(vrfy.verify_ecdsa(&msg, &sig, &pk).is_ok());
|
||||||
assert!(full.verify_ecdsa(&msg, &sig, &pk).is_ok());
|
assert!(full.verify_ecdsa(&msg, &sig, &pk).is_ok());
|
||||||
|
|
||||||
drop(full);drop(sign);drop(vrfy);
|
drop(full);
|
||||||
|
drop(sign);
|
||||||
|
drop(vrfy);
|
||||||
|
|
||||||
unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) };
|
unsafe { ffi::secp256k1_context_destroy(ctx_vrfy) };
|
||||||
unsafe { ffi::secp256k1_context_destroy(ctx_sign) };
|
unsafe { ffi::secp256k1_context_destroy(ctx_sign) };
|
||||||
|
@ -613,7 +606,6 @@ mod tests {
|
||||||
ManuallyDrop::drop(&mut full);
|
ManuallyDrop::drop(&mut full);
|
||||||
ManuallyDrop::drop(&mut sign);
|
ManuallyDrop::drop(&mut sign);
|
||||||
ManuallyDrop::drop(&mut vrfy);
|
ManuallyDrop::drop(&mut vrfy);
|
||||||
|
|
||||||
}
|
}
|
||||||
drop(ctx_full);
|
drop(ctx_full);
|
||||||
drop(ctx_sign);
|
drop(ctx_sign);
|
||||||
|
@ -729,15 +721,18 @@ mod tests {
|
||||||
assert!(ecdsa::Signature::from_str(
|
assert!(ecdsa::Signature::from_str(
|
||||||
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab4"
|
||||||
).is_err());
|
)
|
||||||
|
.is_err());
|
||||||
assert!(ecdsa::Signature::from_str(
|
assert!(ecdsa::Signature::from_str(
|
||||||
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab"
|
||||||
).is_err());
|
)
|
||||||
|
.is_err());
|
||||||
assert!(ecdsa::Signature::from_str(
|
assert!(ecdsa::Signature::from_str(
|
||||||
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eabxx"
|
||||||
).is_err());
|
)
|
||||||
|
.is_err());
|
||||||
assert!(ecdsa::Signature::from_str(
|
assert!(ecdsa::Signature::from_str(
|
||||||
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
"3046022100839c1fbc5304de944f697c9f4b1d01d1faeba32d751c0f7acb21ac8a0f436a\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
||||||
|
@ -745,7 +740,8 @@ mod tests {
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45\
|
||||||
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
|
72022100e89bd46bb3a5a62adc679f659b7ce876d83ee297c7a5587b2011c4fcc72eab45"
|
||||||
).is_err());
|
)
|
||||||
|
.is_err());
|
||||||
|
|
||||||
// 71 byte signature
|
// 71 byte signature
|
||||||
let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776";
|
let hex_str = "30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce774b02202876e7102f204f6bfee26c967c3926ce702cf97d4b010062e193f763190f6776";
|
||||||
|
@ -862,15 +858,23 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bad_slice() {
|
fn test_bad_slice() {
|
||||||
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
|
assert_eq!(
|
||||||
Err(Error::InvalidSignature));
|
ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE + 1]),
|
||||||
assert_eq!(ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
|
Err(Error::InvalidSignature)
|
||||||
Err(Error::InvalidSignature));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ecdsa::Signature::from_der(&[0; constants::MAX_SIGNATURE_SIZE]),
|
||||||
|
Err(Error::InvalidSignature)
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
|
assert_eq!(
|
||||||
Err(Error::InvalidMessage));
|
Message::from_slice(&[0; constants::MESSAGE_SIZE - 1]),
|
||||||
assert_eq!(Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]),
|
Err(Error::InvalidMessage)
|
||||||
Err(Error::InvalidMessage));
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Message::from_slice(&[0; constants::MESSAGE_SIZE + 1]),
|
||||||
|
Err(Error::InvalidMessage)
|
||||||
|
);
|
||||||
assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok());
|
assert!(Message::from_slice(&[0; constants::MESSAGE_SIZE]).is_ok());
|
||||||
assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok());
|
assert!(Message::from_slice(&[1; constants::MESSAGE_SIZE]).is_ok());
|
||||||
}
|
}
|
||||||
|
@ -892,7 +896,6 @@ mod tests {
|
||||||
assert_eq!(src, &result_buf[..i]);
|
assert_eq!(src, &result_buf[..i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assert!(to_hex(&[1; 2], &mut [0u8; 3]).is_err());
|
assert!(to_hex(&[1; 2], &mut [0u8; 3]).is_err());
|
||||||
assert!(to_hex(&[1; 2], &mut [0u8; 4]).is_ok());
|
assert!(to_hex(&[1; 2], &mut [0u8; 4]).is_ok());
|
||||||
assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err());
|
assert!(from_hex("deadbeaf", &mut [0u8; 3]).is_err());
|
||||||
|
@ -909,7 +912,9 @@ mod tests {
|
||||||
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let noncedata = [42u8; 32];
|
let noncedata = [42u8; 32];
|
||||||
let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap();
|
let sk =
|
||||||
|
SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
|
||||||
|
.unwrap();
|
||||||
let expected_sig = hex!("24861b3edd4e7da43319c635091405feced6efa4ec99c3c3c35f6c3ba0ed8816116772e84994084db85a6c20589f6a85af569d42275c2a5dd900da5776b99d5d");
|
let expected_sig = hex!("24861b3edd4e7da43319c635091405feced6efa4ec99c3c3c35f6c3ba0ed8816116772e84994084db85a6c20589f6a85af569d42275c2a5dd900da5776b99d5d");
|
||||||
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
|
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
|
||||||
|
|
||||||
|
@ -948,7 +953,9 @@ mod tests {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
let msg = hex!("887d04bb1cf1b1554f1b268dfe62d13064ca67ae45348d50d1392ce2d13418ac");
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap();
|
let sk =
|
||||||
|
SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead")
|
||||||
|
.unwrap();
|
||||||
let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713");
|
let expected_sig = hex!("047dd4d049db02b430d24c41c7925b2725bcd5a85393513bdec04b4dc363632b1054d0180094122b380f4cfa391e6296244da773173e78fc745c1b9c79f7b713");
|
||||||
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
|
let expected_sig = ecdsa::Signature::from_compact(&expected_sig).unwrap();
|
||||||
|
|
||||||
|
@ -964,7 +971,9 @@ mod tests {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
|
let msg = hex!("ef2d5b9a7c61865a95941d0f04285420560df7e9d76890ac1b8867b12ce43167");
|
||||||
let msg = Message::from_slice(&msg).unwrap();
|
let msg = Message::from_slice(&msg).unwrap();
|
||||||
let sk = SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b").unwrap();
|
let sk =
|
||||||
|
SecretKey::from_str("848355d75fe1c354cf05539bb29b2015f1863065bcb6766b44d399ab95c3fa0b")
|
||||||
|
.unwrap();
|
||||||
let expected_sig = ecdsa::Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap();
|
let expected_sig = ecdsa::Signature::from_str("304302202ffc447100d518c8ba643d11f3e6a83a8640488e7d2537b1954b942408be6ea3021f26e1248dd1e52160c3a38af9769d91a1a806cab5f9d508c103464d3c02d6e1").unwrap();
|
||||||
|
|
||||||
let sig = secp.sign_ecdsa_grind_r(&msg, &sk, 2);
|
let sig = secp.sign_ecdsa_grind_r(&msg, &sk, 2);
|
||||||
|
@ -977,7 +986,7 @@ mod tests {
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde() {
|
fn test_serde() {
|
||||||
use serde_test::{Configure, Token, assert_tokens};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
|
|
||||||
|
@ -985,11 +994,10 @@ mod tests {
|
||||||
let sk = SecretKey::from_slice(&[2; 32]).unwrap();
|
let sk = SecretKey::from_slice(&[2; 32]).unwrap();
|
||||||
let sig = s.sign_ecdsa(&msg, &sk);
|
let sig = s.sign_ecdsa(&msg, &sk);
|
||||||
static SIG_BYTES: [u8; 71] = [
|
static SIG_BYTES: [u8; 71] = [
|
||||||
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237,
|
48, 69, 2, 33, 0, 157, 11, 173, 87, 103, 25, 211, 42, 231, 107, 237, 179, 76, 119, 72,
|
||||||
179, 76, 119, 72, 102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148,
|
102, 103, 60, 189, 227, 244, 225, 41, 81, 85, 92, 148, 8, 230, 206, 119, 75, 2, 32, 40,
|
||||||
8, 230, 206, 119, 75, 2, 32, 40, 118, 231, 16, 47, 32, 79, 107, 254,
|
118, 231, 16, 47, 32, 79, 107, 254, 226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125,
|
||||||
226, 108, 150, 124, 57, 38, 206, 112, 44, 249, 125, 75, 1, 0, 98, 225,
|
75, 1, 0, 98, 225, 147, 247, 99, 25, 15, 103, 118,
|
||||||
147, 247, 99, 25, 15, 103, 118
|
|
||||||
];
|
];
|
||||||
static SIG_STR: &str = "\
|
static SIG_STR: &str = "\
|
||||||
30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\
|
30450221009d0bad576719d32ae76bedb34c774866673cbde3f4e12951555c9408e6ce77\
|
||||||
|
@ -1003,7 +1011,6 @@ mod tests {
|
||||||
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
|
assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
|
||||||
assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
|
assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
|
||||||
assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
|
assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
|
@ -1033,34 +1040,26 @@ mod tests {
|
||||||
let hash = hashes::sha256::Hash::hash(test_bytes);
|
let hash = hashes::sha256::Hash::hash(test_bytes);
|
||||||
let msg = Message::from(hash);
|
let msg = Message::from(hash);
|
||||||
assert_eq!(msg.0, hash.into_inner());
|
assert_eq!(msg.0, hash.into_inner());
|
||||||
assert_eq!(
|
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes));
|
||||||
msg,
|
|
||||||
Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes)
|
|
||||||
);
|
|
||||||
|
|
||||||
let hash = hashes::sha256d::Hash::hash(test_bytes);
|
let hash = hashes::sha256d::Hash::hash(test_bytes);
|
||||||
let msg = Message::from(hash);
|
let msg = Message::from(hash);
|
||||||
assert_eq!(msg.0, hash.into_inner());
|
assert_eq!(msg.0, hash.into_inner());
|
||||||
assert_eq!(
|
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes));
|
||||||
msg,
|
|
||||||
Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(bench)]
|
#[cfg(bench)]
|
||||||
mod benches {
|
mod benches {
|
||||||
use test::{Bencher, black_box};
|
|
||||||
|
|
||||||
use rand::{RngCore, thread_rng};
|
|
||||||
use rand::rngs::mock::StepRng;
|
use rand::rngs::mock::StepRng;
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
|
use test::{black_box, Bencher};
|
||||||
|
|
||||||
use super::{Message, Secp256k1};
|
use super::{Message, Secp256k1};
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
#[cfg(any(feature = "alloc", feature = "std"))]
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
||||||
pub fn generate(bh: &mut Bencher) {
|
pub fn generate(bh: &mut Bencher) {
|
||||||
|
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let mut r = StepRng::new(1, 1);
|
let mut r = StepRng::new(1, 1);
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
|
|
|
@ -24,7 +24,7 @@ macro_rules! impl_pretty_debug {
|
||||||
f.write_str(")")
|
f.write_str(")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats error. If `std` feature is OFF appends error source (delimited by `: `). We do this
|
/// Formats error. If `std` feature is OFF appends error source (delimited by `: `). We do this
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub struct Scalar([u8; 32]);
|
||||||
|
|
||||||
const MAX_RAW: [u8; 32] = [
|
const MAX_RAW: [u8; 32] = [
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||||
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40
|
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl Scalar {
|
impl Scalar {
|
||||||
|
@ -39,9 +39,7 @@ impl Scalar {
|
||||||
/// Generates a random scalar
|
/// Generates a random scalar
|
||||||
#[cfg(any(test, feature = "rand-std"))]
|
#[cfg(any(test, feature = "rand-std"))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "rand-std")))]
|
||||||
pub fn random() -> Self {
|
pub fn random() -> Self { Self::random_custom(rand::thread_rng()) }
|
||||||
Self::random_custom(rand::thread_rng())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a random scalar using supplied RNG
|
/// Generates a random scalar using supplied RNG
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
|
@ -88,9 +86,7 @@ impl Scalar {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes to big endian bytes
|
/// Serializes to big endian bytes
|
||||||
pub fn to_be_bytes(self) -> [u8; 32] {
|
pub fn to_be_bytes(self) -> [u8; 32] { self.0 }
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serializes to little endian bytes
|
/// Serializes to little endian bytes
|
||||||
pub fn to_le_bytes(self) -> [u8; 32] {
|
pub fn to_le_bytes(self) -> [u8; 32] {
|
||||||
|
@ -101,9 +97,7 @@ impl Scalar {
|
||||||
|
|
||||||
// returns a reference to internal bytes
|
// returns a reference to internal bytes
|
||||||
// non-public to not leak the internal representation
|
// non-public to not leak the internal representation
|
||||||
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] {
|
pub(crate) fn as_be_bytes(&self) -> &[u8; 32] { &self.0 }
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn as_c_ptr(&self) -> *const u8 {
|
pub(crate) fn as_c_ptr(&self) -> *const u8 {
|
||||||
use secp256k1_sys::CPtr;
|
use secp256k1_sys::CPtr;
|
||||||
|
@ -113,11 +107,8 @@ impl Scalar {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<crate::SecretKey> for Scalar {
|
impl From<crate::SecretKey> for Scalar {
|
||||||
fn from(value: crate::SecretKey) -> Self {
|
fn from(value: crate::SecretKey) -> Self { Scalar(value.secret_bytes()) }
|
||||||
Scalar(value.secret_bytes())
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Error returned when the value of scalar is invalid - larger than the curve order.
|
/// Error returned when the value of scalar is invalid - larger than the curve order.
|
||||||
// Intentionally doesn't implement `Copy` to improve forward compatibility.
|
// Intentionally doesn't implement `Copy` to improve forward compatibility.
|
||||||
|
@ -125,8 +116,7 @@ impl From<crate::SecretKey> for Scalar {
|
||||||
#[allow(missing_copy_implementations)]
|
#[allow(missing_copy_implementations)]
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct OutOfRangeError {
|
pub struct OutOfRangeError {}
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for OutOfRangeError {
|
impl fmt::Display for OutOfRangeError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -7,12 +7,11 @@ use core::{fmt, ptr, str};
|
||||||
#[cfg(any(test, feature = "rand"))]
|
#[cfg(any(test, feature = "rand"))]
|
||||||
use rand::{CryptoRng, Rng};
|
use rand::{CryptoRng, Rng};
|
||||||
|
|
||||||
use crate::{constants, Error, from_hex, Message, Secp256k1, Signing, Verification};
|
use crate::ffi::{self, impl_array_newtype, CPtr};
|
||||||
use crate::key::{KeyPair, XOnlyPublicKey};
|
use crate::key::{KeyPair, XOnlyPublicKey};
|
||||||
use crate::ffi::{self, CPtr, impl_array_newtype};
|
|
||||||
|
|
||||||
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
#[cfg(all(feature = "global-context", feature = "rand-std"))]
|
||||||
use crate::SECP256K1;
|
use crate::SECP256K1;
|
||||||
|
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
|
||||||
|
|
||||||
/// Represents a Schnorr signature.
|
/// Represents a Schnorr signature.
|
||||||
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
|
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
|
||||||
|
@ -35,12 +34,12 @@ impl<'de> serde::Deserialize<'de> for Signature {
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
|
||||||
if d.is_human_readable() {
|
if d.is_human_readable() {
|
||||||
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
d.deserialize_str(super::serde_util::FromStrVisitor::new(
|
||||||
"a hex string representing 64 byte schnorr signature"
|
"a hex string representing 64 byte schnorr signature",
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
|
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
|
||||||
"raw 64 bytes schnorr signature",
|
"raw 64 bytes schnorr signature",
|
||||||
Signature::from_slice
|
Signature::from_slice,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,9 +55,7 @@ impl fmt::LowerHex for Signature {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Signature {
|
impl fmt::Display for Signature {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
|
||||||
fmt::LowerHex::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl str::FromStr for Signature {
|
impl str::FromStr for Signature {
|
||||||
|
@ -66,9 +63,8 @@ impl str::FromStr for Signature {
|
||||||
fn from_str(s: &str) -> Result<Signature, Error> {
|
fn from_str(s: &str) -> Result<Signature, Error> {
|
||||||
let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
|
let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
|
||||||
match from_hex(s, &mut res) {
|
match from_hex(s, &mut res) {
|
||||||
Ok(constants::SCHNORR_SIGNATURE_SIZE) => {
|
Ok(constants::SCHNORR_SIGNATURE_SIZE) =>
|
||||||
Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE])
|
Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE]),
|
||||||
}
|
|
||||||
_ => Err(Error::InvalidSignature),
|
_ => Err(Error::InvalidSignature),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,11 +126,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a schnorr signature without using any auxiliary random data.
|
/// Create a schnorr signature without using any auxiliary random data.
|
||||||
pub fn sign_schnorr_no_aux_rand(
|
pub fn sign_schnorr_no_aux_rand(&self, msg: &Message, keypair: &KeyPair) -> Signature {
|
||||||
&self,
|
|
||||||
msg: &Message,
|
|
||||||
keypair: &KeyPair,
|
|
||||||
) -> Signature {
|
|
||||||
self.sign_schnorr_helper(msg, keypair, ptr::null())
|
self.sign_schnorr_helper(msg, keypair, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,11 +137,7 @@ impl<C: Signing> Secp256k1<C> {
|
||||||
keypair: &KeyPair,
|
keypair: &KeyPair,
|
||||||
aux_rand: &[u8; 32],
|
aux_rand: &[u8; 32],
|
||||||
) -> Signature {
|
) -> Signature {
|
||||||
self.sign_schnorr_helper(
|
self.sign_schnorr_helper(msg, keypair, aux_rand.as_c_ptr() as *const ffi::types::c_uchar)
|
||||||
msg,
|
|
||||||
keypair,
|
|
||||||
aux_rand.as_c_ptr() as *const ffi::types::c_uchar,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a schnorr signature using the given random number generator to
|
/// Create a schnorr signature using the given random number generator to
|
||||||
|
@ -199,15 +187,15 @@ impl<C: Verification> Secp256k1<C> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
|
|
||||||
use rand::{RngCore, rngs::ThreadRng, thread_rng};
|
use rand::rngs::ThreadRng;
|
||||||
|
use rand::{thread_rng, RngCore};
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
|
||||||
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
|
|
||||||
use crate::schnorr::{KeyPair, XOnlyPublicKey, Signature};
|
|
||||||
use crate::Error::InvalidPublicKey;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::schnorr::{KeyPair, Signature, XOnlyPublicKey};
|
||||||
|
use crate::Error::InvalidPublicKey;
|
||||||
|
use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
|
||||||
|
|
||||||
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
#[cfg(all(not(fuzzing), any(feature = "alloc", feature = "std")))]
|
||||||
macro_rules! hex_32 {
|
macro_rules! hex_32 {
|
||||||
|
@ -231,25 +219,17 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
fn schnor_sign_with_rng_verify() {
|
fn schnor_sign_with_rng_verify() {
|
||||||
sign_helper(|secp, msg, seckey, mut rng| {
|
sign_helper(|secp, msg, seckey, mut rng| secp.sign_schnorr_with_rng(msg, seckey, &mut rng))
|
||||||
secp.sign_schnorr_with_rng(msg, seckey, &mut rng)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
fn schnorr_sign_verify() {
|
fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
|
||||||
sign_helper(|secp, msg, seckey, _| {
|
|
||||||
secp.sign_schnorr(msg, seckey)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
fn schnorr_sign_no_aux_rand_verify() {
|
fn schnorr_sign_no_aux_rand_verify() {
|
||||||
sign_helper(|secp, msg, seckey, _| {
|
sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
|
||||||
secp.sign_schnorr_no_aux_rand(msg, seckey)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "rand-std"))]
|
#[cfg(all(feature = "std", feature = "rand-std"))]
|
||||||
|
@ -291,8 +271,7 @@ mod tests {
|
||||||
hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
|
hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
|
||||||
let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
|
let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
|
||||||
|
|
||||||
let sig = secp
|
let sig = secp.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
|
||||||
.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
|
|
||||||
|
|
||||||
assert_eq!(expected_sig, sig);
|
assert_eq!(expected_sig, sig);
|
||||||
}
|
}
|
||||||
|
@ -306,8 +285,9 @@ mod tests {
|
||||||
let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
|
||||||
let msg = Message::from_slice(&hex_msg).unwrap();
|
let msg = Message::from_slice(&hex_msg).unwrap();
|
||||||
let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
|
let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
|
||||||
let pubkey =
|
let pubkey = XOnlyPublicKey::from_str(
|
||||||
XOnlyPublicKey::from_str("B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390")
|
"B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
|
assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
|
||||||
|
@ -398,14 +378,21 @@ mod tests {
|
||||||
pk
|
pk
|
||||||
};
|
};
|
||||||
#[cfg(fuzzing)]
|
#[cfg(fuzzing)]
|
||||||
let pk = XOnlyPublicKey::from_slice(&[0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92, 0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe, 0x91, 0xdd, 0xd1, 0x66]).expect("pk");
|
let pk = XOnlyPublicKey::from_slice(&[
|
||||||
|
0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92,
|
||||||
|
0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe,
|
||||||
|
0x91, 0xdd, 0xd1, 0x66,
|
||||||
|
])
|
||||||
|
.expect("pk");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
pk.to_string(),
|
pk.to_string(),
|
||||||
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
|
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
XOnlyPublicKey::from_str("18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166")
|
XOnlyPublicKey::from_str(
|
||||||
|
"18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
pk
|
pk
|
||||||
);
|
);
|
||||||
|
@ -465,8 +452,7 @@ mod tests {
|
||||||
let msg = Message::from_slice(&[1; 32]).unwrap();
|
let msg = Message::from_slice(&[1; 32]).unwrap();
|
||||||
let keypair = KeyPair::from_seckey_slice(&s, &[2; 32]).unwrap();
|
let keypair = KeyPair::from_seckey_slice(&s, &[2; 32]).unwrap();
|
||||||
let aux = [3u8; 32];
|
let aux = [3u8; 32];
|
||||||
let sig = s
|
let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
|
||||||
.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
|
|
||||||
static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
|
static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
|
||||||
0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41,
|
0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41,
|
||||||
0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e,
|
0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e,
|
||||||
|
@ -479,8 +465,8 @@ mod tests {
|
||||||
";
|
";
|
||||||
|
|
||||||
static PK_BYTES: [u8; 32] = [
|
static PK_BYTES: [u8; 32] = [
|
||||||
24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127,
|
24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 48,
|
||||||
48, 170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102
|
170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102,
|
||||||
];
|
];
|
||||||
static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
|
static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
|
||||||
let pk = XOnlyPublicKey::from_slice(&PK_BYTES).unwrap();
|
let pk = XOnlyPublicKey::from_slice(&PK_BYTES).unwrap();
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
//! Helpers for displaying secret values
|
//! Helpers for displaying secret values
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use crate::{to_hex, constants::SECRET_KEY_SIZE, key::{SecretKey, KeyPair}, ecdh::SharedSecret};
|
|
||||||
|
use crate::constants::SECRET_KEY_SIZE;
|
||||||
|
use crate::ecdh::SharedSecret;
|
||||||
|
use crate::key::{KeyPair, SecretKey};
|
||||||
|
use crate::to_hex;
|
||||||
macro_rules! impl_display_secret {
|
macro_rules! impl_display_secret {
|
||||||
// Default hasher exists only in standard library and not alloc
|
// Default hasher exists only in standard library and not alloc
|
||||||
($thing:ident) => {
|
($thing:ident) => {
|
||||||
|
@ -27,7 +31,7 @@ macro_rules! impl_display_secret {
|
||||||
const DEBUG_HASH_TAG: &[u8] = &[
|
const DEBUG_HASH_TAG: &[u8] = &[
|
||||||
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
|
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
|
||||||
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
|
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
|
||||||
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
|
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22,
|
||||||
]; // =SHA256(b"rust-secp256k1DEBUG");
|
]; // =SHA256(b"rust-secp256k1DEBUG");
|
||||||
|
|
||||||
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||||
|
@ -37,9 +41,7 @@ macro_rules! impl_display_secret {
|
||||||
hasher.write(&self.secret_bytes());
|
hasher.write(&self.secret_bytes());
|
||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
|
|
||||||
f.debug_tuple(stringify!($thing))
|
f.debug_tuple(stringify!($thing)).field(&format_args!("#{:016x}", hash)).finish()
|
||||||
.field(&format_args!("#{:016x}", hash))
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +59,7 @@ macro_rules! impl_display_secret {
|
||||||
engine.input(&self.secret_bytes());
|
engine.input(&self.secret_bytes());
|
||||||
let hash = sha256::Hash::from_engine(engine);
|
let hash = sha256::Hash::from_engine(engine);
|
||||||
|
|
||||||
f.debug_tuple(stringify!($thing))
|
f.debug_tuple(stringify!($thing)).field(&format_args!("#{:016x}", hash)).finish()
|
||||||
.field(&format_args!("#{:016x}", hash))
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ macro_rules! impl_display_secret {
|
||||||
write!(f, "<secret requires std or bitcoin_hashes feature to display>")
|
write!(f, "<secret requires std or bitcoin_hashes feature to display>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper struct for safely printing secrets (like [`SecretKey`] value).
|
/// Helper struct for safely printing secrets (like [`SecretKey`] value).
|
||||||
|
@ -84,7 +84,7 @@ macro_rules! impl_display_secret {
|
||||||
/// [`Debug`]: fmt::Debug
|
/// [`Debug`]: fmt::Debug
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct DisplaySecret {
|
pub struct DisplaySecret {
|
||||||
secret: [u8; SECRET_KEY_SIZE]
|
secret: [u8; SECRET_KEY_SIZE],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for DisplaySecret {
|
impl fmt::Debug for DisplaySecret {
|
||||||
|
@ -92,9 +92,7 @@ impl fmt::Debug for DisplaySecret {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut slice = [0u8; SECRET_KEY_SIZE * 2];
|
let mut slice = [0u8; SECRET_KEY_SIZE * 2];
|
||||||
let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed");
|
let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed");
|
||||||
f.debug_tuple("DisplaySecret")
|
f.debug_tuple("DisplaySecret").field(&hex).finish()
|
||||||
.field(&hex)
|
|
||||||
.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,9 +134,7 @@ impl SecretKey {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn display_secret(&self) -> DisplaySecret {
|
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
|
||||||
DisplaySecret { secret: self.secret_bytes() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyPair {
|
impl KeyPair {
|
||||||
|
@ -172,9 +168,7 @@ impl KeyPair {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn display_secret(&self) -> DisplaySecret {
|
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
|
||||||
DisplaySecret { secret: self.secret_bytes() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedSecret {
|
impl SharedSecret {
|
||||||
|
@ -210,7 +204,5 @@ impl SharedSecret {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn display_secret(&self) -> DisplaySecret {
|
pub fn display_secret(&self) -> DisplaySecret { DisplaySecret { secret: self.secret_bytes() } }
|
||||||
DisplaySecret { secret: self.secret_bytes() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::str::{self, FromStr};
|
use core::str::{self, FromStr};
|
||||||
|
|
||||||
use serde::de;
|
use serde::de;
|
||||||
|
|
||||||
/// A serde visitor that works for `T`s implementing `FromStr`.
|
/// A serde visitor that works for `T`s implementing `FromStr`.
|
||||||
|
@ -11,10 +12,7 @@ pub struct FromStrVisitor<T> {
|
||||||
|
|
||||||
impl<T> FromStrVisitor<T> {
|
impl<T> FromStrVisitor<T> {
|
||||||
pub fn new(expectation: &'static str) -> Self {
|
pub fn new(expectation: &'static str) -> Self {
|
||||||
FromStrVisitor {
|
FromStrVisitor { expectation, _pd: PhantomData }
|
||||||
expectation,
|
|
||||||
_pd: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +43,7 @@ where
|
||||||
Err: fmt::Display,
|
Err: fmt::Display,
|
||||||
{
|
{
|
||||||
pub fn new(expectation: &'static str, parse_fn: F) -> Self {
|
pub fn new(expectation: &'static str, parse_fn: F) -> Self {
|
||||||
BytesVisitor {
|
BytesVisitor { expectation, parse_fn }
|
||||||
expectation,
|
|
||||||
parse_fn,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,10 +76,7 @@ macro_rules! impl_tuple_visitor {
|
||||||
E: fmt::Display,
|
E: fmt::Display,
|
||||||
{
|
{
|
||||||
pub fn new(expectation: &'static str, parse_fn: F) -> Self {
|
pub fn new(expectation: &'static str, parse_fn: F) -> Self {
|
||||||
$thing {
|
$thing { expectation, parse_fn }
|
||||||
expectation,
|
|
||||||
parse_fn,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +107,7 @@ macro_rules! impl_tuple_visitor {
|
||||||
(self.parse_fn)(&bytes).map_err(de::Error::custom)
|
(self.parse_fn)(&bytes).map_err(de::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_tuple_visitor!(Tuple32Visitor, 32);
|
impl_tuple_visitor!(Tuple32Visitor, 32);
|
||||||
|
|
|
@ -5,9 +5,9 @@ extern crate bincode;
|
||||||
extern crate cbor;
|
extern crate cbor;
|
||||||
extern crate secp256k1;
|
extern crate secp256k1;
|
||||||
|
|
||||||
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
|
|
||||||
#[cfg(feature = "global-context")]
|
#[cfg(feature = "global-context")]
|
||||||
use secp256k1::{Secp256k1, KeyPair};
|
use secp256k1::{KeyPair, Secp256k1};
|
||||||
|
use secp256k1::{PublicKey, SecretKey, XOnlyPublicKey};
|
||||||
|
|
||||||
// Arbitrary key data.
|
// Arbitrary key data.
|
||||||
|
|
||||||
|
@ -70,7 +70,8 @@ fn bincode_key_pair() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bincode_x_only_public_key() {
|
fn bincode_x_only_public_key() {
|
||||||
let pk = XOnlyPublicKey::from_slice(&XONLY_PK_BYTES).expect("failed to create xonly pk from slice");
|
let pk =
|
||||||
|
XOnlyPublicKey::from_slice(&XONLY_PK_BYTES).expect("failed to create xonly pk from slice");
|
||||||
let ser = bincode::serialize(&pk).unwrap();
|
let ser = bincode::serialize(&pk).unwrap();
|
||||||
|
|
||||||
assert_eq!(ser, XONLY_PK_BYTES);
|
assert_eq!(ser, XONLY_PK_BYTES);
|
||||||
|
|
Loading…
Reference in New Issue