diff --git a/ssh-encoding/src/mpint.rs b/ssh-encoding/src/mpint.rs index 7c479732..ca0b3d48 100644 --- a/ssh-encoding/src/mpint.rs +++ b/ssh-encoding/src/mpint.rs @@ -1,4 +1,4 @@ -//! Multiple precision integer +//! Multiple precision integer. use crate::{CheckedSum, Decode, Encode, Error, Reader, Result, Writer}; use alloc::{boxed::Box, vec::Vec}; @@ -48,34 +48,42 @@ pub struct Mpint { } impl Mpint { - /// Create a new multiple precision integer from the given - /// big endian-encoded byte slice. + /// Create a new multiple precision integer from the given big endian-encoded byte slice. /// - /// Note that this method expects a leading zero on positive integers whose - /// MSB is set, but does *NOT* expect a 4-byte length prefix. + /// Note that this method expects a leading zero on positive integers whose MSB is set, but does + /// *NOT* expect a 4-byte length prefix. + /// + /// # Errors + /// Returns [`Error::MpintEncoding`] in the event of an unnecessary leading `0`. pub fn from_bytes(bytes: &[u8]) -> Result { bytes.try_into() } - /// Create a new multiple precision integer from the given big endian - /// encoded byte slice representing a positive integer. + /// Create a new multiple precision integer from the given big endian encoded byte slice + /// representing a positive integer. /// - /// The input may begin with leading zeros, which will be stripped when - /// converted to [`Mpint`] encoding. - pub fn from_positive_bytes(mut bytes: &[u8]) -> Result { - let mut inner = Vec::with_capacity(bytes.len()); - + /// The input may begin with leading zeros, which will be stripped when converted to [`Mpint`] + /// encoding. + pub fn from_positive_bytes(mut bytes: &[u8]) -> Self { + // Strip leading zeros while bytes.first().copied() == Some(0) { bytes = &bytes[1..]; } - match bytes.first().copied() { - Some(n) if n >= 0x80 => inner.push(0), - _ => (), + // Add a leading zero to the output if necessary + let inner = match bytes.first().copied() { + Some(n) if n >= 0x80 => { + let mut inner = Vec::with_capacity(bytes.len().saturating_add(1)); + inner.push(0); + inner.extend_from_slice(bytes); + inner + } + _ => Vec::from(bytes), + }; + + Self { + inner: inner.into_boxed_slice(), } - - inner.extend_from_slice(bytes); - inner.into_boxed_slice().try_into() } /// Get the big integer data encoded as big endian bytes. @@ -208,21 +216,17 @@ impl fmt::UpperHex for Mpint { } #[cfg(feature = "bigint")] -impl TryFrom for Mpint { - type Error = Error; - - fn try_from(uint: Uint) -> Result { - Mpint::try_from(&uint) +impl From<&Uint> for Mpint { + fn from(uint: &Uint) -> Mpint { + let bytes = Zeroizing::new(uint.to_be_bytes()); + Mpint::from_positive_bytes(&bytes) } } #[cfg(feature = "bigint")] -impl TryFrom<&Uint> for Mpint { - type Error = Error; - - fn try_from(uint: &Uint) -> Result { - let bytes = Zeroizing::new(uint.to_be_bytes()); - Mpint::from_positive_bytes(&bytes) +impl From for Mpint { + fn from(uint: Uint) -> Mpint { + Mpint::from(&uint) } } @@ -278,18 +282,9 @@ mod tests { } #[test] fn from_positive_bytes_strips_leading_zeroes() { - assert_eq!( - Mpint::from_positive_bytes(&hex!("00")).unwrap().as_ref(), - b"" - ); - assert_eq!( - Mpint::from_positive_bytes(&hex!("00 00")).unwrap().as_ref(), - b"" - ); - assert_eq!( - Mpint::from_positive_bytes(&hex!("00 01")).unwrap().as_ref(), - b"\x01" - ); + assert_eq!(Mpint::from_positive_bytes(&hex!("00")).as_ref(), b""); + assert_eq!(Mpint::from_positive_bytes(&hex!("00 00")).as_ref(), b""); + assert_eq!(Mpint::from_positive_bytes(&hex!("00 01")).as_ref(), b"\x01"); } // TODO(tarcieri): drop support for negative numbers? diff --git a/ssh-key/src/private/dsa.rs b/ssh-key/src/private/dsa.rs index 85dc240d..496845fe 100644 --- a/ssh-key/src/private/dsa.rs +++ b/ssh-key/src/private/dsa.rs @@ -104,40 +104,36 @@ impl Drop for DsaPrivateKey { } #[cfg(feature = "dsa")] -impl TryFrom for Uint { - type Error = Error; - - fn try_from(key: DsaPrivateKey) -> Result { - Ok(Uint::try_from(&key.inner)?) +impl From<&dsa::SigningKey> for DsaPrivateKey { + fn from(key: &dsa::SigningKey) -> DsaPrivateKey { + DsaPrivateKey { + inner: key.x().as_ref().into(), + } } } #[cfg(feature = "dsa")] -impl TryFrom<&DsaPrivateKey> for Uint { - type Error = Error; - - fn try_from(key: &DsaPrivateKey) -> Result { - Ok(Uint::try_from(&key.inner)?) +impl From for DsaPrivateKey { + fn from(key: dsa::SigningKey) -> DsaPrivateKey { + DsaPrivateKey::from(&key) } } #[cfg(feature = "dsa")] -impl TryFrom for DsaPrivateKey { +impl TryFrom for Uint { type Error = Error; - fn try_from(key: dsa::SigningKey) -> Result { - DsaPrivateKey::try_from(&key) + fn try_from(key: DsaPrivateKey) -> Result { + Ok(Uint::try_from(&key.inner)?) } } #[cfg(feature = "dsa")] -impl TryFrom<&dsa::SigningKey> for DsaPrivateKey { +impl TryFrom<&DsaPrivateKey> for Uint { type Error = Error; - fn try_from(key: &dsa::SigningKey) -> Result { - Ok(DsaPrivateKey { - inner: key.x().as_ref().try_into()?, - }) + fn try_from(key: &DsaPrivateKey) -> Result { + Ok(Uint::try_from(&key.inner)?) } } @@ -161,7 +157,7 @@ impl DsaKeypair { #[cfg(all(feature = "dsa", feature = "rand_core"))] pub fn random(rng: &mut R) -> Result { let components = dsa::Components::generate(rng, Self::KEY_SIZE); - dsa::SigningKey::generate(rng, components).try_into() + Ok(dsa::SigningKey::generate(rng, components).into()) } /// Create a new [`DsaKeypair`] with the given `public` and `private` components. @@ -258,22 +254,18 @@ impl TryFrom<&DsaKeypair> for dsa::SigningKey { } #[cfg(feature = "dsa")] -impl TryFrom for DsaKeypair { - type Error = Error; - - fn try_from(key: dsa::SigningKey) -> Result { - DsaKeypair::try_from(&key) +impl From for DsaKeypair { + fn from(key: dsa::SigningKey) -> DsaKeypair { + DsaKeypair::from(&key) } } #[cfg(feature = "dsa")] -impl TryFrom<&dsa::SigningKey> for DsaKeypair { - type Error = Error; - - fn try_from(key: &dsa::SigningKey) -> Result { - Ok(DsaKeypair { - private: key.try_into()?, - public: key.verifying_key().try_into()?, - }) +impl From<&dsa::SigningKey> for DsaKeypair { + fn from(key: &dsa::SigningKey) -> DsaKeypair { + DsaKeypair { + private: key.into(), + public: key.verifying_key().into(), + } } } diff --git a/ssh-key/src/private/rsa.rs b/ssh-key/src/private/rsa.rs index ac3413c2..1ec72b50 100644 --- a/ssh-key/src/private/rsa.rs +++ b/ssh-key/src/private/rsa.rs @@ -280,10 +280,10 @@ impl TryFrom<&rsa::RsaPrivateKey> for RsaKeypair { let iqmp = key.crt_coefficient().ok_or(Error::Crypto)?; let private = RsaPrivateKey { - d: key.d().try_into()?, - iqmp: iqmp.try_into()?, - p: p.try_into()?, - q: q.try_into()?, + d: key.d().into(), + iqmp: iqmp.into(), + p: p.into(), + q: q.into(), }; Ok(RsaKeypair { public, private }) diff --git a/ssh-key/src/public/dsa.rs b/ssh-key/src/public/dsa.rs index 14b44c04..5a4cd678 100644 --- a/ssh-key/src/public/dsa.rs +++ b/ssh-key/src/public/dsa.rs @@ -130,24 +130,20 @@ impl TryFrom<&DsaPublicKey> for dsa::VerifyingKey { } #[cfg(feature = "dsa")] -impl TryFrom for DsaPublicKey { - type Error = Error; - - fn try_from(key: dsa::VerifyingKey) -> Result { - DsaPublicKey::try_from(&key) +impl From for DsaPublicKey { + fn from(key: dsa::VerifyingKey) -> DsaPublicKey { + DsaPublicKey::from(&key) } } #[cfg(feature = "dsa")] -impl TryFrom<&dsa::VerifyingKey> for DsaPublicKey { - type Error = Error; - - fn try_from(key: &dsa::VerifyingKey) -> Result { - Ok(DsaPublicKey { - p: key.components().p().as_ref().try_into()?, - q: key.components().q().as_ref().try_into()?, - g: key.components().g().as_ref().try_into()?, - y: key.y().as_ref().try_into()?, - }) +impl From<&dsa::VerifyingKey> for DsaPublicKey { + fn from(key: &dsa::VerifyingKey) -> DsaPublicKey { + DsaPublicKey { + p: key.components().p().as_ref().into(), + q: key.components().q().as_ref().into(), + g: key.components().g().as_ref().into(), + y: key.y().as_ref().into(), + } } } diff --git a/ssh-key/src/public/rsa.rs b/ssh-key/src/public/rsa.rs index 5d43471a..725c7ce6 100644 --- a/ssh-key/src/public/rsa.rs +++ b/ssh-key/src/public/rsa.rs @@ -129,9 +129,7 @@ impl TryFrom<&rsa::RsaPublicKey> for RsaPublicKey { type Error = Error; fn try_from(key: &rsa::RsaPublicKey) -> Result { - let e = Mpint::try_from(key.e())?; - let n = Mpint::try_from(key.n().as_ref())?; - RsaPublicKey::new(e, n) + RsaPublicKey::new(key.e().into(), key.n().as_ref().into()) } } diff --git a/ssh-key/src/signature.rs b/ssh-key/src/signature.rs index aab3f02b..eff80106 100644 --- a/ssh-key/src/signature.rs +++ b/ssh-key/src/signature.rs @@ -512,8 +512,8 @@ macro_rules! impl_signature_for_curve { #[allow(clippy::arithmetic_side_effects)] let mut data = Vec::with_capacity($size * 2 + 4 * 2 + 2); - Mpint::from_positive_bytes(&r)?.encode(&mut data)?; - Mpint::from_positive_bytes(&s)?.encode(&mut data)?; + Mpint::from_positive_bytes(&r).encode(&mut data)?; + Mpint::from_positive_bytes(&s).encode(&mut data)?; Ok(Signature { algorithm: Algorithm::Ecdsa {