use crate::PublicKey; use thiserror::Error; pub type PrivateKeyBytes = [u8; 32]; pub trait PrivateKey: Sized { type PublicKey: PublicKey; type Err: std::error::Error; fn from_bytes(b: &PrivateKeyBytes) -> Self; fn to_bytes(&self) -> PrivateKeyBytes; fn is_zero_valid_public_key() -> bool { false } fn key() -> &'static str; 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; } #[derive(Clone, Debug, Error)] pub enum PrivateKeyError { #[error("The provided private key must be nonzero, but is not")] NonZero, #[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() } }