diff --git a/crates/daemon/keyforkd-client/src/lib.rs b/crates/daemon/keyforkd-client/src/lib.rs index de31926..d1fce59 100644 --- a/crates/daemon/keyforkd-client/src/lib.rs +++ b/crates/daemon/keyforkd-client/src/lib.rs @@ -234,7 +234,7 @@ impl Client { } let depth = path.len() as u8; - Ok(ExtendedPrivateKey::new_from_parts( + Ok(ExtendedPrivateKey::from_parts( &d.data, depth, d.chain_code, diff --git a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs index 0cabf44..cd6a147 100644 --- a/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs +++ b/crates/derive/keyfork-derive-util/src/extended_key/private_key.rs @@ -124,9 +124,9 @@ mod serde_with { K: PrivateKey + Clone, { let variable_len_bytes = <&[u8]>::deserialize(deserializer)?; - let bytes: [u8; 32] = variable_len_bytes - .try_into() - .expect(bug!("unable to parse serialized private key; no support for static len")); + let bytes: [u8; 32] = variable_len_bytes.try_into().expect(bug!( + "unable to parse serialized private key; no support for static len" + )); Ok(K::from_bytes(&bytes)) } } @@ -179,13 +179,20 @@ where .into_bytes(); let (private_key, chain_code) = hash.split_at(KEY_SIZE / 8); - Self::new_from_parts( + assert!( + !private_key.iter().all(|byte| *byte == 0), + bug!("hmac function returned all-zero master key") + ); + + Self::from_parts( private_key .try_into() .expect(bug!("KEY_SIZE / 8 did not give a 32 byte slice")), 0, // Checked: chain_code is always the same length, hash is static size - chain_code.try_into().expect(bug!("Invalid chain code length")), + chain_code + .try_into() + .expect(bug!("Invalid chain code length")), ) } @@ -205,9 +212,9 @@ where /// # b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; /// let chain_code: &[u8; 32] = // /// # b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; - /// let xprv = ExtendedPrivateKey::::new_from_parts(key, 4, *chain_code); + /// let xprv = ExtendedPrivateKey::::from_parts(key, 4, *chain_code); /// ``` - pub fn new_from_parts(key: &[u8; 32], depth: u8, chain_code: [u8; 32]) -> Self { + pub fn from_parts(key: &[u8; 32], depth: u8, chain_code: [u8; 32]) -> Self { Self { private_key: K::from_bytes(key), depth, @@ -229,7 +236,7 @@ where /// # b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; /// let chain_code: &[u8; 32] = // /// # b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; - /// let xprv = ExtendedPrivateKey::::new_from_parts(key, 4, *chain_code); + /// let xprv = ExtendedPrivateKey::::from_parts(key, 4, *chain_code); /// assert_eq!(xprv.private_key(), &PrivateKey::from_bytes(key)); /// ``` pub fn private_key(&self) -> &K { @@ -262,7 +269,7 @@ where /// # } /// ``` pub fn extended_public_key(&self) -> ExtendedPublicKey { - ExtendedPublicKey::new_from_parts(self.public_key(), self.depth, self.chain_code) + ExtendedPublicKey::from_parts(self.public_key(), self.depth, self.chain_code) } /// Return a public key for the current [`PrivateKey`]. @@ -301,7 +308,7 @@ where /// # b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; /// let chain_code: &[u8; 32] = // /// # b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; - /// let xprv = ExtendedPrivateKey::::new_from_parts(key, 4, *chain_code); + /// let xprv = ExtendedPrivateKey::::from_parts(key, 4, *chain_code); /// assert_eq!(xprv.depth(), 4); /// ``` pub fn depth(&self) -> u8 { @@ -321,7 +328,7 @@ where /// # b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; /// let chain_code: &[u8; 32] = // /// # b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; - /// let xprv = ExtendedPrivateKey::::new_from_parts(key, 4, *chain_code); + /// let xprv = ExtendedPrivateKey::::from_parts(key, 4, *chain_code); /// assert_eq!(chain_code, &xprv.chain_code()); /// ``` pub fn chain_code(&self) -> [u8; 32] { diff --git a/crates/derive/keyfork-derive-util/src/extended_key/public_key.rs b/crates/derive/keyfork-derive-util/src/extended_key/public_key.rs index f366429..56dddae 100644 --- a/crates/derive/keyfork-derive-util/src/extended_key/public_key.rs +++ b/crates/derive/keyfork-derive-util/src/extended_key/public_key.rs @@ -60,11 +60,11 @@ where /// let chain_code: &[u8; 32] = // /// # b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; /// let pubkey = PublicKey::from_bytes(key); - /// let xpub = ExtendedPublicKey::::new_from_parts(pubkey, 0, *chain_code); + /// let xpub = ExtendedPublicKey::::from_parts(pubkey, 0, *chain_code); /// # Ok(()) /// # } /// ``` - pub fn new_from_parts(public_key: K, depth: u8, chain_code: ChainCode) -> Self { + pub fn from_parts(public_key: K, depth: u8, chain_code: ChainCode) -> Self { Self { public_key, depth, @@ -86,7 +86,7 @@ where /// # let chain_code: &[u8; 32] = b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; /// # let pubkey = PublicKey::from_bytes(key); /// let xpub = // - /// # ExtendedPublicKey::::new_from_parts(pubkey, 0, *chain_code); + /// # ExtendedPublicKey::::from_parts(pubkey, 0, *chain_code); /// let pubkey = xpub.public_key(); /// # Ok(()) /// # } @@ -121,7 +121,7 @@ where /// # let chain_code: &[u8; 32] = b"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; /// # let pubkey = PublicKey::from_bytes(key); /// let xpub = // - /// # ExtendedPublicKey::::new_from_parts(pubkey, 0, *chain_code); + /// # ExtendedPublicKey::::from_parts(pubkey, 0, *chain_code); /// let index = DerivationIndex::new(0, false)?; /// let child = xpub.derive_child(&index)?; /// # Ok(()) diff --git a/crates/derive/keyfork-derive-util/src/private_key.rs b/crates/derive/keyfork-derive-util/src/private_key.rs index 3e8f37e..2a600d3 100644 --- a/crates/derive/keyfork-derive-util/src/private_key.rs +++ b/crates/derive/keyfork-derive-util/src/private_key.rs @@ -102,6 +102,10 @@ 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, + + /// A scalar could not be constructed for the given algorithm. + #[error("A scalar could not be constructed for the given algorithm")] + InvalidScalar, } #[cfg(feature = "secp256k1")] @@ -130,20 +134,19 @@ impl PrivateKey for k256::SecretKey { } 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(bug!("Should have been able to get a NonZeroScalar")); + use k256::elliptic_curve::ScalarPrimitive; + use k256::{Scalar, Secp256k1}; + + // Construct a scalar from bytes + let scalar = ScalarPrimitive::::from_bytes(other.into()); + let scalar = Option::>::from(scalar); + let scalar = scalar.ok_or(PrivateKeyError::InvalidScalar)?; + let scalar = Scalar::from(scalar); let derived_scalar = self.to_nonzero_scalar().as_ref() + scalar.as_ref(); - Ok( - Option::::from(NonZeroScalar::new(derived_scalar)) - .map(Into::into) - .expect(bug!("Should be able to make Key")), - ) + let nonzero_scalar = Option::::from(NonZeroScalar::new(derived_scalar)) + .ok_or(PrivateKeyError::NonZero)?; + Ok(Self::from(nonzero_scalar)) } } @@ -202,9 +205,7 @@ impl PrivateKey for TestPrivateKey { type Err = PrivateKeyError; fn from_bytes(b: &PrivateKeyBytes) -> Self { - Self { - key: *b - } + Self { key: *b } } fn to_bytes(&self) -> PrivateKeyBytes { diff --git a/crates/derive/keyfork-derive-util/src/public_key.rs b/crates/derive/keyfork-derive-util/src/public_key.rs index 0468641..ef89244 100644 --- a/crates/derive/keyfork-derive-util/src/public_key.rs +++ b/crates/derive/keyfork-derive-util/src/public_key.rs @@ -77,6 +77,10 @@ pub enum PublicKeyError { #[error("The provided public key must be nonzero, but is not")] NonZero, + /// A scalar could not be constructed for the given algorithm. + #[error("A scalar could not be constructed for the given algorithm")] + InvalidScalar, + /// Public key derivation is unsupported for this algorithm. #[error("Public key derivation is unsupported for this algorithm")] DerivationUnsupported, @@ -85,7 +89,7 @@ pub enum PublicKeyError { #[cfg(feature = "secp256k1")] use k256::{ elliptic_curve::{group::prime::PrimeCurveAffine, sec1::ToEncodedPoint}, - AffinePoint, NonZeroScalar, + AffinePoint, }; #[cfg(feature = "secp256k1")] @@ -105,14 +109,16 @@ impl PublicKey for k256::PublicKey { } fn derive_child(&self, other: PrivateKeyBytes) -> Result { - if other.iter().all(|n| n == &0) { - return Err(PublicKeyError::NonZero); - } - // Checked: See above - let scalar = Option::::from(NonZeroScalar::from_repr(other.into())) - .expect(bug!("Should have been able to get a NonZeroScalar")); + use k256::elliptic_curve::ScalarPrimitive; + use k256::{Secp256k1, Scalar}; - let point = self.to_projective() + (AffinePoint::generator() * *scalar); + // Construct a scalar from bytes + let scalar = ScalarPrimitive::::from_bytes(&other.into()); + let scalar = Option::>::from(scalar); + let scalar = scalar.ok_or(PublicKeyError::InvalidScalar)?; + let scalar = Scalar::from(scalar); + + let point = self.to_projective() + (AffinePoint::generator() * scalar); Ok(Self::from_affine(point.into()) .expect(bug!("Could not from_affine after scalar arithmetic"))) } diff --git a/crates/derive/keyfork-derive-util/src/request.rs b/crates/derive/keyfork-derive-util/src/request.rs index 0df421c..94af23b 100644 --- a/crates/derive/keyfork-derive-util/src/request.rs +++ b/crates/derive/keyfork-derive-util/src/request.rs @@ -300,7 +300,7 @@ mod secp256k1 { fn try_from(value: &DerivationResponse) -> Result { match value.algorithm { - DerivationAlgorithm::Secp256k1 => Ok(Self::new_from_parts( + DerivationAlgorithm::Secp256k1 => Ok(Self::from_parts( &value.data, value.depth, value.chain_code, @@ -335,7 +335,7 @@ mod ed25519 { fn try_from(value: &DerivationResponse) -> Result { match value.algorithm { - DerivationAlgorithm::Ed25519 => Ok(Self::new_from_parts( + DerivationAlgorithm::Ed25519 => Ok(Self::from_parts( &value.data, value.depth, value.chain_code,