1use crate::Result;
4
5#[cfg(feature = "alloc")]
6use {
7 crate::{RsaPrivateKey, RsaPublicKey},
8 der::SecretDocument,
9};
10
11#[cfg(feature = "pem")]
12use {
13 crate::LineEnding,
14 alloc::string::String,
15 der::{pem::PemLabel, zeroize::Zeroizing},
16};
17
18#[cfg(feature = "pkcs8")]
19use crate::{ALGORITHM_ID, ALGORITHM_OID};
20
21#[cfg(feature = "std")]
22use std::path::Path;
23
24#[cfg(all(feature = "alloc", feature = "pkcs8"))]
25use der::{Decode, Document};
26
27pub trait DecodeRsaPrivateKey: Sized {
29 fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
32
33 #[cfg(feature = "pem")]
41 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
42 fn from_pkcs1_pem(s: &str) -> Result<Self> {
43 let (label, doc) = SecretDocument::from_pem(s)?;
44 RsaPrivateKey::validate_pem_label(label)?;
45 Self::from_pkcs1_der(doc.as_bytes())
46 }
47
48 #[cfg(feature = "std")]
51 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
52 fn read_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
53 Self::from_pkcs1_der(SecretDocument::read_der_file(path)?.as_bytes())
54 }
55
56 #[cfg(all(feature = "pem", feature = "std"))]
58 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
59 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
60 fn read_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
61 let (label, doc) = SecretDocument::read_pem_file(path)?;
62 RsaPrivateKey::validate_pem_label(&label)?;
63 Self::from_pkcs1_der(doc.as_bytes())
64 }
65}
66
67pub trait DecodeRsaPublicKey: Sized {
69 fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
72
73 #[cfg(feature = "pem")]
81 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
82 fn from_pkcs1_pem(s: &str) -> Result<Self> {
83 let (label, doc) = Document::from_pem(s)?;
84 RsaPublicKey::validate_pem_label(label)?;
85 Self::from_pkcs1_der(doc.as_bytes())
86 }
87
88 #[cfg(feature = "std")]
91 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
92 fn read_pkcs1_der_file(path: impl AsRef<Path>) -> Result<Self> {
93 let doc = Document::read_der_file(path)?;
94 Self::from_pkcs1_der(doc.as_bytes())
95 }
96
97 #[cfg(all(feature = "pem", feature = "std"))]
99 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
100 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
101 fn read_pkcs1_pem_file(path: impl AsRef<Path>) -> Result<Self> {
102 let (label, doc) = Document::read_pem_file(path)?;
103 RsaPublicKey::validate_pem_label(&label)?;
104 Self::from_pkcs1_der(doc.as_bytes())
105 }
106}
107
108#[cfg(feature = "alloc")]
110#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
111pub trait EncodeRsaPrivateKey {
112 fn to_pkcs1_der(&self) -> Result<SecretDocument>;
114
115 #[cfg(feature = "pem")]
117 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
118 fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<Zeroizing<String>> {
119 let doc = self.to_pkcs1_der()?;
120 Ok(doc.to_pem(RsaPrivateKey::PEM_LABEL, line_ending)?)
121 }
122
123 #[cfg(feature = "std")]
125 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
126 fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
127 Ok(self.to_pkcs1_der()?.write_der_file(path)?)
128 }
129
130 #[cfg(all(feature = "pem", feature = "std"))]
132 #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
133 fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
134 let doc = self.to_pkcs1_der()?;
135 Ok(doc.write_pem_file(path, RsaPrivateKey::PEM_LABEL, line_ending)?)
136 }
137}
138
139#[cfg(feature = "alloc")]
141#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
142pub trait EncodeRsaPublicKey {
143 fn to_pkcs1_der(&self) -> Result<Document>;
145
146 #[cfg(feature = "pem")]
148 #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
149 fn to_pkcs1_pem(&self, line_ending: LineEnding) -> Result<String> {
150 let doc = self.to_pkcs1_der()?;
151 Ok(doc.to_pem(RsaPublicKey::PEM_LABEL, line_ending)?)
152 }
153
154 #[cfg(feature = "std")]
156 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
157 fn write_pkcs1_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
158 Ok(self.to_pkcs1_der()?.write_der_file(path)?)
159 }
160
161 #[cfg(all(feature = "pem", feature = "std"))]
163 #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
164 fn write_pkcs1_pem_file(&self, path: impl AsRef<Path>, line_ending: LineEnding) -> Result<()> {
165 let doc = self.to_pkcs1_der()?;
166 Ok(doc.write_pem_file(path, RsaPublicKey::PEM_LABEL, line_ending)?)
167 }
168}
169
170#[cfg(feature = "pkcs8")]
171#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
172impl<T: pkcs8::DecodePrivateKey> DecodeRsaPrivateKey for T {
173 fn from_pkcs1_der(private_key: &[u8]) -> Result<Self> {
174 Ok(Self::try_from(pkcs8::PrivateKeyInfo {
175 algorithm: ALGORITHM_ID,
176 private_key,
177 public_key: None,
178 })?)
179 }
180}
181
182#[cfg(feature = "pkcs8")]
183#[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))]
184impl<T: pkcs8::DecodePublicKey> DecodeRsaPublicKey for T {
185 fn from_pkcs1_der(public_key: &[u8]) -> Result<Self> {
186 Ok(Self::try_from(pkcs8::SubjectPublicKeyInfo {
187 algorithm: ALGORITHM_ID,
188 subject_public_key: public_key,
189 })?)
190 }
191}
192
193#[cfg(all(feature = "alloc", feature = "pkcs8"))]
194#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))]
195impl<T: pkcs8::EncodePrivateKey> EncodeRsaPrivateKey for T {
196 fn to_pkcs1_der(&self) -> Result<SecretDocument> {
197 let pkcs8_doc = self.to_pkcs8_der()?;
198 let pkcs8_key = pkcs8::PrivateKeyInfo::from_der(pkcs8_doc.as_bytes())?;
199 pkcs8_key.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
200 RsaPrivateKey::from_der(pkcs8_key.private_key)?.try_into()
201 }
202}
203
204#[cfg(all(feature = "alloc", feature = "pkcs8"))]
205#[cfg_attr(docsrs, doc(cfg(all(feature = "alloc", feature = "pkcs8"))))]
206impl<T: pkcs8::EncodePublicKey> EncodeRsaPublicKey for T {
207 fn to_pkcs1_der(&self) -> Result<Document> {
208 let doc = self.to_public_key_der()?;
209 let spki = pkcs8::SubjectPublicKeyInfo::from_der(doc.as_bytes())?;
210 spki.algorithm.assert_algorithm_oid(ALGORITHM_OID)?;
211 RsaPublicKey::from_der(spki.subject_public_key)?.try_into()
212 }
213}