diff --git a/ssh-key/src/sshsig.rs b/ssh-key/src/sshsig.rs index 2bbe5ae..1b7c3c6 100644 --- a/ssh-key/src/sshsig.rs +++ b/ssh-key/src/sshsig.rs @@ -14,6 +14,9 @@ use crate::{PrivateKey, PublicKey}; type Version = u32; +#[cfg(feature = "serde")] +use serde::{de, ser, Deserialize, Serialize}; + /// `sshsig` provides a general-purpose signature format based on SSH keys and /// wire formats. /// @@ -202,6 +205,7 @@ impl SshSig { } /// Get the hash algorithm used to produce this signature. + /// /// Data to be signed is first hashed with the specified `hash_alg`. /// This is done to limit the amount of data presented to the signature @@ -346,3 +350,37 @@ impl Encode for SignedData<'_> { Ok(()) } } + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for SshSig { + fn deserialize(deserializer: D) -> core::result::Result + where + D: de::Deserializer<'de>, + { + if deserializer.is_human_readable() { + let string = String::deserialize(deserializer)?; + string.parse::().map_err(de::Error::custom) + } else { + let bytes = Vec::::deserialize(deserializer)?; + Self::decode(&mut bytes.as_slice()).map_err(de::Error::custom) + } + } +} + +#[cfg(feature = "serde")] +impl Serialize for SshSig { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: ser::Serializer, + { + if serializer.is_human_readable() { + self.to_pem(LineEnding::LF) + .map_err(ser::Error::custom)? + .serialize(serializer) + } else { + let mut bytes = Vec::new(); + self.encode(&mut bytes).map_err(ser::Error::custom)?; + bytes.serialize(serializer) + } + } +}