1use crate::{AlgorithmIdentifier, Error, Result};
4use core::cmp::Ordering;
5use der::{
6 Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, FixedTag, Header, Length, Reader,
7 Sequence, ValueOrd, Writer,
8 asn1::{AnyRef, BitStringRef},
9};
10
11#[cfg(feature = "alloc")]
12use der::{
13 Document,
14 asn1::{Any, BitString},
15};
16
17#[cfg(feature = "fingerprint")]
18use {
19 crate::{DigestWriter, FingerprintBytes},
20 digest::Digest,
21 sha2::Sha256,
22};
23
24#[cfg(feature = "pem")]
25use der::pem::PemLabel;
26
27pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo<AnyRef<'a>, BitStringRef<'a>>;
31
32#[cfg(feature = "alloc")]
36pub type SubjectPublicKeyInfoOwned = SubjectPublicKeyInfo<Any, BitString>;
37
38#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
51#[derive(Clone, Debug, Eq, PartialEq)]
52pub struct SubjectPublicKeyInfo<Params, Key> {
53 pub algorithm: AlgorithmIdentifier<Params>,
55
56 pub subject_public_key: Key,
58}
59
60impl<'a, Params, Key> SubjectPublicKeyInfo<Params, Key>
61where
62 Params: Choice<'a, Error = der::Error> + Encode,
63 Key: Decode<'a, Error = der::Error> + Encode + FixedTag,
66{
67 #[cfg(all(feature = "fingerprint", feature = "alloc", feature = "base64"))]
77 pub fn fingerprint_base64(&self) -> Result<alloc::string::String> {
78 use base64ct::{Base64, Encoding};
79 Ok(Base64::encode_string(&self.fingerprint_bytes()?))
80 }
81
82 #[cfg(feature = "fingerprint")]
92 pub fn fingerprint_bytes(&self) -> Result<FingerprintBytes> {
93 let mut hash = Sha256::new();
94 self.encode(&mut DigestWriter(&mut hash))?;
95 Ok(hash.finalize().into())
96 }
97}
98
99impl<'a, Params, Key> DecodeValue<'a> for SubjectPublicKeyInfo<Params, Key>
100where
101 Params: Choice<'a, Error = der::Error> + Encode,
102 Key: Decode<'a, Error = der::Error>,
103{
104 type Error = der::Error;
105
106 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
107 Ok(Self {
108 algorithm: reader.decode()?,
109 subject_public_key: Key::decode(reader)?,
110 })
111 }
112}
113
114impl<'a, Params, Key> EncodeValue for SubjectPublicKeyInfo<Params, Key>
115where
116 Params: Choice<'a, Error = der::Error> + Encode,
117 Key: Encode,
118{
119 fn value_len(&self) -> der::Result<Length> {
120 self.algorithm.encoded_len()? + self.subject_public_key.encoded_len()?
121 }
122
123 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
124 self.algorithm.encode(writer)?;
125 self.subject_public_key.encode(writer)?;
126 Ok(())
127 }
128}
129
130impl<'a, Params, Key> Sequence<'a> for SubjectPublicKeyInfo<Params, Key>
131where
132 Params: Choice<'a, Error = der::Error> + Encode,
133 Key: Decode<'a, Error = der::Error> + Encode + FixedTag,
134{
135}
136
137impl<'a, Params, Key> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<Params, Key>
138where
139 Params: Choice<'a, Error = der::Error> + Encode,
140 Key: Decode<'a, Error = der::Error> + Encode + FixedTag,
141{
142 type Error = Error;
143
144 fn try_from(bytes: &'a [u8]) -> Result<Self> {
145 Ok(Self::from_der(bytes)?)
146 }
147}
148
149impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo<Params, Key>
150where
151 Params: Choice<'a, Error = der::Error> + DerOrd + Encode,
152 Key: ValueOrd,
153{
154 fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
155 match self.algorithm.der_cmp(&other.algorithm)? {
156 Ordering::Equal => self.subject_public_key.value_cmp(&other.subject_public_key),
157 other => Ok(other),
158 }
159 }
160}
161
162#[cfg(feature = "alloc")]
163impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<SubjectPublicKeyInfo<Params, Key>> for Document
164where
165 Params: Choice<'a, Error = der::Error> + Encode,
166 Key: Decode<'a, Error = der::Error> + Encode + FixedTag,
167 BitStringRef<'a>: From<&'k Key>,
168{
169 type Error = Error;
170
171 fn try_from(spki: SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
172 Self::try_from(&spki)
173 }
174}
175
176#[cfg(feature = "alloc")]
177impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo<Params, Key>> for Document
178where
179 Params: Choice<'a, Error = der::Error> + Encode,
180 Key: Decode<'a, Error = der::Error> + Encode + FixedTag,
181 BitStringRef<'a>: From<&'k Key>,
182{
183 type Error = Error;
184
185 fn try_from(spki: &SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
186 Ok(Self::encode_msg(spki)?)
187 }
188}
189
190#[cfg(feature = "pem")]
191impl<Params, Key> PemLabel for SubjectPublicKeyInfo<Params, Key> {
192 const PEM_LABEL: &'static str = "PUBLIC KEY";
193}
194
195#[cfg(feature = "alloc")]
196mod allocating {
197 use super::*;
198 use crate::EncodePublicKey;
199 use der::referenced::*;
200
201 impl<'a> RefToOwned<'a> for SubjectPublicKeyInfoRef<'a> {
202 type Owned = SubjectPublicKeyInfoOwned;
203 fn ref_to_owned(&self) -> Self::Owned {
204 SubjectPublicKeyInfo {
205 algorithm: self.algorithm.ref_to_owned(),
206 subject_public_key: self.subject_public_key.ref_to_owned(),
207 }
208 }
209 }
210
211 impl OwnedToRef for SubjectPublicKeyInfoOwned {
212 type Borrowed<'a> = SubjectPublicKeyInfoRef<'a>;
213 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
214 SubjectPublicKeyInfo {
215 algorithm: self.algorithm.owned_to_ref(),
216 subject_public_key: self.subject_public_key.owned_to_ref(),
217 }
218 }
219 }
220
221 impl SubjectPublicKeyInfoOwned {
222 pub fn from_key<T: EncodePublicKey>(source: &T) -> Result<Self> {
228 Ok(source.to_public_key_der()?.decode_msg::<Self>()?)
229 }
230 }
231}