use core::fmt;
use crate::{to_hex, constants::SECRET_KEY_SIZE, key::{SecretKey, KeyPair}, ecdh::SharedSecret};
macro_rules! impl_display_secret {
($thing:ident) => {
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl core::fmt::Debug for $thing {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use core::hash::Hasher;
const DEBUG_HASH_TAG: &[u8] = &[
0x66, 0xa6, 0x77, 0x1b, 0x9b, 0x6d, 0xae, 0xa1, 0xb2, 0xee, 0x4e, 0x07, 0x49,
0x4a, 0xac, 0x87, 0xa9, 0xb8, 0x5b, 0x4b, 0x35, 0x02, 0xaa, 0x6d, 0x0f, 0x79,
0xcb, 0x63, 0xe6, 0xf8, 0x66, 0x22
];
let mut hasher = std::collections::hash_map::DefaultHasher::new();
hasher.write(DEBUG_HASH_TAG);
hasher.write(DEBUG_HASH_TAG);
hasher.write(&self.secret_bytes());
let hash = hasher.finish();
f.debug_tuple(stringify!($thing))
.field(&format_args!("#{:016x}", hash))
.finish()
}
}
#[cfg(all(not(feature = "std"), feature = "bitcoin_hashes"))]
impl ::core::fmt::Debug for $thing {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
use crate::hashes::{sha256, Hash, HashEngine};
let tag = "rust-secp256k1DEBUG";
let mut engine = sha256::Hash::engine();
let tag_hash = sha256::Hash::hash(tag.as_bytes());
engine.input(&tag_hash[..]);
engine.input(&tag_hash[..]);
engine.input(&self.secret_bytes());
let hash = sha256::Hash::from_engine(engine);
f.debug_tuple(stringify!($thing))
.field(&format_args!("#{:016x}", hash))
.finish()
}
}
#[cfg(all(not(feature = "std"), not(feature = "bitcoin_hashes")))]
impl ::core::fmt::Debug for $thing {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "<secret requires std or bitcoin_hashes feature to display>")
}
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DisplaySecret {
secret: [u8; SECRET_KEY_SIZE]
}
impl fmt::Debug for DisplaySecret {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut slice = [0u8; SECRET_KEY_SIZE * 2];
let hex = to_hex(&self.secret, &mut slice).expect("fixed-size hex serializer failed");
f.debug_tuple("DisplaySecret")
.field(&hex)
.finish()
}
}
impl fmt::Display for DisplaySecret {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in &self.secret {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl SecretKey {
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
}
impl KeyPair {
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
}
impl SharedSecret {
#[inline]
pub fn display_secret(&self) -> DisplaySecret {
DisplaySecret { secret: self.secret_bytes() }
}
}