• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Traits for encoding/decoding SPKI public keys.
2 
3 use crate::{Error, Result, SubjectPublicKeyInfo};
4 
5 #[cfg(feature = "alloc")]
6 use der::Document;
7 
8 #[cfg(feature = "pem")]
9 use {
10     alloc::string::String,
11     der::pem::{LineEnding, PemLabel},
12 };
13 
14 #[cfg(feature = "std")]
15 use std::path::Path;
16 
17 /// Parse a public key object from an encoded SPKI document.
18 pub trait DecodePublicKey:
19     for<'a> TryFrom<SubjectPublicKeyInfo<'a>, Error = Error> + Sized
20 {
21     /// Deserialize object from ASN.1 DER-encoded [`SubjectPublicKeyInfo`]
22     /// (binary format).
from_public_key_der(bytes: &[u8]) -> Result<Self>23     fn from_public_key_der(bytes: &[u8]) -> Result<Self> {
24         Self::try_from(SubjectPublicKeyInfo::try_from(bytes)?)
25     }
26 
27     /// Deserialize PEM-encoded [`SubjectPublicKeyInfo`].
28     ///
29     /// Keys in this format begin with the following delimiter:
30     ///
31     /// ```text
32     /// -----BEGIN PUBLIC KEY-----
33     /// ```
34     #[cfg(feature = "pem")]
35     #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
from_public_key_pem(s: &str) -> Result<Self>36     fn from_public_key_pem(s: &str) -> Result<Self> {
37         let (label, doc) = Document::from_pem(s)?;
38         SubjectPublicKeyInfo::validate_pem_label(label)?;
39         Self::from_public_key_der(doc.as_bytes())
40     }
41 
42     /// Load public key object from an ASN.1 DER-encoded file on the local
43     /// filesystem (binary format).
44     #[cfg(feature = "std")]
45     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
read_public_key_der_file(path: impl AsRef<Path>) -> Result<Self>46     fn read_public_key_der_file(path: impl AsRef<Path>) -> Result<Self> {
47         let doc = Document::read_der_file(path)?;
48         Self::from_public_key_der(doc.as_bytes())
49     }
50 
51     /// Load public key object from a PEM-encoded file on the local filesystem.
52     #[cfg(all(feature = "pem", feature = "std"))]
53     #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
read_public_key_pem_file(path: impl AsRef<Path>) -> Result<Self>54     fn read_public_key_pem_file(path: impl AsRef<Path>) -> Result<Self> {
55         let (label, doc) = Document::read_pem_file(path)?;
56         SubjectPublicKeyInfo::validate_pem_label(&label)?;
57         Self::from_public_key_der(doc.as_bytes())
58     }
59 }
60 
61 /// Serialize a public key object to a SPKI-encoded document.
62 #[cfg(feature = "alloc")]
63 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
64 pub trait EncodePublicKey {
65     /// Serialize a [`Document`] containing a SPKI-encoded public key.
to_public_key_der(&self) -> Result<Document>66     fn to_public_key_der(&self) -> Result<Document>;
67 
68     /// Serialize this public key as PEM-encoded SPKI with the given [`LineEnding`].
69     #[cfg(feature = "pem")]
70     #[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
to_public_key_pem(&self, line_ending: LineEnding) -> Result<String>71     fn to_public_key_pem(&self, line_ending: LineEnding) -> Result<String> {
72         let doc = self.to_public_key_der()?;
73         Ok(doc.to_pem(SubjectPublicKeyInfo::PEM_LABEL, line_ending)?)
74     }
75 
76     /// Write ASN.1 DER-encoded public key to the given path
77     #[cfg(feature = "std")]
78     #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
write_public_key_der_file(&self, path: impl AsRef<Path>) -> Result<()>79     fn write_public_key_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
80         Ok(self.to_public_key_der()?.write_der_file(path)?)
81     }
82 
83     /// Write ASN.1 DER-encoded public key to the given path
84     #[cfg(all(feature = "pem", feature = "std"))]
85     #[cfg_attr(docsrs, doc(cfg(all(feature = "pem", feature = "std"))))]
write_public_key_pem_file( &self, path: impl AsRef<Path>, line_ending: LineEnding, ) -> Result<()>86     fn write_public_key_pem_file(
87         &self,
88         path: impl AsRef<Path>,
89         line_ending: LineEnding,
90     ) -> Result<()> {
91         let doc = self.to_public_key_der()?;
92         Ok(doc.write_pem_file(path, SubjectPublicKeyInfo::PEM_LABEL, line_ending)?)
93     }
94 }
95