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

83 lines
2.7 KiB
Rust
Raw Normal View History

use crate::private_key::PrivateKeyBytes;
use digest::Digest;
use ripemd::Ripemd160;
use sha2::Sha256;
use thiserror::Error;
2023-09-01 04:57:05 +00:00
pub(crate) type PublicKeyBytes = [u8; 33];
/// Functions required to use an `ExtendedPublicKey`.
pub trait PublicKey: Sized {
/// The error returned by [`PublicKey::derive_child()`].
type Err: std::error::Error;
/// Create a Self from bytes.
fn from_bytes(b: &PublicKeyBytes) -> Self;
/// Convert a &Self to bytse.
fn to_bytes(&self) -> PublicKeyBytes;
/// Derive a child [`PublicKey`] 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>;
/// Create a BIP-0032/SLIP-0010 fingerprint from the public key.
fn fingerprint(&self) -> [u8; 4] {
let hash = Sha256::new().chain_update(self.to_bytes()).finalize();
let hash = Ripemd160::new().chain_update(hash).finalize();
// Note: Safety assured by type returned from Ripemd160
hash[..4].try_into().unwrap()
}
}
/// Errors associated with creating and arithmetic on public keys. This specific error is only
/// intended to be used by the implementations in this crate.
#[derive(Clone, Debug, Error)]
pub enum PublicKeyError {
/// For the given algorithm, the private key must be nonzero.
#[error("The provided public 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::{
elliptic_curve::{group::prime::PrimeCurveAffine, sec1::ToEncodedPoint},
AffinePoint, NonZeroScalar,
};
#[cfg(feature = "secp256k1")]
impl PublicKey for k256::PublicKey {
type Err = PublicKeyError;
fn from_bytes(b: &PublicKeyBytes) -> Self {
Self::from_sec1_bytes(b).expect("Invalid public key bytes")
}
fn to_bytes(&self) -> PublicKeyBytes {
// Note: Safety assured by type returned from EncodedPoint
self.to_encoded_point(true).as_bytes().try_into().unwrap()
}
fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Self::Err> {
if other.iter().all(|n| n == &0) {
return Err(PublicKeyError::NonZero);
}
// Checked: See above
let scalar = Option::<NonZeroScalar>::from(NonZeroScalar::from_repr(other.into()))
.expect("Should have been able to get a NonZeroScalar");
let point = self.to_projective() + (AffinePoint::generator() * *scalar);
Self::from_affine(point.into()).map_err(From::from)
}
}