82 lines
2.2 KiB
Rust
82 lines
2.2 KiB
Rust
|
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()
|
||
|
}
|
||
|
}
|