Skip to content

Commit 5db4115

Browse files
committed
Obfuscate SharedSecret when printing
Currently printing the `SharedSecret` using `Display` or `Debug` prints the real secret, this is sub-optimal. We have a solution for other secrets in the project where printing is obfuscated and we provide a `display_secret` method for explicitly printing. Mirror the logic for other secrets and obfuscate the `SharedSecret` when printing.
1 parent babc36c commit 5db4115

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

src/ecdh.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ use core::borrow::Borrow;
2121
use key::{SecretKey, PublicKey};
2222
use ffi::{self, CPtr};
2323
use secp256k1_sys::types::{c_int, c_uchar, c_void};
24+
use constants;
25+
26+
// The logic for displaying shared secrets relies on this (see `secret.rs`).
27+
const SHARED_SECRET_SIZE: usize = constants::SECRET_KEY_SIZE;
2428

2529
/// Enables two parties to create a shared secret without revealing their own secrets.
2630
///
@@ -39,14 +43,15 @@ use secp256k1_sys::types::{c_int, c_uchar, c_void};
3943
/// assert_eq!(sec1, sec2);
4044
/// # }
4145
// ```
42-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
43-
pub struct SharedSecret([u8; 32]);
46+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
47+
pub struct SharedSecret([u8; SHARED_SECRET_SIZE]);
48+
impl_display_secret!(SharedSecret);
4449

4550
impl SharedSecret {
4651
/// Creates a new shared secret from a pubkey and secret key.
4752
#[inline]
4853
pub fn new(point: &PublicKey, scalar: &SecretKey) -> SharedSecret {
49-
let mut buf = [0u8; 32];
54+
let mut buf = [0u8; SHARED_SECRET_SIZE];
5055
let res = unsafe {
5156
ffi::secp256k1_ecdh(
5257
ffi::secp256k1_context_no_precomp,
@@ -60,6 +65,12 @@ impl SharedSecret {
6065
debug_assert_eq!(res, 1);
6166
SharedSecret(buf)
6267
}
68+
69+
/// Gets the shared secret as a byte value.
70+
#[inline]
71+
pub fn into_secret(&self) -> [u8; SHARED_SECRET_SIZE] {
72+
self.0
73+
}
6374
}
6475

6576
impl Borrow<[u8]> for SharedSecret {

src/secret.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use ::core::fmt;
1818
use ::{SecretKey, KeyPair, to_hex};
19+
use ecdh::SharedSecret;
1920
use constants::SECRET_KEY_SIZE;
2021

2122
macro_rules! impl_display_secret {
@@ -177,3 +178,40 @@ impl KeyPair {
177178
DisplaySecret { secret: self.into_secret() }
178179
}
179180
}
181+
182+
impl SharedSecret {
183+
/// Formats the explicit byte value of the shared secret kept inside the type as a
184+
/// little-endian hexadecimal string using the provided formatter.
185+
///
186+
/// This is the only method that outputs the actual shared secret value, and, thus,
187+
/// should be used with extreme caution.
188+
///
189+
/// # Examples
190+
///
191+
/// ```
192+
/// # #[cfg(feature = "std")] {
193+
/// # use std::str::FromStr;
194+
/// # use secp256k1::{SecretKey, PublicKey};
195+
/// use secp256k1::ecdh::SharedSecret;
196+
///
197+
/// # let pk = PublicKey::from_slice(&[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]).expect("hard coded slice should parse correctly");
198+
/// # let sk = SecretKey::from_str("57f0148f94d13095cfda539d0da0d1541304b678d8b36e243980aab4e1b7cead").unwrap();
199+
///
200+
/// let secret = SharedSecret::new(&pk, &sk);
201+
/// // Here we explicitly display the secret value:
202+
/// assert_eq!(
203+
/// format!("{}", secret.display_secret()),
204+
/// "cf05ae7da039ddce6d56dd57d3000c6dd91c6f1695eae47e05389f11e2467043"
205+
/// );
206+
/// // Also, we can explicitly display with `Debug`:
207+
/// assert_eq!(
208+
/// format!("{:?}", secret.display_secret()),
209+
/// format!("DisplaySecret(\"{}\")", secret.display_secret())
210+
/// );
211+
/// # }
212+
/// ```
213+
#[inline]
214+
pub fn display_secret(&self) -> DisplaySecret {
215+
DisplaySecret { secret: self.into_secret() }
216+
}
217+
}

0 commit comments

Comments
 (0)