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}