From 5417fad7cb8f835c50ee3c85f40acbb606be397b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 27 Oct 2022 14:14:57 +1100 Subject: [PATCH] Add method SecretKey::from_hashed_data Analogous to the method on `Message`; add a constructor method on `SecretKey` that hashes the input data. While we are at it improve the rustdocs on `Message::from_hashed_data` so docs on both methods are uniform. --- src/key.rs | 36 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 17 ++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/key.rs b/src/key.rs index 2e95f46..8128145 100644 --- a/src/key.rs +++ b/src/key.rs @@ -25,6 +25,9 @@ use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey use crate::ffi::{self, CPtr, impl_array_newtype}; use crate::ffi::types::c_uint; +#[cfg(feature = "bitcoin_hashes")] +use crate::{hashes, ThirtyTwoByteHash}; + #[cfg(feature = "serde")] use serde::ser::SerializeTuple; @@ -228,6 +231,31 @@ impl SecretKey { SecretKey(sk) } + /// Constructs a [`SecretKey`] by hashing `data` with hash algorithm `H`. + /// + /// Requires the feature `bitcoin_hashes` to be enabled. + /// + /// # Examples + /// + /// ``` + /// # #[cfg(feature="bitcoin_hashes")] { + /// use secp256k1::hashes::{sha256, Hash}; + /// use secp256k1::SecretKey; + /// + /// let sk1 = SecretKey::from_hashed_data::("Hello world!".as_bytes()); + /// // is equivalent to + /// let sk2 = SecretKey::from(sha256::Hash::hash("Hello world!".as_bytes())); + /// + /// assert_eq!(sk1, sk2); + /// # } + /// ``` + #[cfg(feature = "bitcoin_hashes")] + #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))] + #[inline] + pub fn from_hashed_data(data: &[u8]) -> Self { + ::hash(data).into() + } + /// Returns the secret key as a byte value. #[inline] pub fn secret_bytes(&self) -> [u8; constants::SECRET_KEY_SIZE] { @@ -352,6 +380,14 @@ impl SecretKey { } } +#[cfg(feature = "bitcoin_hashes")] +impl From for SecretKey { + /// Converts a 32-byte hash directly to a secret key without error paths. + fn from(t: T) -> SecretKey { + SecretKey::from_slice(&t.into_32()).expect("failed to create secret key") + } +} + #[cfg(feature = "serde")] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl serde::Serialize for SecretKey { diff --git a/src/lib.rs b/src/lib.rs index 9e336b5..af6f52d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -281,20 +281,23 @@ impl Message { } } - /// Constructs a `Message` by hashing `data` with hash algorithm `H`. This requires the feature - /// `bitcoin_hashes` to be enabled. - /// ```rust - /// extern crate bitcoin_hashes; - /// # extern crate secp256k1; + /// Constructs a [`Message`] by hashing `data` with hash algorithm `H`. + /// + /// Requires the feature `bitcoin_hashes` to be enabled. + /// + /// # Examples + /// + /// ``` + /// # #[cfg(feature="bitcoin_hashes")] { + /// use secp256k1::hashes::{sha256, Hash}; /// use secp256k1::Message; - /// use bitcoin_hashes::sha256; - /// use bitcoin_hashes::Hash; /// /// let m1 = Message::from_hashed_data::("Hello world!".as_bytes()); /// // is equivalent to /// let m2 = Message::from(sha256::Hash::hash("Hello world!".as_bytes())); /// /// assert_eq!(m1, m2); + /// # } /// ``` #[cfg(feature = "bitcoin_hashes")] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))]