From 9d3d2a6599d2f194efd3b47defce73fb5ca75f86 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:22:07 +0200 Subject: [PATCH 1/7] pkcs1: split RsaPublicKeyGeneric into RsaPublicKey and RsaPublicKeyOwned --- pkcs1/src/lib.rs | 1 + pkcs1/src/public_key.rs | 51 ++++++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/pkcs1/src/lib.rs b/pkcs1/src/lib.rs index c5f302813..b277a701b 100644 --- a/pkcs1/src/lib.rs +++ b/pkcs1/src/lib.rs @@ -44,6 +44,7 @@ pub use crate::{ #[cfg(feature = "alloc")] pub use crate::{ private_key::{OtherPrimeInfos, other_prime_info::OtherPrimeInfo}, + public_key::RsaPublicKeyOwned, traits::{EncodeRsaPrivateKey, EncodeRsaPublicKey}, }; diff --git a/pkcs1/src/public_key.rs b/pkcs1/src/public_key.rs index bf8e59c49..8e66b18e8 100644 --- a/pkcs1/src/public_key.rs +++ b/pkcs1/src/public_key.rs @@ -2,16 +2,23 @@ use crate::{Error, Result}; use der::{ - Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Writer, + Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Writer, asn1::UintRef, }; #[cfg(feature = "alloc")] -use der::Document; +use der::{Document, asn1::Uint}; #[cfg(feature = "pem")] use der::pem::PemLabel; +/// [`RsaPublicKeyGeneric`] with [`UintRef`] INTEGERs. +pub type RsaPublicKey<'a> = RsaPublicKeyGeneric>; + +/// [`RsaPublicKeyGeneric`] with allocating [`Uint`] INTEGERs. +#[cfg(feature = "alloc")] +pub type RsaPublicKeyOwned = RsaPublicKeyGeneric; + /// PKCS#1 RSA Public Keys as defined in [RFC 8017 Appendix 1.1]. /// /// ASN.1 structure containing a serialized RSA public key: @@ -25,15 +32,18 @@ use der::pem::PemLabel; /// /// [RFC 8017 Appendix 1.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.1 #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct RsaPublicKey<'a> { +pub struct RsaPublicKeyGeneric { /// `n`: RSA modulus - pub modulus: UintRef<'a>, + pub modulus: UintType, /// `e`: RSA public exponent - pub public_exponent: UintRef<'a>, + pub public_exponent: UintType, } -impl<'a> DecodeValue<'a> for RsaPublicKey<'a> { +impl<'a, UintType> DecodeValue<'a> for RsaPublicKeyGeneric +where + UintType: DecodeValue<'a, Error = der::Error> + FixedTag + 'a, +{ type Error = der::Error; fn decode_value>(reader: &mut R, _header: Header) -> der::Result { Ok(Self { @@ -43,7 +53,10 @@ impl<'a> DecodeValue<'a> for RsaPublicKey<'a> { } } -impl EncodeValue for RsaPublicKey<'_> { +impl EncodeValue for RsaPublicKeyGeneric +where + UintType: EncodeValue + FixedTag, +{ fn value_len(&self) -> der::Result { self.modulus.encoded_len()? + self.public_exponent.encoded_len()? } @@ -55,9 +68,13 @@ impl EncodeValue for RsaPublicKey<'_> { } } -impl<'a> Sequence<'a> for RsaPublicKey<'a> {} +impl<'a, UintType> Sequence<'a> for RsaPublicKeyGeneric {} -impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> { +impl<'a, UintType> TryFrom<&'a [u8]> for RsaPublicKeyGeneric +where + RsaPublicKeyGeneric: Decode<'a>, + Error: From< as Decode<'a>>::Error>, +{ type Error = Error; fn try_from(bytes: &'a [u8]) -> Result { @@ -66,24 +83,30 @@ impl<'a> TryFrom<&'a [u8]> for RsaPublicKey<'a> { } #[cfg(feature = "alloc")] -impl TryFrom> for Document { +impl TryFrom> for Document +where + RsaPublicKeyGeneric: EncodeValue, +{ type Error = Error; - fn try_from(spki: RsaPublicKey<'_>) -> Result { + fn try_from(spki: RsaPublicKeyGeneric) -> Result { Self::try_from(&spki) } } #[cfg(feature = "alloc")] -impl TryFrom<&RsaPublicKey<'_>> for Document { +impl TryFrom<&RsaPublicKeyGeneric> for Document +where + RsaPublicKeyGeneric: EncodeValue, +{ type Error = Error; - fn try_from(spki: &RsaPublicKey<'_>) -> Result { + fn try_from(spki: &RsaPublicKeyGeneric) -> Result { Ok(Self::encode_msg(spki)?) } } #[cfg(feature = "pem")] -impl PemLabel for RsaPublicKey<'_> { +impl PemLabel for RsaPublicKeyGeneric { const PEM_LABEL: &'static str = "RSA PUBLIC KEY"; } From ce0d9c4aa19b14306c035d79bed7732310d6dc67 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:25:53 +0200 Subject: [PATCH 2/7] pkcs1: refactor: rename RsaPublicKey to RsaPublicKeyRef --- pkcs1/src/lib.rs | 2 +- pkcs1/src/private_key.rs | 14 +++++++------- pkcs1/src/public_key.rs | 2 +- pkcs1/src/traits.rs | 10 +++++----- pkcs1/tests/public_key.rs | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkcs1/src/lib.rs b/pkcs1/src/lib.rs index b277a701b..19c64cc5f 100644 --- a/pkcs1/src/lib.rs +++ b/pkcs1/src/lib.rs @@ -36,7 +36,7 @@ pub use crate::{ error::{Error, Result}, params::{RsaOaepParams, RsaPssParams, TrailerField}, private_key::RsaPrivateKey, - public_key::RsaPublicKey, + public_key::RsaPublicKeyRef, traits::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, version::Version, }; diff --git a/pkcs1/src/private_key.rs b/pkcs1/src/private_key.rs index 0c1886efd..c89d56b5b 100644 --- a/pkcs1/src/private_key.rs +++ b/pkcs1/src/private_key.rs @@ -3,7 +3,7 @@ #[cfg(feature = "alloc")] pub(crate) mod other_prime_info; -use crate::{Error, Result, RsaPublicKey, Version}; +use crate::{Error, Result, RsaPublicKeyRef, Version}; use core::fmt; use der::{ Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, Tag, Writer, @@ -72,8 +72,8 @@ pub struct RsaPrivateKey<'a> { impl<'a> RsaPrivateKey<'a> { /// Get the public key that corresponds to this [`RsaPrivateKey`]. - pub fn public_key(&self) -> RsaPublicKey<'a> { - RsaPublicKey { + pub fn public_key(&self) -> RsaPublicKeyRef<'a> { + RsaPublicKeyRef { modulus: self.modulus, public_exponent: self.public_exponent, } @@ -150,14 +150,14 @@ impl EncodeValue for RsaPrivateKey<'_> { impl<'a> Sequence<'a> for RsaPrivateKey<'a> {} -impl<'a> From> for RsaPublicKey<'a> { - fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKey<'a> { +impl<'a> From> for RsaPublicKeyRef<'a> { + fn from(private_key: RsaPrivateKey<'a>) -> RsaPublicKeyRef<'a> { private_key.public_key() } } -impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKey<'a> { - fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKey<'a> { +impl<'a> From<&RsaPrivateKey<'a>> for RsaPublicKeyRef<'a> { + fn from(private_key: &RsaPrivateKey<'a>) -> RsaPublicKeyRef<'a> { private_key.public_key() } } diff --git a/pkcs1/src/public_key.rs b/pkcs1/src/public_key.rs index 8e66b18e8..746502451 100644 --- a/pkcs1/src/public_key.rs +++ b/pkcs1/src/public_key.rs @@ -13,7 +13,7 @@ use der::{Document, asn1::Uint}; use der::pem::PemLabel; /// [`RsaPublicKeyGeneric`] with [`UintRef`] INTEGERs. -pub type RsaPublicKey<'a> = RsaPublicKeyGeneric>; +pub type RsaPublicKeyRef<'a> = RsaPublicKeyGeneric>; /// [`RsaPublicKeyGeneric`] with allocating [`Uint`] INTEGERs. #[cfg(feature = "alloc")] diff --git a/pkcs1/src/traits.rs b/pkcs1/src/traits.rs index 9424775f8..c8edd16a9 100644 --- a/pkcs1/src/traits.rs +++ b/pkcs1/src/traits.rs @@ -16,7 +16,7 @@ use { use std::path::Path; #[cfg(all(feature = "alloc", feature = "pem"))] -use crate::{RsaPrivateKey, RsaPublicKey}; +use crate::{RsaPrivateKey, RsaPublicKeyRef}; /// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document. pub trait DecodeRsaPrivateKey: Sized { @@ -70,7 +70,7 @@ pub trait DecodeRsaPublicKey: Sized { #[cfg(feature = "pem")] fn from_pkcs1_pem(s: &str) -> Result { let (label, doc) = Document::from_pem(s)?; - RsaPublicKey::validate_pem_label(label)?; + RsaPublicKeyRef::validate_pem_label(label)?; Self::from_pkcs1_der(doc.as_bytes()) } @@ -86,7 +86,7 @@ pub trait DecodeRsaPublicKey: Sized { #[cfg(all(feature = "pem", feature = "std"))] fn read_pkcs1_pem_file(path: impl AsRef) -> Result { let (label, doc) = Document::read_pem_file(path)?; - RsaPublicKey::validate_pem_label(&label)?; + RsaPublicKeyRef::validate_pem_label(&label)?; Self::from_pkcs1_der(doc.as_bytes()) } } @@ -128,7 +128,7 @@ pub trait EncodeRsaPublicKey { #[cfg(feature = "pem")] fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result { let doc = self.to_pkcs1_der()?; - Ok(doc.to_pem(RsaPublicKey::PEM_LABEL, line_ending)?) + Ok(doc.to_pem(RsaPublicKeyRef::PEM_LABEL, line_ending)?) } /// Write ASN.1 DER-encoded public key to the given path. @@ -141,6 +141,6 @@ pub trait EncodeRsaPublicKey { #[cfg(all(feature = "pem", feature = "std"))] fn write_pkcs1_pem_file(&self, path: impl AsRef, line_ending: LineEnding) -> Result<()> { let doc = self.to_pkcs1_der()?; - Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?) + Ok(doc.write_pem_file(path, RsaPublicKeyRef::PEM_LABEL, line_ending)?) } } diff --git a/pkcs1/tests/public_key.rs b/pkcs1/tests/public_key.rs index f3e480e82..ea2ba88e2 100644 --- a/pkcs1/tests/public_key.rs +++ b/pkcs1/tests/public_key.rs @@ -1,7 +1,7 @@ //! PKCS#1 public key tests use hex_literal::hex; -use pkcs1::RsaPublicKey; +use pkcs1::RsaPublicKeyRef; /// RSA-2048 PKCS#1 public key encoded as ASN.1 DER. /// @@ -22,7 +22,7 @@ const RSA_4096_DER_EXAMPLE: &[u8] = include_bytes!("examples/rsa4096-pub.der"); #[test] fn decode_rsa2048_der() { - let key = RsaPublicKey::try_from(RSA_2048_DER_EXAMPLE).unwrap(); + let key = RsaPublicKeyRef::try_from(RSA_2048_DER_EXAMPLE).unwrap(); // Extracted using: // $ openssl asn1parse -in tests/examples/rsa2048-pub.pem @@ -37,7 +37,7 @@ fn decode_rsa2048_der() { #[test] fn decode_rsa4096_der() { - let key = RsaPublicKey::try_from(RSA_4096_DER_EXAMPLE).unwrap(); + let key = RsaPublicKeyRef::try_from(RSA_4096_DER_EXAMPLE).unwrap(); // Extracted using: // $ openssl asn1parse -in tests/examples/rsa4096-pub.pem From 0d16085b0412273c692b844ac959a2576c57551e Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:26:59 +0200 Subject: [PATCH 3/7] pkcs1: refactor: rename RsaPublicKeyGeneric to RsaPublicKey --- pkcs1/src/public_key.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pkcs1/src/public_key.rs b/pkcs1/src/public_key.rs index 746502451..c29362ab9 100644 --- a/pkcs1/src/public_key.rs +++ b/pkcs1/src/public_key.rs @@ -13,11 +13,11 @@ use der::{Document, asn1::Uint}; use der::pem::PemLabel; /// [`RsaPublicKeyGeneric`] with [`UintRef`] INTEGERs. -pub type RsaPublicKeyRef<'a> = RsaPublicKeyGeneric>; +pub type RsaPublicKeyRef<'a> = RsaPublicKey>; /// [`RsaPublicKeyGeneric`] with allocating [`Uint`] INTEGERs. #[cfg(feature = "alloc")] -pub type RsaPublicKeyOwned = RsaPublicKeyGeneric; +pub type RsaPublicKeyOwned = RsaPublicKey; /// PKCS#1 RSA Public Keys as defined in [RFC 8017 Appendix 1.1]. /// @@ -32,7 +32,7 @@ pub type RsaPublicKeyOwned = RsaPublicKeyGeneric; /// /// [RFC 8017 Appendix 1.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.1.1 #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct RsaPublicKeyGeneric { +pub struct RsaPublicKey { /// `n`: RSA modulus pub modulus: UintType, @@ -40,7 +40,7 @@ pub struct RsaPublicKeyGeneric { pub public_exponent: UintType, } -impl<'a, UintType> DecodeValue<'a> for RsaPublicKeyGeneric +impl<'a, UintType> DecodeValue<'a> for RsaPublicKey where UintType: DecodeValue<'a, Error = der::Error> + FixedTag + 'a, { @@ -53,7 +53,7 @@ where } } -impl EncodeValue for RsaPublicKeyGeneric +impl EncodeValue for RsaPublicKey where UintType: EncodeValue + FixedTag, { @@ -68,12 +68,12 @@ where } } -impl<'a, UintType> Sequence<'a> for RsaPublicKeyGeneric {} +impl<'a, UintType> Sequence<'a> for RsaPublicKey {} -impl<'a, UintType> TryFrom<&'a [u8]> for RsaPublicKeyGeneric +impl<'a, UintType> TryFrom<&'a [u8]> for RsaPublicKey where - RsaPublicKeyGeneric: Decode<'a>, - Error: From< as Decode<'a>>::Error>, + RsaPublicKey: Decode<'a>, + Error: From< as Decode<'a>>::Error>, { type Error = Error; @@ -83,30 +83,30 @@ where } #[cfg(feature = "alloc")] -impl TryFrom> for Document +impl TryFrom> for Document where - RsaPublicKeyGeneric: EncodeValue, + RsaPublicKey: EncodeValue, { type Error = Error; - fn try_from(spki: RsaPublicKeyGeneric) -> Result { + fn try_from(spki: RsaPublicKey) -> Result { Self::try_from(&spki) } } #[cfg(feature = "alloc")] -impl TryFrom<&RsaPublicKeyGeneric> for Document +impl TryFrom<&RsaPublicKey> for Document where - RsaPublicKeyGeneric: EncodeValue, + RsaPublicKey: EncodeValue, { type Error = Error; - fn try_from(spki: &RsaPublicKeyGeneric) -> Result { + fn try_from(spki: &RsaPublicKey) -> Result { Ok(Self::encode_msg(spki)?) } } #[cfg(feature = "pem")] -impl PemLabel for RsaPublicKeyGeneric { +impl PemLabel for RsaPublicKey { const PEM_LABEL: &'static str = "RSA PUBLIC KEY"; } From 0072dd7246ce370e7b89047b1389f44b67ab63b7 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:31:19 +0200 Subject: [PATCH 4/7] pkcs1: typo RsaPublicKey --- pkcs1/src/public_key.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkcs1/src/public_key.rs b/pkcs1/src/public_key.rs index c29362ab9..b7f3b6ee3 100644 --- a/pkcs1/src/public_key.rs +++ b/pkcs1/src/public_key.rs @@ -12,10 +12,10 @@ use der::{Document, asn1::Uint}; #[cfg(feature = "pem")] use der::pem::PemLabel; -/// [`RsaPublicKeyGeneric`] with [`UintRef`] INTEGERs. +/// [`RsaPublicKey`] with [`UintRef`] INTEGERs. pub type RsaPublicKeyRef<'a> = RsaPublicKey>; -/// [`RsaPublicKeyGeneric`] with allocating [`Uint`] INTEGERs. +/// [`RsaPublicKey`] with allocating [`Uint`] INTEGERs. #[cfg(feature = "alloc")] pub type RsaPublicKeyOwned = RsaPublicKey; From 27041374035d246ec86a7fd4b29b9ef0a5437427 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 22:22:40 +0200 Subject: [PATCH 5/7] patch rsa crate with RustCrypto/RSA commit rev --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 76339a17c..add67e2b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,10 @@ x509-tsp = { path = "./x509-tsp" } x509-cert = { path = "./x509-cert" } x509-ocsp = { path = "./x509-ocsp" } +# RSA: refactor: use RsaPublicKeyRef instead of RsaPublicKey from RustCrypto/formats - #706 +rsa = { git = "https://github.com/RustCrypto/RSA.git", rev = "dc89967d5acf570f35375a9eb9151380fabd2f28" } + + [workspace.lints.clippy] borrow_as_ptr = "warn" cast_lossless = "warn" From 231113e6df86e89156e95a4cff1d29acb093c519 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 22:25:32 +0200 Subject: [PATCH 6/7] pkcs1: pub use RsaPublicKey --- pkcs1/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs1/src/lib.rs b/pkcs1/src/lib.rs index 19c64cc5f..847405669 100644 --- a/pkcs1/src/lib.rs +++ b/pkcs1/src/lib.rs @@ -36,7 +36,7 @@ pub use crate::{ error::{Error, Result}, params::{RsaOaepParams, RsaPssParams, TrailerField}, private_key::RsaPrivateKey, - public_key::RsaPublicKeyRef, + public_key::{RsaPublicKey, RsaPublicKeyRef}, traits::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, version::Version, }; From a278c64680a07c462364f991473da0ad53d09af7 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Tue, 25 Aug 2026 22:30:24 +0200 Subject: [PATCH 7/7] use RsaPublicKey #[cfg(doc)] --- pkcs1/src/traits.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkcs1/src/traits.rs b/pkcs1/src/traits.rs index c8edd16a9..d337fafae 100644 --- a/pkcs1/src/traits.rs +++ b/pkcs1/src/traits.rs @@ -18,6 +18,9 @@ use std::path::Path; #[cfg(all(feature = "alloc", feature = "pem"))] use crate::{RsaPrivateKey, RsaPublicKeyRef}; +#[cfg(doc)] +use crate::RsaPublicKey; + /// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document. pub trait DecodeRsaPrivateKey: Sized { /// Deserialize PKCS#1 private key from ASN.1 DER-encoded data