1use crate::{AlgorithmIdentifier, Error, Result, SubjectPublicKeyInfoRef};
4use der::{EncodeValue, Tagged};
5
6#[cfg(feature = "alloc")]
7use {
8    crate::AlgorithmIdentifierOwned,
9    der::{asn1::BitString, Any, Document},
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>;
29
30    #[cfg(feature = "pem")]
38    fn from_public_key_pem(s: &str) -> Result<Self> {
39        let (label, doc) = Document::from_pem(s)?;
40        SubjectPublicKeyInfoRef::validate_pem_label(label)?;
41        Self::from_public_key_der(doc.as_bytes())
42    }
43
44    #[cfg(feature = "std")]
47    fn read_public_key_der_file(path: impl AsRef<Path>) -> Result<Self> {
48        let doc = Document::read_der_file(path)?;
49        Self::from_public_key_der(doc.as_bytes())
50    }
51
52    #[cfg(all(feature = "pem", feature = "std"))]
54    fn read_public_key_pem_file(path: impl AsRef<Path>) -> Result<Self> {
55        let (label, doc) = Document::read_pem_file(path)?;
56        SubjectPublicKeyInfoRef::validate_pem_label(&label)?;
57        Self::from_public_key_der(doc.as_bytes())
58    }
59}
60
61impl<T> DecodePublicKey for T
62where
63    T: for<'a> TryFrom<SubjectPublicKeyInfoRef<'a>, Error = Error>,
64{
65    fn from_public_key_der(bytes: &[u8]) -> Result<Self> {
66        Self::try_from(SubjectPublicKeyInfoRef::try_from(bytes)?)
67    }
68}
69
70#[cfg(feature = "alloc")]
72pub trait EncodePublicKey {
73    fn to_public_key_der(&self) -> Result<Document>;
75
76    #[cfg(feature = "pem")]
78    fn to_public_key_pem(&self, line_ending: LineEnding) -> Result<String> {
79        let doc = self.to_public_key_der()?;
80        Ok(doc.to_pem(SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
81    }
82
83    #[cfg(feature = "std")]
85    fn write_public_key_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
86        Ok(self.to_public_key_der()?.write_der_file(path)?)
87    }
88
89    #[cfg(all(feature = "pem", feature = "std"))]
91    fn write_public_key_pem_file(
92        &self,
93        path: impl AsRef<Path>,
94        line_ending: LineEnding,
95    ) -> Result<()> {
96        let doc = self.to_public_key_der()?;
97        Ok(doc.write_pem_file(path, SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
98    }
99}
100
101pub trait AssociatedAlgorithmIdentifier {
105    type Params: Tagged + EncodeValue;
107
108    const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
110}
111
112#[cfg(feature = "alloc")]
116pub trait DynAssociatedAlgorithmIdentifier {
117    fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
119}
120
121#[cfg(feature = "alloc")]
122impl<T> DynAssociatedAlgorithmIdentifier for T
123where
124    T: AssociatedAlgorithmIdentifier,
125{
126    fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
127        Ok(AlgorithmIdentifierOwned {
128            oid: T::ALGORITHM_IDENTIFIER.oid,
129            parameters: T::ALGORITHM_IDENTIFIER
130                .parameters
131                .as_ref()
132                .map(Any::encode_from)
133                .transpose()?,
134        })
135    }
136}
137
138pub trait SignatureAlgorithmIdentifier {
143    type Params: Tagged + EncodeValue;
145
146    const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
148}
149
150#[cfg(feature = "alloc")]
155pub trait DynSignatureAlgorithmIdentifier {
156    fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
158}
159
160#[cfg(feature = "alloc")]
161impl<T> DynSignatureAlgorithmIdentifier for T
162where
163    T: SignatureAlgorithmIdentifier,
164{
165    fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
166        Ok(AlgorithmIdentifierOwned {
167            oid: T::SIGNATURE_ALGORITHM_IDENTIFIER.oid,
168            parameters: T::SIGNATURE_ALGORITHM_IDENTIFIER
169                .parameters
170                .as_ref()
171                .map(Any::encode_from)
172                .transpose()?,
173        })
174    }
175}
176
177#[cfg(feature = "alloc")]
181pub trait SignatureBitStringEncoding {
182    fn to_bitstring(&self) -> der::Result<BitString>;
184}