Skip to content

Commit adfda2e

Browse files
committed
Using dedicated safe_debug for secret key containing types
1 parent 847ee94 commit adfda2e

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

src/key.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use ffi::{self, CPtr};
2929
/// Secret 256-bit key used as `x` in an ECDSA signature
3030
pub struct SecretKey(pub(crate) [u8; constants::SECRET_KEY_SIZE]);
3131
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
32-
impl_pretty_debug!(SecretKey);
32+
impl_safe_debug!(SecretKey);
3333

3434
impl fmt::LowerHex for SecretKey {
3535
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -675,8 +675,15 @@ mod test {
675675
let s = Secp256k1::new();
676676
let (sk, _) = s.generate_keypair(&mut DumbRng(0));
677677

678+
#[cfg(all(feature = "bitcoin_hashes", not(fuzzing)))]
678679
assert_eq!(&format!("{:?}", sk),
679-
"SecretKey(0100000000000000020000000000000003000000000000000400000000000000)");
680+
"SecretKey(#73e200e2...29d234a4)");
681+
#[cfg(all(not(feature = "bitcoin_hashes"), feature = "std"))]
682+
assert_eq!(&format!("{:?}", sk),
683+
"SecretKey(#a463cd1b7ffe86b0)");
684+
#[allow(deprecated)] {
685+
assert_eq!(sk.format_secret_key(),
686+
"0100000000000000020000000000000003000000000000000400000000000000"); };
680687
}
681688

682689
#[test]

src/macros.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,84 @@ macro_rules! impl_pretty_debug {
1818
impl ::core::fmt::Debug for $thing {
1919
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
2020
write!(f, "{}(", stringify!($thing))?;
21-
for i in self[..].iter().cloned() {
21+
for i in &self[..] {
2222
write!(f, "{:02x}", i)?;
2323
}
24-
write!(f, ")")
24+
f.write_str(")")
25+
}
26+
}
27+
}
28+
}
29+
30+
macro_rules! impl_safe_debug {
31+
($thing:ident) => {
32+
#[cfg(feature = "alloc")]
33+
use alloc::string::String;
34+
35+
#[cfg(feature = "bitcoin_hashes")]
36+
impl ::core::fmt::Debug for $thing {
37+
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
38+
use ::bitcoin_hashes::{Hash, sha256};
39+
write!(f, "{}(#", stringify!($thing))?;
40+
let hash = sha256::Hash::hash(&self.0[..]);
41+
for i in &hash[..4] {
42+
write!(f, "{:02x}", i)?;
43+
}
44+
f.write_str("...")?;
45+
for i in &hash[28..] {
46+
write!(f, "{:02x}", i)?;
47+
}
48+
f.write_str(")")
49+
}
50+
}
51+
52+
#[cfg(all(not(feature = "bitcoin_hashes"), feature = "std"))]
53+
impl ::core::fmt::Debug for $thing {
54+
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
55+
use ::core::hash::Hasher;
56+
let mut hasher = ::std::collections::hash_map::DefaultHasher::new();
57+
58+
hasher.write(&self.0[..]);
59+
let hash = hasher.finish();
60+
61+
write!(f, "{}(#{:016x})", stringify!($thing), hash)
62+
}
63+
}
64+
65+
impl $thing {
66+
/// Formats the explicit byte value of the secret key kept inside the type as a
67+
/// little-endian hexadecimal string using the provided formatter.
68+
///
69+
/// This is the only method that outputs the actual secret key value, and, thus,
70+
/// should be used with extreme precaution.
71+
#[deprecated(
72+
note = "Caution: you are explicitly outputting secret key value! This can be done
73+
only in debug environment and that's why always considered as ``deprecated''"
74+
)]
75+
pub fn fmt_secret_key(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
76+
for i in &self.0[..] {
77+
write!(f, "{:02x}", i)?;
78+
}
79+
Ok(())
80+
}
81+
82+
/// Formats the explicit byte value of the secret key kept inside the type as a
83+
/// little-endian hexadecimal string.
84+
///
85+
/// This is the only method that outputs the actual secret key value, and, thus,
86+
/// should be used with extreme precaution.
87+
#[deprecated(
88+
note = "Caution: you are explicitly outputting secret key value! This can be done
89+
only in debug environment and that's why always considered as ``deprecated''"
90+
)]
91+
#[cfg(any(feature = "std", feature = "alloc"))]
92+
pub fn format_secret_key(&self) -> String {
93+
#[cfg(feature = "alloc")] use alloc::vec::Vec;
94+
let mut s = Vec::with_capacity(self.0.len());
95+
for i in &self.0[..] {
96+
s.push(format!("{:02x}", i));
97+
}
98+
s.join("")
2599
}
26100
}
27101
}

src/schnorrsig.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ impl str::FromStr for Signature {
7676
}
7777

7878
/// Opaque data structure that holds a keypair consisting of a secret and a public key.
79-
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
79+
#[derive(Clone)]
8080
pub struct KeyPair(ffi::KeyPair);
81+
impl_safe_debug!(KeyPair);
8182

8283
/// A Schnorr public key, used for verification of Schnorr signatures
8384
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]

0 commit comments

Comments
 (0)