Skip to content

Commit ce44277

Browse files
Move ECDSA functionality into ECDSA module
1 parent e0c3bb2 commit ce44277

File tree

4 files changed

+205
-204
lines changed

4 files changed

+205
-204
lines changed

src/ecdh.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ impl SharedSecret {
169169

170170
#[cfg(test)]
171171
mod tests {
172+
use super::*;
172173
use rand::thread_rng;
173-
use super::SharedSecret;
174174
use super::super::Secp256k1;
175175

176176
#[cfg(target_arch = "wasm32")]
@@ -224,7 +224,7 @@ mod tests {
224224
let x = [5u8; 32];
225225
let y = [7u8; 32];
226226
let mut output = [0u8; 64];
227-
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), ::ptr::null_mut()) };
227+
let res = unsafe { super::c_callback(output.as_mut_ptr(), x.as_ptr(), y.as_ptr(), ptr::null_mut()) };
228228
assert_eq!(res, 1);
229229
let mut new_x = [0u8; 32];
230230
let mut new_y = [0u8; 32];

src/ecdsa/mod.rs

Lines changed: 199 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! Structs and functionality related to the ECDSA signature algorithm.
22
3-
use core::{fmt, str, ops};
4-
use Error;
3+
use core::{fmt, str, ops, ptr, mem};
4+
5+
use {Signing, Verification, Message, PublicKey, Secp256k1, SecretKey, from_hex, Error, ffi};
56
use ffi::CPtr;
6-
use ffi;
7-
use from_hex;
87

98
#[cfg(feature = "recovery")]
109
mod recovery;
@@ -305,3 +304,199 @@ impl<'de> ::serde::Deserialize<'de> for Signature {
305304
}
306305
}
307306
}
307+
308+
impl<C: Signing> Secp256k1<C> {
309+
310+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
311+
/// Requires a signing-capable context.
312+
#[deprecated(since = "0.21.0", note = "Use sign_ecdsa instead.")]
313+
pub fn sign(&self, msg: &Message, sk: &SecretKey) -> Signature {
314+
self.sign_ecdsa(msg, sk)
315+
}
316+
317+
/// Constructs a signature for `msg` using the secret key `sk` and RFC6979 nonce
318+
/// Requires a signing-capable context.
319+
pub fn sign_ecdsa(&self, msg: &Message, sk: &SecretKey) -> Signature {
320+
unsafe {
321+
let mut ret = ffi::Signature::new();
322+
// We can assume the return value because it's not possible to construct
323+
// an invalid signature from a valid `Message` and `SecretKey`
324+
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
325+
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
326+
ptr::null()), 1);
327+
Signature::from(ret)
328+
}
329+
}
330+
331+
fn sign_grind_with_check(
332+
&self, msg: &Message,
333+
sk: &SecretKey,
334+
check: impl Fn(&ffi::Signature) -> bool) -> Signature {
335+
let mut entropy_p : *const ffi::types::c_void = ptr::null();
336+
let mut counter : u32 = 0;
337+
let mut extra_entropy = [0u8; 32];
338+
loop {
339+
unsafe {
340+
let mut ret = ffi::Signature::new();
341+
// We can assume the return value because it's not possible to construct
342+
// an invalid signature from a valid `Message` and `SecretKey`
343+
assert_eq!(ffi::secp256k1_ecdsa_sign(self.ctx, &mut ret, msg.as_c_ptr(),
344+
sk.as_c_ptr(), ffi::secp256k1_nonce_function_rfc6979,
345+
entropy_p), 1);
346+
if check(&ret) {
347+
return Signature::from(ret);
348+
}
349+
350+
counter += 1;
351+
// From 1.32 can use `to_le_bytes` instead
352+
let le_counter = counter.to_le();
353+
let le_counter_bytes : [u8; 4] = mem::transmute(le_counter);
354+
for (i, b) in le_counter_bytes.iter().enumerate() {
355+
extra_entropy[i] = *b;
356+
}
357+
358+
entropy_p = extra_entropy.as_ptr() as *const ffi::types::c_void;
359+
360+
// When fuzzing, these checks will usually spinloop forever, so just short-circuit them.
361+
#[cfg(fuzzing)]
362+
return Signature::from(ret);
363+
}
364+
}
365+
}
366+
367+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
368+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
369+
/// a signature that is less than 71 - bytes_to_grund bytes. The number
370+
/// of signing operation performed by this function is exponential in the
371+
/// number of bytes grinded.
372+
/// Requires a signing capable context.
373+
#[deprecated(since = "0.21.0", note = "Use sign_ecdsa_grind_r instead.")]
374+
pub fn sign_grind_r(&self, msg: &Message, sk: &SecretKey, bytes_to_grind: usize) -> Signature {
375+
self.sign_ecdsa_grind_r(msg, sk, bytes_to_grind)
376+
}
377+
378+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
379+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
380+
/// a signature that is less than 71 - bytes_to_grund bytes. The number
381+
/// of signing operation performed by this function is exponential in the
382+
/// number of bytes grinded.
383+
/// Requires a signing capable context.
384+
pub fn sign_ecdsa_grind_r(&self, msg: &Message, sk: &SecretKey, bytes_to_grind: usize) -> Signature {
385+
let len_check = |s : &ffi::Signature| der_length_check(s, 71 - bytes_to_grind);
386+
return self.sign_grind_with_check(msg, sk, len_check);
387+
}
388+
389+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
390+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
391+
/// a signature that is less than 71 bytes and compatible with the low r
392+
/// signature implementation of bitcoin core. In average, this function
393+
/// will perform two signing operations.
394+
/// Requires a signing capable context.
395+
#[deprecated(since = "0.21.0", note = "Use sign_ecdsa_grind_r instead.")]
396+
pub fn sign_low_r(&self, msg: &Message, sk: &SecretKey) -> Signature {
397+
return self.sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
398+
}
399+
400+
/// Constructs a signature for `msg` using the secret key `sk`, RFC6979 nonce
401+
/// and "grinds" the nonce by passing extra entropy if necessary to produce
402+
/// a signature that is less than 71 bytes and compatible with the low r
403+
/// signature implementation of bitcoin core. In average, this function
404+
/// will perform two signing operations.
405+
/// Requires a signing capable context.
406+
pub fn sign_ecdsa_low_r(&self, msg: &Message, sk: &SecretKey) -> Signature {
407+
return self.sign_grind_with_check(msg, sk, compact_sig_has_zero_first_bit)
408+
}
409+
}
410+
411+
impl<C: Verification> Secp256k1<C> {
412+
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
413+
/// key `pubkey`. Returns `Ok(())` on success. Note that this function cannot
414+
/// be used for Bitcoin consensus checking since there may exist signatures
415+
/// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a
416+
/// verify-capable context.
417+
///
418+
/// ```rust
419+
/// # #[cfg(feature="rand")] {
420+
/// # use secp256k1::rand::rngs::OsRng;
421+
/// # use secp256k1::{Secp256k1, Message, Error};
422+
/// #
423+
/// # let secp = Secp256k1::new();
424+
/// # let mut rng = OsRng::new().expect("OsRng");
425+
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rng);
426+
/// #
427+
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
428+
/// let sig = secp.sign(&message, &secret_key);
429+
/// assert_eq!(secp.verify(&message, &sig, &public_key), Ok(()));
430+
///
431+
/// let message = Message::from_slice(&[0xcd; 32]).expect("32 bytes");
432+
/// assert_eq!(secp.verify(&message, &sig, &public_key), Err(Error::IncorrectSignature));
433+
/// # }
434+
/// ```
435+
#[inline]
436+
#[deprecated(since = "0.21.0", note = "Use verify_ecdsa instead")]
437+
pub fn verify(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> {
438+
self.verify_ecdsa(msg, sig, pk)
439+
}
440+
441+
/// Checks that `sig` is a valid ECDSA signature for `msg` using the public
442+
/// key `pubkey`. Returns `Ok(())` on success. Note that this function cannot
443+
/// be used for Bitcoin consensus checking since there may exist signatures
444+
/// which OpenSSL would verify but not libsecp256k1, or vice-versa. Requires a
445+
/// verify-capable context.
446+
///
447+
/// ```rust
448+
/// # #[cfg(feature="rand")] {
449+
/// # use secp256k1::rand::rngs::OsRng;
450+
/// # use secp256k1::{Secp256k1, Message, Error};
451+
/// #
452+
/// # let secp = Secp256k1::new();
453+
/// # let mut rng = OsRng::new().expect("OsRng");
454+
/// # let (secret_key, public_key) = secp.generate_keypair(&mut rng);
455+
/// #
456+
/// let message = Message::from_slice(&[0xab; 32]).expect("32 bytes");
457+
/// let sig = secp.sign_ecdsa(&message, &secret_key);
458+
/// assert_eq!(secp.verify_ecdsa(&message, &sig, &public_key), Ok(()));
459+
///
460+
/// let message = Message::from_slice(&[0xcd; 32]).expect("32 bytes");
461+
/// assert_eq!(secp.verify_ecdsa(&message, &sig, &public_key), Err(Error::IncorrectSignature));
462+
/// # }
463+
/// ```
464+
#[inline]
465+
pub fn verify_ecdsa(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> {
466+
unsafe {
467+
if ffi::secp256k1_ecdsa_verify(self.ctx, sig.as_c_ptr(), msg.as_c_ptr(), pk.as_c_ptr()) == 0 {
468+
Err(Error::IncorrectSignature)
469+
} else {
470+
Ok(())
471+
}
472+
}
473+
}
474+
}
475+
476+
pub(crate) fn compact_sig_has_zero_first_bit(sig: &ffi::Signature) -> bool {
477+
let mut compact = [0u8; 64];
478+
unsafe {
479+
let err = ffi::secp256k1_ecdsa_signature_serialize_compact(
480+
ffi::secp256k1_context_no_precomp,
481+
compact.as_mut_c_ptr(),
482+
sig,
483+
);
484+
debug_assert!(err == 1);
485+
}
486+
compact[0] < 0x80
487+
}
488+
489+
pub(crate) fn der_length_check(sig: &ffi::Signature, max_len: usize) -> bool {
490+
let mut ser_ret = [0u8; 72];
491+
let mut len: usize = ser_ret.len();
492+
unsafe {
493+
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
494+
ffi::secp256k1_context_no_precomp,
495+
ser_ret.as_mut_c_ptr(),
496+
&mut len,
497+
sig,
498+
);
499+
debug_assert!(err == 1);
500+
}
501+
len <= max_len
502+
}

src/key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ impl KeyPair {
589589
/// Creates a new random secret key. Requires compilation with the "rand" feature.
590590
#[inline]
591591
#[cfg(any(test, feature = "rand"))]
592-
pub fn new<R: Rng + ?Sized, C: Signing>(secp: &Secp256k1<C>, rng: &mut R) -> KeyPair {
592+
pub fn new<R: ::rand::Rng + ?Sized, C: Signing>(secp: &Secp256k1<C>, rng: &mut R) -> KeyPair {
593593
let mut random_32_bytes = || {
594594
let mut ret = [0u8; 32];
595595
rng.fill_bytes(&mut ret);

0 commit comments

Comments
 (0)