pkcs1/
traits.rs

1//! Traits for parsing objects from PKCS#1 encoded documents
2
3use 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
21/// Parse an [`RsaPrivateKey`] from a PKCS#1-encoded document.
22pub trait DecodeRsaPrivateKey: Sized {
23    /// Deserialize PKCS#1 private key from ASN.1 DER-encoded data
24    /// (binary format).
25    fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
26
27    /// Deserialize PKCS#1-encoded private key from PEM.
28    ///
29    /// Keys in this format begin with the following:
30    ///
31    /// ```text
32    /// -----BEGIN RSA PRIVATE KEY-----
33    /// ```
34    #[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    /// Load PKCS#1 private key from an ASN.1 DER-encoded file on the local
42    /// filesystem (binary format).
43    #[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    /// Load PKCS#1 private key from a PEM-encoded file on the local filesystem.
49    #[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
57/// Parse a [`RsaPublicKey`] from a PKCS#1-encoded document.
58pub trait DecodeRsaPublicKey: Sized {
59    /// Deserialize object from ASN.1 DER-encoded [`RsaPublicKey`]
60    /// (binary format).
61    fn from_pkcs1_der(bytes: &[u8]) -> Result<Self>;
62
63    /// Deserialize PEM-encoded [`RsaPublicKey`].
64    ///
65    /// Keys in this format begin with the following:
66    ///
67    /// ```text
68    /// -----BEGIN RSA PUBLIC KEY-----
69    /// ```
70    #[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    /// Load [`RsaPublicKey`] from an ASN.1 DER-encoded file on the local
78    /// filesystem (binary format).
79    #[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    /// Load [`RsaPublicKey`] from a PEM-encoded file on the local filesystem.
86    #[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/// Serialize a [`RsaPrivateKey`] to a PKCS#1 encoded document.
95#[cfg(feature = "alloc")]
96pub trait EncodeRsaPrivateKey {
97    /// Serialize a [`SecretDocument`] containing a PKCS#1-encoded private key.
98    fn to_pkcs1_der(&self) -> Result<SecretDocument>;
99
100    /// Serialize this private key as PEM-encoded PKCS#1 with the given [`LineEnding`].
101    #[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    /// Write ASN.1 DER-encoded PKCS#1 private key to the given path.
108    #[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    /// Write ASN.1 PEM-encoded PKCS#1 private key to the given path.
114    #[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/// Serialize a [`RsaPublicKey`] to a PKCS#1-encoded document.
122#[cfg(feature = "alloc")]
123pub trait EncodeRsaPublicKey {
124    /// Serialize a [`Document`] containing a PKCS#1-encoded public key.
125    fn to_pkcs1_der(&self) -> Result<Document>;
126
127    /// Serialize this public key as PEM-encoded PKCS#1 with the given line ending.
128    #[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    /// Write ASN.1 DER-encoded public key to the given path.
135    #[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    /// Write ASN.1 PEM-encoded public key to the given path.
141    #[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}