diff --git a/ssh-key/src/mpint.rs b/ssh-key/src/mpint.rs index d632b44b..6c4bcd6e 100644 --- a/ssh-key/src/mpint.rs +++ b/ssh-key/src/mpint.rs @@ -1,9 +1,8 @@ //! Multiple precision integer use crate::{Error, Result}; -use alloc::vec::Vec; +use alloc::{boxed::Box, vec::Vec}; use core::fmt; -use core::hash::{Hash, Hasher}; use encoding::{CheckedSum, Decode, Encode, Reader, Writer}; use subtle::{Choice, ConstantTimeEq}; use zeroize::Zeroize; @@ -42,7 +41,7 @@ use zeroize::Zeroizing; #[derive(Clone, PartialOrd, Ord)] pub struct Mpint { /// Inner big endian-serialized integer value - inner: Vec, + inner: Box<[u8]>, } impl Mpint { @@ -69,7 +68,7 @@ impl Mpint { } inner.extend_from_slice(bytes); - inner.try_into() + inner.into_boxed_slice().try_into() } /// Get the big integer data encoded as big endian bytes. @@ -115,17 +114,11 @@ impl PartialEq for Mpint { } } -impl Hash for Mpint { - fn hash(&self, state: &mut H) { - self.inner.hash(state) - } -} - impl Decode for Mpint { type Error = Error; fn decode(reader: &mut impl Reader) -> Result { - Vec::decode(reader)?.try_into() + Vec::decode(reader)?.into_boxed_slice().try_into() } } @@ -144,15 +137,15 @@ impl TryFrom<&[u8]> for Mpint { type Error = Error; fn try_from(bytes: &[u8]) -> Result { - Vec::from(bytes).try_into() + Vec::from(bytes).into_boxed_slice().try_into() } } -impl TryFrom> for Mpint { +impl TryFrom> for Mpint { type Error = Error; - fn try_from(bytes: Vec) -> Result { - match bytes.as_slice() { + fn try_from(bytes: Box<[u8]>) -> Result { + match &*bytes { // Unnecessary leading 0 [0x00] => Err(Error::FormatEncoding), // Unnecessary leading 0 diff --git a/ssh-key/src/public/dsa.rs b/ssh-key/src/public/dsa.rs index b1c3bbbe..189aa6a1 100644 --- a/ssh-key/src/public/dsa.rs +++ b/ssh-key/src/public/dsa.rs @@ -1,12 +1,13 @@ //! Digital Signature Algorithm (DSA) public keys. use crate::{Error, Mpint, Result}; +use core::hash::{Hash, Hasher}; use encoding::{CheckedSum, Decode, Encode, Reader, Writer}; /// Digital Signature Algorithm (DSA) public key. /// /// Described in [FIPS 186-4 § 4.1](https://csrc.nist.gov/publications/detail/fips/186/4/final). -#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct DsaPublicKey { /// Prime modulus. pub p: Mpint, @@ -53,6 +54,16 @@ impl Encode for DsaPublicKey { } } +impl Hash for DsaPublicKey { + #[inline] + fn hash(&self, state: &mut H) { + self.p.as_bytes().hash(state); + self.q.as_bytes().hash(state); + self.g.as_bytes().hash(state); + self.y.as_bytes().hash(state); + } +} + #[cfg(feature = "dsa")] impl TryFrom for dsa::VerifyingKey { type Error = Error; diff --git a/ssh-key/src/public/key_data.rs b/ssh-key/src/public/key_data.rs index 176dc99d..fe7cb87a 100644 --- a/ssh-key/src/public/key_data.rs +++ b/ssh-key/src/public/key_data.rs @@ -11,7 +11,7 @@ use super::{DsaPublicKey, OpaquePublicKey, RsaPublicKey}; use super::{EcdsaPublicKey, SkEcdsaSha2NistP256}; /// Public key data. -#[derive(Clone, Debug, Hash, Ord, Eq, PartialEq, PartialOrd)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[non_exhaustive] pub enum KeyData { /// Digital Signature Algorithm (DSA) public key data. diff --git a/ssh-key/src/public/rsa.rs b/ssh-key/src/public/rsa.rs index e49d9c39..ceba11c8 100644 --- a/ssh-key/src/public/rsa.rs +++ b/ssh-key/src/public/rsa.rs @@ -1,6 +1,7 @@ //! Rivest–Shamir–Adleman (RSA) public keys. use crate::{Error, Mpint, Result}; +use core::hash::{Hash, Hasher}; use encoding::{CheckedSum, Decode, Encode, Reader, Writer}; #[cfg(feature = "rsa")] @@ -13,7 +14,7 @@ use { /// RSA public key. /// /// Described in [RFC4253 § 6.6](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6). -#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct RsaPublicKey { /// RSA public exponent. pub e: Mpint, @@ -49,6 +50,14 @@ impl Encode for RsaPublicKey { } } +impl Hash for RsaPublicKey { + #[inline] + fn hash(&self, state: &mut H) { + self.e.as_bytes().hash(state); + self.n.as_bytes().hash(state); + } +} + #[cfg(feature = "rsa")] impl TryFrom for rsa::RsaPublicKey { type Error = Error;