1use crate::{AlgorithmIdentifier, Error, Result, SubjectPublicKeyInfoRef};
4use der::{EncodeValue, Tagged};
5
6#[cfg(feature = "alloc")]
7use {
8 crate::AlgorithmIdentifierOwned,
9 der::{Any, Document, asn1::BitString},
10};
11
12#[cfg(feature = "pem")]
13use {
14 alloc::string::String,
15 der::pem::{LineEnding, PemLabel},
16};
17
18#[cfg(feature = "std")]
19use std::path::Path;
20
21#[cfg(doc)]
22use crate::SubjectPublicKeyInfo;
23
24pub trait DecodePublicKey: Sized {
26 fn from_public_key_der(bytes: &[u8]) -> Result<Self>;
32
33 #[cfg(feature = "pem")]
44 fn from_public_key_pem(s: &str) -> Result<Self> {
45 let (label, doc) = Document::from_pem(s)?;
46 SubjectPublicKeyInfoRef::validate_pem_label(label)?;
47 Self::from_public_key_der(doc.as_bytes())
48 }
49
50 #[cfg(feature = "std")]
56 fn read_public_key_der_file(path: impl AsRef<Path>) -> Result<Self> {
57 let doc = Document::read_der_file(path)?;
58 Self::from_public_key_der(doc.as_bytes())
59 }
60
61 #[cfg(all(feature = "pem", feature = "std"))]
66 fn read_public_key_pem_file(path: impl AsRef<Path>) -> Result<Self> {
67 let (label, doc) = Document::read_pem_file(path)?;
68 SubjectPublicKeyInfoRef::validate_pem_label(&label)?;
69 Self::from_public_key_der(doc.as_bytes())
70 }
71}
72
73impl<T> DecodePublicKey for T
74where
75 T: for<'a> TryFrom<SubjectPublicKeyInfoRef<'a>, Error = Error>,
76{
77 fn from_public_key_der(bytes: &[u8]) -> Result<Self> {
78 Self::try_from(SubjectPublicKeyInfoRef::try_from(bytes)?)
79 }
80}
81
82#[cfg(feature = "alloc")]
84pub trait EncodePublicKey {
85 fn to_public_key_der(&self) -> Result<Document>;
90
91 #[cfg(feature = "pem")]
96 fn to_public_key_pem(&self, line_ending: LineEnding) -> Result<String> {
97 let doc = self.to_public_key_der()?;
98 Ok(doc.to_pem(SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
99 }
100
101 #[cfg(feature = "std")]
106 fn write_public_key_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
107 Ok(self.to_public_key_der()?.write_der_file(path)?)
108 }
109
110 #[cfg(all(feature = "pem", feature = "std"))]
115 fn write_public_key_pem_file(
116 &self,
117 path: impl AsRef<Path>,
118 line_ending: LineEnding,
119 ) -> Result<()> {
120 let doc = self.to_public_key_der()?;
121 Ok(doc.write_pem_file(path, SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
122 }
123}
124
125pub trait AssociatedAlgorithmIdentifier {
129 type Params: Tagged + EncodeValue;
131
132 const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
134}
135
136#[cfg(feature = "alloc")]
140pub trait DynAssociatedAlgorithmIdentifier {
141 fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
146}
147
148#[cfg(feature = "alloc")]
149impl<T> DynAssociatedAlgorithmIdentifier for T
150where
151 T: AssociatedAlgorithmIdentifier,
152{
153 fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
154 Ok(AlgorithmIdentifierOwned {
155 oid: T::ALGORITHM_IDENTIFIER.oid,
156 parameters: T::ALGORITHM_IDENTIFIER
157 .parameters
158 .as_ref()
159 .map(Any::encode_from)
160 .transpose()?,
161 })
162 }
163}
164
165pub trait SignatureAlgorithmIdentifier {
170 type Params: Tagged + EncodeValue;
172
173 const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
175}
176
177#[cfg(feature = "alloc")]
182pub trait DynSignatureAlgorithmIdentifier {
183 fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
188}
189
190#[cfg(feature = "alloc")]
191impl<T> DynSignatureAlgorithmIdentifier for T
192where
193 T: SignatureAlgorithmIdentifier,
194{
195 fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
196 Ok(AlgorithmIdentifierOwned {
197 oid: T::SIGNATURE_ALGORITHM_IDENTIFIER.oid,
198 parameters: T::SIGNATURE_ALGORITHM_IDENTIFIER
199 .parameters
200 .as_ref()
201 .map(Any::encode_from)
202 .transpose()?,
203 })
204 }
205}
206
207#[cfg(feature = "alloc")]
211pub trait SignatureBitStringEncoding {
212 fn to_bitstring(&self) -> der::Result<BitString>;
217}