diff --git a/src/oaep/decrypting_key.rs b/src/oaep/decrypting_key.rs index eacff38e..340d0d16 100644 --- a/src/oaep/decrypting_key.rs +++ b/src/oaep/decrypting_key.rs @@ -8,6 +8,8 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; @@ -17,6 +19,7 @@ use zeroize::ZeroizeOnDrop; /// /// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1 #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct DecryptingKey where D: Digest, diff --git a/src/oaep/encrypting_key.rs b/src/oaep/encrypting_key.rs index 0951e652..39053098 100644 --- a/src/oaep/encrypting_key.rs +++ b/src/oaep/encrypting_key.rs @@ -4,6 +4,8 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; use core::marker::PhantomData; use digest::{Digest, FixedOutputReset}; use rand_core::CryptoRngCore; @@ -12,6 +14,7 @@ use rand_core::CryptoRngCore; /// /// [RFC8017 § 7.1]: https://datatracker.ietf.org/doc/html/rfc8017#section-7.1 #[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct EncryptingKey where D: Digest, diff --git a/src/pss/blinded_signing_key.rs b/src/pss/blinded_signing_key.rs index adc0ff5f..d641c2b6 100644 --- a/src/pss/blinded_signing_key.rs +++ b/src/pss/blinded_signing_key.rs @@ -15,7 +15,12 @@ use signature::{ hazmat::RandomizedPrehashSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, }; use zeroize::ZeroizeOnDrop; - +#[cfg(feature = "serde")] +use { + pkcs8::PrivateKeyInfo, + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::der::Decode, +}; /// Signing key for producing "blinded" RSASSA-PSS signatures as described in /// [draft-irtf-cfrg-rsa-blind-signatures](https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/). #[derive(Debug, Clone)] @@ -198,3 +203,34 @@ where } impl ZeroizeOnDrop for BlindedSigningKey where D: Digest {} + +#[cfg(feature = "serde")] +impl Serialize for BlindedSigningKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + let der = self.inner.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for BlindedSigningKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> core::result::Result + where + De: serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + let pki = PrivateKeyInfo::from_der(&der_bytes).map_err(de::Error::custom)?; + RsaPrivateKey::try_from(pki) + .map_err(de::Error::custom) + .map(Self::new) + } +} diff --git a/src/pss/signature.rs b/src/pss/signature.rs index 031e2201..e6a185b8 100644 --- a/src/pss/signature.rs +++ b/src/pss/signature.rs @@ -3,6 +3,8 @@ use crate::algorithms::pad::uint_to_be_pad; use ::signature::SignatureEncoding; use alloc::{boxed::Box, string::ToString}; +#[cfg(feature = "serde")] +use serdect::serde::{Deserialize, Serialize}; use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use num_bigint::BigUint; use spki::{ @@ -73,3 +75,29 @@ impl Display for Signature { write!(f, "{:X}", self) } } + +#[cfg(feature = "serde")] +impl Serialize for Signature { + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + serdect::slice::serialize_hex_lower_or_bin(&self.inner.to_bytes_be(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Signature { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serdect::serde::Deserializer<'de>, + { + let bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + let inner = BigUint::from_bytes_be(&bytes); + + Ok(Self { + inner, + len: bytes.len(), + }) + } +} \ No newline at end of file diff --git a/src/pss/signing_key.rs b/src/pss/signing_key.rs index 39b41472..105a0c63 100644 --- a/src/pss/signing_key.rs +++ b/src/pss/signing_key.rs @@ -15,6 +15,12 @@ use signature::{ hazmat::RandomizedPrehashSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, }; use zeroize::ZeroizeOnDrop; +#[cfg(feature = "serde")] +use { + pkcs8::PrivateKeyInfo, + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::der::Decode, +}; #[cfg(feature = "getrandom")] use { @@ -220,3 +226,34 @@ where } impl ZeroizeOnDrop for SigningKey where D: Digest {} + +#[cfg(feature = "serde")] +impl Serialize for SigningKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serdect::serde::Serializer, + { + let der = self.inner.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for SigningKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> core::result::Result + where + De: serdect::serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + let pki = PrivateKeyInfo::from_der(&der_bytes).map_err(de::Error::custom)?; + RsaPrivateKey::try_from(pki) + .map_err(de::Error::custom) + .map(Self::new) + } +} diff --git a/src/pss/verifying_key.rs b/src/pss/verifying_key.rs index ed065492..6aaee591 100644 --- a/src/pss/verifying_key.rs +++ b/src/pss/verifying_key.rs @@ -7,6 +7,12 @@ use pkcs8::{ Document, EncodePublicKey, }; use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; +#[cfg(feature = "serde")] +use { + pkcs8::{AssociatedOid, SubjectPublicKeyInfo}, + serdect::serde::{de, ser, Deserialize, Serialize}, + spki::der::Decode, +}; /// Verifying key for checking the validity of RSASSA-PSS signatures as /// described in [RFC8017 § 8.1]. @@ -156,3 +162,34 @@ where key.inner } } + +#[cfg(feature = "serde")] +impl Serialize for VerifyingKey +where + D: Digest, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let der = self.inner.to_public_key_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der, serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, D> Deserialize<'de> for VerifyingKey +where + D: Digest + AssociatedOid, +{ + fn deserialize(deserializer: De) -> Result + where + De: serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + let spki = SubjectPublicKeyInfo::from_der(&der_bytes).map_err(de::Error::custom)?; + RsaPublicKey::try_from(spki) + .map_err(de::Error::custom) + .map(Self::new) + } +}