1 //! X.509 `SubjectPublicKeyInfo`
2 
3 use crate::{AlgorithmIdentifier, Error, Result};
4 use core::cmp::Ordering;
5 use der::{
6     asn1::{AnyRef, BitStringRef},
7     Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, FixedTag, Header, Length, Reader,
8     Sequence, ValueOrd, Writer,
9 };
10 
11 #[cfg(feature = "alloc")]
12 use der::{
13     asn1::{Any, BitString},
14     Document,
15 };
16 
17 #[cfg(feature = "fingerprint")]
18 use crate::{fingerprint, FingerprintBytes};
19 
20 #[cfg(feature = "pem")]
21 use der::pem::PemLabel;
22 
23 /// [`SubjectPublicKeyInfo`] with [`AnyRef`] algorithm parameters, and [`BitStringRef`] params.
24 pub type SubjectPublicKeyInfoRef<'a> = SubjectPublicKeyInfo<AnyRef<'a>, BitStringRef<'a>>;
25 
26 /// [`SubjectPublicKeyInfo`] with [`Any`] algorithm parameters, and [`BitString`] params.
27 #[cfg(feature = "alloc")]
28 pub type SubjectPublicKeyInfoOwned = SubjectPublicKeyInfo<Any, BitString>;
29 
30 /// X.509 `SubjectPublicKeyInfo` (SPKI) as defined in [RFC 5280 § 4.1.2.7].
31 ///
32 /// ASN.1 structure containing an [`AlgorithmIdentifier`] and public key
33 /// data in an algorithm specific format.
34 ///
35 /// ```text
36 ///    SubjectPublicKeyInfo  ::=  SEQUENCE  {
37 ///         algorithm            AlgorithmIdentifier,
38 ///         subjectPublicKey     BIT STRING  }
39 /// ```
40 ///
41 /// [RFC 5280 § 4.1.2.7]: https://tools.ietf.org/html/rfc5280#section-4.1.2.7
42 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
43 #[derive(Clone, Debug, Eq, PartialEq)]
44 pub struct SubjectPublicKeyInfo<Params, Key> {
45     /// X.509 [`AlgorithmIdentifier`] for the public key type
46     pub algorithm: AlgorithmIdentifier<Params>,
47 
48     /// Public key data
49     pub subject_public_key: Key,
50 }
51 
52 impl<'a, Params, Key> SubjectPublicKeyInfo<Params, Key>
53 where
54     Params: Choice<'a> + Encode,
55     // TODO: replace FixedTag with FixedTag<TAG = { Tag::BitString }> once
56     // https://github.com/rust-lang/rust/issues/92827 is fixed
57     Key: Decode<'a> + Encode + FixedTag,
58 {
59     /// Calculate the SHA-256 fingerprint of this [`SubjectPublicKeyInfo`] and
60     /// encode it as a Base64 string.
61     ///
62     /// See [RFC7469 § 2.1.1] for more information.
63     ///
64     /// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1
65     #[cfg(all(feature = "fingerprint", feature = "alloc", feature = "base64"))]
fingerprint_base64(&self) -> Result<alloc::string::String>66     pub fn fingerprint_base64(&self) -> Result<alloc::string::String> {
67         use base64ct::{Base64, Encoding};
68         Ok(Base64::encode_string(&self.fingerprint_bytes()?))
69     }
70 
71     /// Calculate the SHA-256 fingerprint of this [`SubjectPublicKeyInfo`] as
72     /// a raw byte array.
73     ///
74     /// See [RFC7469 § 2.1.1] for more information.
75     ///
76     /// [RFC7469 § 2.1.1]: https://datatracker.ietf.org/doc/html/rfc7469#section-2.1.1
77     #[cfg(feature = "fingerprint")]
fingerprint_bytes(&self) -> Result<FingerprintBytes>78     pub fn fingerprint_bytes(&self) -> Result<FingerprintBytes> {
79         let mut builder = fingerprint::Builder::new();
80         self.encode(&mut builder)?;
81         Ok(builder.finish())
82     }
83 }
84 
85 impl<'a: 'k, 'k, Params, Key: 'k> DecodeValue<'a> for SubjectPublicKeyInfo<Params, Key>
86 where
87     Params: Choice<'a> + Encode,
88     Key: Decode<'a>,
89 {
decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self>90     fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
91         reader.read_nested(header.length, |reader| {
92             Ok(Self {
93                 algorithm: reader.decode()?,
94                 subject_public_key: Key::decode(reader)?,
95             })
96         })
97     }
98 }
99 
100 impl<'a, Params, Key> EncodeValue for SubjectPublicKeyInfo<Params, Key>
101 where
102     Params: Choice<'a> + Encode,
103     Key: Encode,
104 {
value_len(&self) -> der::Result<Length>105     fn value_len(&self) -> der::Result<Length> {
106         self.algorithm.encoded_len()? + self.subject_public_key.encoded_len()?
107     }
108 
encode_value(&self, writer: &mut impl Writer) -> der::Result<()>109     fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
110         self.algorithm.encode(writer)?;
111         self.subject_public_key.encode(writer)?;
112         Ok(())
113     }
114 }
115 
116 impl<'a, Params, Key> Sequence<'a> for SubjectPublicKeyInfo<Params, Key>
117 where
118     Params: Choice<'a> + Encode,
119     Key: Decode<'a> + Encode + FixedTag,
120 {
121 }
122 
123 impl<'a, Params, Key> TryFrom<&'a [u8]> for SubjectPublicKeyInfo<Params, Key>
124 where
125     Params: Choice<'a> + Encode,
126     Key: Decode<'a> + Encode + FixedTag,
127 {
128     type Error = Error;
129 
try_from(bytes: &'a [u8]) -> Result<Self>130     fn try_from(bytes: &'a [u8]) -> Result<Self> {
131         Ok(Self::from_der(bytes)?)
132     }
133 }
134 
135 impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo<Params, Key>
136 where
137     Params: Choice<'a> + DerOrd + Encode,
138     Key: ValueOrd,
139 {
value_cmp(&self, other: &Self) -> der::Result<Ordering>140     fn value_cmp(&self, other: &Self) -> der::Result<Ordering> {
141         match self.algorithm.der_cmp(&other.algorithm)? {
142             Ordering::Equal => self.subject_public_key.value_cmp(&other.subject_public_key),
143             other => Ok(other),
144         }
145     }
146 }
147 
148 #[cfg(feature = "alloc")]
149 impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<SubjectPublicKeyInfo<Params, Key>> for Document
150 where
151     Params: Choice<'a> + Encode,
152     Key: Decode<'a> + Encode + FixedTag,
153     BitStringRef<'a>: From<&'k Key>,
154 {
155     type Error = Error;
156 
try_from(spki: SubjectPublicKeyInfo<Params, Key>) -> Result<Document>157     fn try_from(spki: SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
158         Self::try_from(&spki)
159     }
160 }
161 
162 #[cfg(feature = "alloc")]
163 impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo<Params, Key>> for Document
164 where
165     Params: Choice<'a> + Encode,
166     Key: Decode<'a> + Encode + FixedTag,
167     BitStringRef<'a>: From<&'k Key>,
168 {
169     type Error = Error;
170 
try_from(spki: &SubjectPublicKeyInfo<Params, Key>) -> Result<Document>171     fn try_from(spki: &SubjectPublicKeyInfo<Params, Key>) -> Result<Document> {
172         Ok(Self::encode_msg(spki)?)
173     }
174 }
175 
176 #[cfg(feature = "pem")]
177 impl<Params, Key> PemLabel for SubjectPublicKeyInfo<Params, Key> {
178     const PEM_LABEL: &'static str = "PUBLIC KEY";
179 }
180 
181 #[cfg(feature = "alloc")]
182 mod allocating {
183     use super::*;
184     use crate::EncodePublicKey;
185     use der::referenced::*;
186 
187     impl<'a> RefToOwned<'a> for SubjectPublicKeyInfoRef<'a> {
188         type Owned = SubjectPublicKeyInfoOwned;
ref_to_owned(&self) -> Self::Owned189         fn ref_to_owned(&self) -> Self::Owned {
190             SubjectPublicKeyInfo {
191                 algorithm: self.algorithm.ref_to_owned(),
192                 subject_public_key: self.subject_public_key.ref_to_owned(),
193             }
194         }
195     }
196 
197     impl OwnedToRef for SubjectPublicKeyInfoOwned {
198         type Borrowed<'a> = SubjectPublicKeyInfoRef<'a>;
owned_to_ref(&self) -> Self::Borrowed<'_>199         fn owned_to_ref(&self) -> Self::Borrowed<'_> {
200             SubjectPublicKeyInfo {
201                 algorithm: self.algorithm.owned_to_ref(),
202                 subject_public_key: self.subject_public_key.owned_to_ref(),
203             }
204         }
205     }
206 
207     impl SubjectPublicKeyInfoOwned {
208         /// Create a [`SubjectPublicKeyInfoOwned`] from any object that implements
209         /// [`EncodePublicKey`].
from_key<T>(source: T) -> Result<Self> where T: EncodePublicKey,210         pub fn from_key<T>(source: T) -> Result<Self>
211         where
212             T: EncodePublicKey,
213         {
214             Ok(source.to_public_key_der()?.decode_msg::<Self>()?)
215         }
216     }
217 }
218