Merge rust-bitcoin/rust-secp256k1#493: Add method `SecretKey::from_hashed_data`

5417fad7cb Add method SecretKey::from_hashed_data (Tobin C. Harding)

Pull request description:

  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.

  Fix: #487

ACKs for top commit:
  apoelstra:
    ACK 5417fad7cb

Tree-SHA512: d321c1e8fddaf5ee692a7f119d86749ea4c8b4f3796f06e8c6145aa03bc22f5c88992e193dd34aa7ba3da8a45cf8f60e72f61e415a092ad16d2bd8c2b6c8fa23
This commit is contained in:
Andrew Poelstra 2022-10-28 20:17:53 +00:00
commit 14b964c8c3
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
2 changed files with 46 additions and 7 deletions

View File

@ -25,6 +25,9 @@ use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey
use crate::ffi::{self, CPtr, impl_array_newtype}; use crate::ffi::{self, CPtr, impl_array_newtype};
use crate::ffi::types::c_uint; use crate::ffi::types::c_uint;
#[cfg(feature = "bitcoin_hashes")]
use crate::{hashes, ThirtyTwoByteHash};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::ser::SerializeTuple; use serde::ser::SerializeTuple;
@ -228,6 +231,31 @@ impl SecretKey {
SecretKey(sk) 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::<sha256::Hash>("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<H: ThirtyTwoByteHash + hashes::Hash>(data: &[u8]) -> Self {
<H as hashes::Hash>::hash(data).into()
}
/// Returns the secret key as a byte value. /// Returns the secret key as a byte value.
#[inline] #[inline]
pub fn secret_bytes(&self) -> [u8; constants::SECRET_KEY_SIZE] { pub fn secret_bytes(&self) -> [u8; constants::SECRET_KEY_SIZE] {
@ -352,6 +380,14 @@ impl SecretKey {
} }
} }
#[cfg(feature = "bitcoin_hashes")]
impl<T: ThirtyTwoByteHash> From<T> 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(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::Serialize for SecretKey { impl serde::Serialize for SecretKey {

View File

@ -281,20 +281,23 @@ impl Message {
} }
} }
/// Constructs a `Message` by hashing `data` with hash algorithm `H`. This requires the feature /// Constructs a [`Message`] by hashing `data` with hash algorithm `H`.
/// `bitcoin_hashes` to be enabled. ///
/// ```rust /// Requires the feature `bitcoin_hashes` to be enabled.
/// extern crate bitcoin_hashes; ///
/// # extern crate secp256k1; /// # Examples
///
/// ```
/// # #[cfg(feature="bitcoin_hashes")] {
/// use secp256k1::hashes::{sha256, Hash};
/// use secp256k1::Message; /// use secp256k1::Message;
/// use bitcoin_hashes::sha256;
/// use bitcoin_hashes::Hash;
/// ///
/// let m1 = Message::from_hashed_data::<sha256::Hash>("Hello world!".as_bytes()); /// let m1 = Message::from_hashed_data::<sha256::Hash>("Hello world!".as_bytes());
/// // is equivalent to /// // is equivalent to
/// let m2 = Message::from(sha256::Hash::hash("Hello world!".as_bytes())); /// let m2 = Message::from(sha256::Hash::hash("Hello world!".as_bytes()));
/// ///
/// assert_eq!(m1, m2); /// assert_eq!(m1, m2);
/// # }
/// ``` /// ```
#[cfg(feature = "bitcoin_hashes")] #[cfg(feature = "bitcoin_hashes")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))] #[cfg_attr(docsrs, doc(cfg(feature = "bitcoin_hashes")))]