use crate::PublicKey; use thiserror::Error; pub type PrivateKeyBytes = [u8; 32]; /// Functions required to use an `ExtendedPrivateKey`. pub trait PrivateKey: Sized { /// A type implementing [`PublicKey`] associated with Self. type PublicKey: PublicKey; /// The error returned by [`PrivateKey::derive_child()`]. type Err: std::error::Error; /// Create a Self from bytes. fn from_bytes(b: &PrivateKeyBytes) -> Self; /// Convert a &Self to bytes. fn to_bytes(&self) -> PrivateKeyBytes; /// Whether or not zero is a valid public key (such as with ed25519 keys). fn is_zero_valid_public_key() -> bool { false } /// The initial key for BIP-0032 and SLIP-0010 derivation, such as secp256k1's "Bitcoin seed". fn key() -> &'static str; /// Generate a [`Self::PublicKey`]. fn public_key(&self) -> Self::PublicKey; /// Derive a child [`PrivateKey`] with given `PrivateKeyBytes`. /// /// # Errors /// /// An error may be returned if: /// * A nonzero `other` is provided. /// * An error specific to the given algorithm was encountered. fn derive_child(&self, other: &PrivateKeyBytes) -> Result; } /// Errors associated with creating and arithmetic on private keys. This specific error is only /// intended to be used by the implementations in this crate. #[derive(Clone, Debug, Error)] pub enum PrivateKeyError { /// For the given algorithm, the private key must be nonzero. #[error("The provided private key must be nonzero, but is not")] NonZero, /// Unable to convert a point to a key. #[error("Unable to convert point to key")] PointToKey(#[from] k256::elliptic_curve::Error), } #[cfg(feature = "secp256k1")] use k256::NonZeroScalar; #[cfg(feature = "secp256k1")] impl PrivateKey for k256::SecretKey { type Err = PrivateKeyError; type PublicKey = k256::PublicKey; fn key() -> &'static str { "Bitcoin seed" } fn from_bytes(b: &PrivateKeyBytes) -> Self { Self::from_slice(b).expect("Invalid private key bytes") } fn to_bytes(&self) -> PrivateKeyBytes { // Note: Safety assured by type returned from EncodedPoint self.to_bytes().into() } fn derive_child(&self, other: &PrivateKeyBytes) -> Result { if other.iter().all(|n| n == &0) { return Err(PrivateKeyError::NonZero); } let other = *other; // Checked: See above nonzero check let scalar = Option::::from(NonZeroScalar::from_repr(other.into())) .expect("Should have been able to get a NonZeroScalar"); let derived_scalar = self.to_nonzero_scalar().as_ref() + scalar.as_ref(); Ok( Option::::from(NonZeroScalar::new(derived_scalar)) .map(Into::into) .expect("Should be able to make Key"), ) } fn public_key(&self) -> Self::PublicKey { self.public_key() } }