1use crate::Result;
4
5#[cfg(feature = "alloc")]
6use der::{Document, SecretDocument};
7
8#[cfg(feature = "pem")]
9use {
10    crate::LineEnding,
11    alloc::string::String,
12    der::{pem::PemLabel, zeroize::Zeroizing},
13};
14
15#[cfg(feature = "std")]
16use std::path::Path;
17
18#[cfg(all(feature = "alloc", feature = "pem"))]
19use crate::{RsaPrivateKey, RsaPublicKey};
20
21pub trait DecodeRsaPrivateKey: Sized {
23    fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
26
27    #[cfg(feature = "pem")]
35    fn from_pkcs1_pem(s: &str) -> Result<Self> {
36        let (label, doc) = SecretDocument::from_pem(s)?;
37        RsaPrivateKey::validate_pem_label(label)?;
38        Self::from_pkcs1_der(doc.as_bytes())
39    }
40
41    #[cfg(feature = "std")]
44    fn read_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
45        Self::from_pkcs1_der(SecretDocument::read_der_file(path)?.as_bytes())
46    }
47
48    #[cfg(all(feature = "pem", feature = "std"))]
50    fn read_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
51        let (label, doc) = SecretDocument::read_pem_file(path)?;
52        RsaPrivateKey::validate_pem_label(&label)?;
53        Self::from_pkcs1_der(doc.as_bytes())
54    }
55}
56
57pub trait DecodeRsaPublicKey: Sized {
59    fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
62
63    #[cfg(feature = "pem")]
71    fn from_pkcs1_pem(s: &str) -> Result<Self> {
72        let (label, doc) = Document::from_pem(s)?;
73        RsaPublicKey::validate_pem_label(label)?;
74        Self::from_pkcs1_der(doc.as_bytes())
75    }
76
77    #[cfg(feature = "std")]
80    fn read_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
81        let doc = Document::read_der_file(path)?;
82        Self::from_pkcs1_der(doc.as_bytes())
83    }
84
85    #[cfg(all(feature = "pem", feature = "std"))]
87    fn read_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
88        let (label, doc) = Document::read_pem_file(path)?;
89        RsaPublicKey::validate_pem_label(&label)?;
90        Self::from_pkcs1_der(doc.as_bytes())
91    }
92}
93
94#[cfg(feature = "alloc")]
96pub trait EncodeRsaPrivateKey {
97    fn to_pkcs1_der(&self) -> Result<SecretDocument>;
99
100    #[cfg(feature = "pem")]
102    fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
103        let doc = self.to_pkcs1_der()?;
104        Ok(doc.to_pem(RsaPrivateKey::PEM_LABEL, line_ending)?)
105    }
106
107    #[cfg(feature = "std")]
109    fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
110        Ok(self.to_pkcs1_der()?.write_der_file(path)?)
111    }
112
113    #[cfg(all(feature = "pem", feature = "std"))]
115    fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
116        let doc = self.to_pkcs1_der()?;
117        Ok(doc.write_pem_file(path, RsaPrivateKey::PEM_LABEL, line_ending)?)
118    }
119}
120
121#[cfg(feature = "alloc")]
123pub trait EncodeRsaPublicKey {
124    fn to_pkcs1_der(&self) -> Result<Document>;
126
127    #[cfg(feature = "pem")]
129    fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<String> {
130        let doc = self.to_pkcs1_der()?;
131        Ok(doc.to_pem(RsaPublicKey::PEM_LABEL, line_ending)?)
132    }
133
134    #[cfg(feature = "std")]
136    fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
137        Ok(self.to_pkcs1_der()?.write_der_file(path)?)
138    }
139
140    #[cfg(all(feature = "pem", feature = "std"))]
142    fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
143        let doc = self.to_pkcs1_der()?;
144        Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?)
145    }
146}