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}