diff --git a/src/key.rs b/src/key.rs index 5e6de22..59f8b7c 100644 --- a/src/key.rs +++ b/src/key.rs @@ -5,9 +5,11 @@ use num_bigint::Sign::Plus; use num_bigint::{BigInt, BigUint}; use num_integer::Integer; use num_traits::{FromPrimitive, One, ToPrimitive}; +use pkcs8::{DecodePrivateKey, EncodePrivateKey}; use rand_core::CryptoRngCore; #[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; +use serdect::serde::{de, ser, Deserialize, Serialize}; +use spki::{DecodePublicKey, EncodePublicKey}; use zeroize::{Zeroize, ZeroizeOnDrop}; use crate::algorithms::generate::generate_multi_prime_key_with_exp; @@ -23,7 +25,6 @@ use crate::CrtValue; /// Represents the public part of an RSA key. #[derive(Debug, Clone, Hash, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPublicKey { /// Modulus: product of prime numbers `p` and `q` n: BigUint, @@ -36,7 +37,6 @@ pub struct RsaPublicKey { /// Represents a whole RSA key, public and private parts. #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RsaPrivateKey { /// Public components of the private key. pubkey_components: RsaPublicKey, @@ -45,7 +45,6 @@ pub struct RsaPrivateKey { /// Prime factors of N, contains >= 2 elements. pub(crate) primes: Vec, /// precomputed values to speed up private operations - #[cfg_attr(feature = "serde", serde(skip))] pub(crate) precomputed: Option, } @@ -531,6 +530,50 @@ fn check_public_with_max_size(public_key: &impl PublicKeyParts, max_size: usize) Ok(()) } +#[cfg(feature = "serde")] +impl Serialize for RsaPublicKey { + fn serialize(&self, serializer: S) -> core::prelude::v1::Result + where + S: serdect::serde::Serializer, + { + let der = self.to_public_key_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der, serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for RsaPublicKey { + fn deserialize(deserializer: D) -> core::prelude::v1::Result + where + D: serdect::serde::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_public_key_der(&der_bytes).map_err(de::Error::custom) + } +} + +#[cfg(feature = "serde")] +impl Serialize for RsaPrivateKey { + fn serialize(&self, serializer: S) -> core::prelude::v1::Result + where + S: ser::Serializer, + { + let der = self.to_pkcs8_der().map_err(ser::Error::custom)?; + serdect::slice::serialize_hex_lower_or_bin(&der.as_bytes(), serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for RsaPrivateKey { + fn deserialize(deserializer: D) -> core::prelude::v1::Result + where + D: de::Deserializer<'de>, + { + let der_bytes = serdect::slice::deserialize_hex_or_bin_vec(deserializer)?; + Self::from_pkcs8_der(&der_bytes).map_err(de::Error::custom) + } +} + #[cfg(test)] mod tests { use super::*; @@ -538,7 +581,6 @@ mod tests { use hex_literal::hex; use num_traits::{FromPrimitive, ToPrimitive}; - use pkcs8::DecodePrivateKey; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; #[test] @@ -640,66 +682,23 @@ mod tests { #[cfg(feature = "serde")] fn test_serde() { use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; - use serde_test::{assert_tokens, Token}; + use serde_test::{assert_tokens, Configure, Token}; let mut rng = ChaCha8Rng::from_seed([42; 32]); let priv_key = RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"); let priv_tokens = [ - Token::Struct { - name: "RsaPrivateKey", - len: 3, - }, - Token::Str("pubkey_components"), - Token::Struct { - name: "RsaPublicKey", - len: 2, - }, - Token::Str("n"), - Token::Seq { len: Some(2) }, - Token::U32(3814409919), - Token::U32(3429654832), - Token::SeqEnd, - Token::Str("e"), - Token::Seq { len: Some(1) }, - Token::U32(65537), - Token::SeqEnd, - Token::StructEnd, - Token::Str("d"), - Token::Seq { len: Some(2) }, - Token::U32(1482162201), - Token::U32(1675500232), - Token::SeqEnd, - Token::Str("primes"), - Token::Seq { len: Some(2) }, - Token::Seq { len: Some(1) }, - Token::U32(4133289821), - Token::SeqEnd, - Token::Seq { len: Some(1) }, - Token::U32(3563808971), - Token::SeqEnd, - Token::SeqEnd, - Token::StructEnd, + Token::Str("3054020100300d06092a864886f70d01010105000440303e020100020900cc6c6130e35b46bf0203010001020863de1ac858580019020500f65cff5d020500d46b68cb02046d9a09f102047b4e3a4f020500f45065cc") ]; - assert_tokens(&priv_key, &priv_tokens); - - let priv_tokens = [ - Token::Struct { - name: "RsaPublicKey", - len: 2, - }, - Token::Str("n"), - Token::Seq { len: Some(2) }, - Token::U32(3814409919), - Token::U32(3429654832), - Token::SeqEnd, - Token::Str("e"), - Token::Seq { len: Some(1) }, - Token::U32(65537), - Token::SeqEnd, - Token::StructEnd, - ]; - assert_tokens(&RsaPublicKey::from(priv_key), &priv_tokens); + assert_tokens(&priv_key.clone().readable(), &priv_tokens); + + let priv_tokens = [Token::Str( + "3024300d06092a864886f70d01010105000313003010020900cc6c6130e35b46bf0203010001", + )]; + assert_tokens( + &RsaPublicKey::from(priv_key.clone()).readable(), + &priv_tokens, + ); } #[test] diff --git a/src/pkcs1v15/signing_key.rs b/src/pkcs1v15/signing_key.rs index 232c99f..35043ec 100644 --- a/src/pkcs1v15/signing_key.rs +++ b/src/pkcs1v15/signing_key.rs @@ -1,18 +1,19 @@ use super::{oid, pkcs1v15_generate_prefix, sign, Signature, VerifyingKey}; use crate::{dummy_rng::DummyRng, Result, RsaPrivateKey}; use alloc::vec::Vec; +use spki::der::Decode; use core::marker::PhantomData; use digest::Digest; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; +use pkcs1::EncodeRsaPrivateKey; use pkcs8::{ spki::{ der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier, - }, - AssociatedOid, EncodePrivateKey, SecretDocument, + }, AssociatedOid, EncodePrivateKey, PrivateKeyInfo, SecretDocument }; use rand_core::CryptoRngCore; +#[cfg(feature = "serde")] +use serdect::serde::{de, ser, Deserialize, Serialize}; use signature::{ hazmat::PrehashSigner, DigestSigner, Keypair, RandomizedDigestSigner, RandomizedSigner, Signer, }; @@ -22,7 +23,6 @@ use zeroize::ZeroizeOnDrop; /// /// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2 #[derive(Debug, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SigningKey where D: Digest, @@ -256,3 +256,32 @@ 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)?; + Self::try_from(pki).map_err(de::Error::custom) + } +} diff --git a/src/pkcs1v15/verifying_key.rs b/src/pkcs1v15/verifying_key.rs index 9464aef..023c6b8 100644 --- a/src/pkcs1v15/verifying_key.rs +++ b/src/pkcs1v15/verifying_key.rs @@ -3,22 +3,22 @@ use crate::RsaPublicKey; use alloc::vec::Vec; use core::marker::PhantomData; use digest::Digest; -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; use pkcs8::{ spki::{ der::AnyRef, AlgorithmIdentifierRef, AssociatedAlgorithmIdentifier, SignatureAlgorithmIdentifier, - }, - AssociatedOid, Document, EncodePublicKey, + }, AssociatedOid }; + +#[cfg(feature = "serde")] +use serdect::serde::{ser, de, Deserialize, Serialize}; use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; +use spki::{der::Decode, Document, EncodePublicKey, SubjectPublicKeyInfo}; /// Verifying key for `RSASSA-PKCS1-v1_5` signatures as described in [RFC8017 § 8.2]. /// /// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2 #[derive(Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct VerifyingKey where D: Digest, @@ -204,3 +204,32 @@ where RsaPublicKey::try_from(spki).map(Self::new) } } + +#[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)?; + Self::try_from(spki).map_err(de::Error::custom) + } +}