keyfork/keyfork-derive-util/src/private_key.rs

82 lines
2.2 KiB
Rust
Raw Normal View History

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<Self, Self::Err>;
}
#[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<Self, Self::Err> {
if other.iter().all(|n| n == &0) {
return Err(PrivateKeyError::NonZero);
}
let other = *other;
// Checked: See above nonzero check
let scalar = Option::<NonZeroScalar>::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::<NonZeroScalar>::from(NonZeroScalar::new(derived_scalar))
.map(Into::into)
.expect("Should be able to make Key"),
)
}
fn public_key(&self) -> Self::PublicKey {
self.public_key()
}
}