From 9d61e289b855a1d4f629d3eeca3c2a67d311a473 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 1 Feb 2022 06:56:54 -0700 Subject: [PATCH] ssh-key: DSA `PublicKey` encoder support --- ssh-key/src/mpint.rs | 12 +++++++++++- ssh-key/src/public.rs | 4 ++++ ssh-key/src/public/dsa.rs | 18 +++++++++++++++++- ssh-key/tests/public_key.rs | 15 +++++++++++---- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ssh-key/src/mpint.rs b/ssh-key/src/mpint.rs index 2e7c3396f..a4c9f07bc 100644 --- a/ssh-key/src/mpint.rs +++ b/ssh-key/src/mpint.rs @@ -1,7 +1,7 @@ //! Multiple precision integer use crate::{ - base64::{self, Decode}, + base64::{self, Decode, Encode}, Error, Result, }; use alloc::vec::Vec; @@ -89,6 +89,16 @@ impl Decode for MPInt { } } +impl Encode for MPInt { + fn encoded_len(&self) -> Result { + Ok(4 + self.as_bytes().len()) + } + + fn encode(&self, encoder: &mut base64::Encoder<'_>) -> Result<()> { + encoder.encode_byte_slice(self.as_bytes()) + } +} + impl TryFrom<&[u8]> for MPInt { type Error = Error; diff --git a/ssh-key/src/public.rs b/ssh-key/src/public.rs index 19be2cd04..44c47ae42 100644 --- a/ssh-key/src/public.rs +++ b/ssh-key/src/public.rs @@ -244,6 +244,8 @@ impl Encode for KeyData { fn encoded_len(&self) -> Result { let alg_len = self.algorithm().encoded_len()?; let key_len = match self { + #[cfg(feature = "alloc")] + Self::Dsa(key) => key.encoded_len()?, #[cfg(feature = "ecdsa")] Self::Ecdsa(key) => key.encoded_len()?, Self::Ed25519(key) => key.encoded_len()?, @@ -257,6 +259,8 @@ impl Encode for KeyData { fn encode(&self, encoder: &mut base64::Encoder<'_>) -> Result<()> { self.algorithm().encode(encoder)?; match self { + #[cfg(feature = "alloc")] + Self::Dsa(key) => key.encode(encoder), #[cfg(feature = "ecdsa")] Self::Ecdsa(key) => key.encode(encoder), Self::Ed25519(key) => key.encode(encoder), diff --git a/ssh-key/src/public/dsa.rs b/ssh-key/src/public/dsa.rs index 47f00de26..d72c64997 100644 --- a/ssh-key/src/public/dsa.rs +++ b/ssh-key/src/public/dsa.rs @@ -1,7 +1,7 @@ //! Digital Signature Algorithm (DSA) public keys. use crate::{ - base64::{self, Decode}, + base64::{self, Decode, Encode}, MPInt, Result, }; @@ -34,3 +34,19 @@ impl Decode for DsaPublicKey { Ok(Self { p, q, g, y }) } } + +impl Encode for DsaPublicKey { + fn encoded_len(&self) -> Result { + Ok(self.p.encoded_len()? + + self.q.encoded_len()? + + self.g.encoded_len()? + + self.y.encoded_len()?) + } + + fn encode(&self, encoder: &mut base64::Encoder<'_>) -> Result<()> { + self.p.encode(encoder)?; + self.q.encode(encoder)?; + self.g.encode(encoder)?; + self.y.encode(encoder) + } +} diff --git a/ssh-key/tests/public_key.rs b/ssh-key/tests/public_key.rs index 00015c6e6..fcebbdf2c 100644 --- a/ssh-key/tests/public_key.rs +++ b/ssh-key/tests/public_key.rs @@ -213,30 +213,37 @@ fn decode_rsa_4096_openssh() { assert_eq!("user@example.com", ossh_key.comment); } +#[cfg(feature = "alloc")] +#[test] +fn encode_dsa_openssh() { + let ossh_key = PublicKey::from_openssh(OSSH_DSA_EXAMPLE).unwrap(); + assert_eq!(OSSH_DSA_EXAMPLE.trim_end(), &ossh_key.to_string()); +} + #[cfg(all(feature = "alloc", feature = "ecdsa"))] #[test] fn encode_ecdsa_p256_openssh() { let ossh_key = PublicKey::from_openssh(OSSH_ECDSA_P256_EXAMPLE).unwrap(); - assert_eq!(OSSH_ECDSA_P256_EXAMPLE.trim_end(), &ossh_key.to_string()) + assert_eq!(OSSH_ECDSA_P256_EXAMPLE.trim_end(), &ossh_key.to_string()); } #[cfg(all(feature = "alloc", feature = "ecdsa"))] #[test] fn encode_ecdsa_p384_openssh() { let ossh_key = PublicKey::from_openssh(OSSH_ECDSA_P384_EXAMPLE).unwrap(); - assert_eq!(OSSH_ECDSA_P384_EXAMPLE.trim_end(), &ossh_key.to_string()) + assert_eq!(OSSH_ECDSA_P384_EXAMPLE.trim_end(), &ossh_key.to_string()); } #[cfg(all(feature = "alloc", feature = "ecdsa"))] #[test] fn encode_ecdsa_p521_openssh() { let ossh_key = PublicKey::from_openssh(OSSH_ECDSA_P521_EXAMPLE).unwrap(); - assert_eq!(OSSH_ECDSA_P521_EXAMPLE.trim_end(), &ossh_key.to_string()) + assert_eq!(OSSH_ECDSA_P521_EXAMPLE.trim_end(), &ossh_key.to_string()); } #[cfg(feature = "alloc")] #[test] fn encode_ed25519_openssh() { let ossh_key = PublicKey::from_openssh(OSSH_ED25519_EXAMPLE).unwrap(); - assert_eq!(OSSH_ED25519_EXAMPLE.trim_end(), &ossh_key.to_string()) + assert_eq!(OSSH_ED25519_EXAMPLE.trim_end(), &ossh_key.to_string()); }