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

97 lines
3.0 KiB
Rust

use crate::PublicKey;
use thiserror::Error;
pub(crate) 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<Self, Self::Err>;
}
/// 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<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()
}
}