Skip to content

Commit 9d43945

Browse files
committed
Stop implementing ThirtyTwoByteHash
The implementations of `ThirtyTwoByteHash` for types from the `hashes` crate are problematic during upgrades because both `bitcoin` and `secp256k1` depend on `hashes` and when the versions of `hashes` get out of sync usage of the trait breaks. In order to resolve this issue stop implementing `ThirtyTwoByteHash` for the `hashes` types, this means also that we cannot use the `hashes::Hash` trait bound when implementing `from_hashed_data` for `SecretKey` or `Message` (because of the bound on `From`). We can still provide the `from_hashed_data` helper function but we now restrict it to only hashing with `sha256` instead of a generic hasher. Users can still create the `Message` and `SecretKey` types from other hashes but to do so they must do it manually, this is documented in the update rustdocs for each function.
1 parent b370f67 commit 9d43945

File tree

2 files changed

+14
-45
lines changed

2 files changed

+14
-45
lines changed

src/key.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,19 @@ impl SecretKey {
268268
/// use secp256k1::hashes::{sha256, Hash};
269269
/// use secp256k1::SecretKey;
270270
///
271-
/// let sk1 = SecretKey::from_hashed_data::<sha256::Hash>("Hello world!".as_bytes());
271+
/// let sk1 = SecretKey::from_hashed_data("Hello world!".as_bytes());
272272
/// // is equivalent to
273-
/// let sk2 = SecretKey::from(sha256::Hash::hash("Hello world!".as_bytes()));
273+
/// let sk2 = SecretKey::from_slice(sha256::Hash::hash("Hello world!".as_bytes()).as_byte_array()).unwrap();
274274
///
275275
/// assert_eq!(sk1, sk2);
276276
/// # }
277277
/// ```
278278
#[cfg(feature = "hashes")]
279279
#[inline]
280-
pub fn from_hashed_data<H: ThirtyTwoByteHash + hashes::Hash>(data: &[u8]) -> Self {
281-
<H as hashes::Hash>::hash(data).into()
280+
pub fn from_hashed_data(data: &[u8]) -> Self {
281+
use hashes::{sha256, Hash};
282+
let hash = sha256::Hash::hash(data);
283+
SecretKey::from_slice(hash.as_byte_array()).expect("sha256 hash is 32 bytes")
282284
}
283285

284286
/// Returns the secret key as a byte value.

src/lib.rs

+8-41
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
//!
3636
//! let secp = Secp256k1::new();
3737
//! let (secret_key, public_key) = secp.generate_keypair(&mut OsRng);
38-
//! let message = Message::from_hashed_data::<sha256::Hash>("Hello World!".as_bytes());
38+
//! let message = Message::from_hashed_data("Hello World!".as_bytes());
3939
//!
4040
//! let sig = secp.sign_ecdsa(&message, &secret_key);
4141
//! assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());
@@ -50,7 +50,7 @@
5050
//! use secp256k1::hashes::sha256;
5151
//!
5252
//! let (secret_key, public_key) = generate_keypair(&mut rand::thread_rng());
53-
//! let message = Message::from_hashed_data::<sha256::Hash>("Hello World!".as_bytes());
53+
//! let message = Message::from_hashed_data("Hello World!".as_bytes());
5454
//!
5555
//! let sig = secret_key.sign_ecdsa(message);
5656
//! assert!(sig.verify(&message, &public_key).is_ok());
@@ -176,8 +176,6 @@ use core::{fmt, mem, str};
176176

177177
#[cfg(all(feature = "global-context", feature = "std"))]
178178
pub use context::global::{self, SECP256K1};
179-
#[cfg(feature = "hashes")]
180-
use hashes::Hash;
181179
#[cfg(feature = "rand")]
182180
pub use rand;
183181
pub use secp256k1_sys as ffi;
@@ -203,21 +201,6 @@ pub trait ThirtyTwoByteHash {
203201
fn into_32(self) -> [u8; 32];
204202
}
205203

206-
#[cfg(feature = "hashes")]
207-
impl ThirtyTwoByteHash for hashes::sha256::Hash {
208-
fn into_32(self) -> [u8; 32] { self.to_byte_array() }
209-
}
210-
211-
#[cfg(feature = "hashes")]
212-
impl ThirtyTwoByteHash for hashes::sha256d::Hash {
213-
fn into_32(self) -> [u8; 32] { self.to_byte_array() }
214-
}
215-
216-
#[cfg(feature = "hashes")]
217-
impl<T: hashes::sha256t::Tag> ThirtyTwoByteHash for hashes::sha256t::Hash<T> {
218-
fn into_32(self) -> [u8; 32] { self.to_byte_array() }
219-
}
220-
221204
/// A (hashed) message input to an ECDSA signature.
222205
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
223206
pub struct Message([u8; constants::MESSAGE_SIZE]);
@@ -284,16 +267,18 @@ impl Message {
284267
/// use secp256k1::hashes::{sha256, Hash};
285268
/// use secp256k1::Message;
286269
///
287-
/// let m1 = Message::from_hashed_data::<sha256::Hash>("Hello world!".as_bytes());
270+
/// let m1 = Message::from_hashed_data("Hello world!".as_bytes());
288271
/// // is equivalent to
289-
/// let m2 = Message::from(sha256::Hash::hash("Hello world!".as_bytes()));
272+
/// let m2 = Message::from_digest(sha256::Hash::hash("Hello world!".as_bytes()).to_byte_array());
290273
///
291274
/// assert_eq!(m1, m2);
292275
/// # }
293276
/// ```
294277
#[cfg(feature = "hashes")]
295-
pub fn from_hashed_data<H: ThirtyTwoByteHash + hashes::Hash>(data: &[u8]) -> Self {
296-
<H as hashes::Hash>::hash(data).into()
278+
pub fn from_hashed_data(data: &[u8]) -> Self {
279+
use hashes::{sha256, Hash};
280+
let hash = sha256::Hash::hash(data);
281+
Message::from_digest(hash.to_byte_array())
297282
}
298283
}
299284

@@ -1043,24 +1028,6 @@ mod tests {
10431028
let sig = SECP256K1.sign_ecdsa(&msg, &sk);
10441029
assert!(SECP256K1.verify_ecdsa(&msg, &sig, &pk).is_ok());
10451030
}
1046-
1047-
#[cfg(feature = "hashes")]
1048-
#[test]
1049-
fn test_from_hash() {
1050-
use hashes::{sha256, sha256d, Hash};
1051-
1052-
let test_bytes = "Hello world!".as_bytes();
1053-
1054-
let hash = sha256::Hash::hash(test_bytes);
1055-
let msg = Message::from(hash);
1056-
assert_eq!(msg.0, hash.to_byte_array());
1057-
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256::Hash>(test_bytes));
1058-
1059-
let hash = sha256d::Hash::hash(test_bytes);
1060-
let msg = Message::from(hash);
1061-
assert_eq!(msg.0, hash.to_byte_array());
1062-
assert_eq!(msg, Message::from_hashed_data::<hashes::sha256d::Hash>(test_bytes));
1063-
}
10641031
}
10651032

10661033
#[cfg(bench)]

0 commit comments

Comments
 (0)