/rust/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/src/spki.rs
Line | Count | Source |
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"))] |
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")] |
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 | | { |
90 | 22.8k | fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> { |
91 | 22.8k | reader.read_nested(header.length, |reader| { |
92 | | Ok(Self { |
93 | 22.7k | algorithm: reader.decode()?, |
94 | 21.2k | subject_public_key: Key::decode(reader)?, |
95 | | }) |
96 | 22.7k | }) <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::decode::DecodeValue>::decode_value::<der::reader::nested::NestedReader<der::reader::nested::NestedReader<der::reader::slice::SliceReader>>>::{closure#0}Line | Count | Source | 91 | 22.7k | reader.read_nested(header.length, |reader| { | 92 | | Ok(Self { | 93 | 22.7k | algorithm: reader.decode()?, | 94 | 21.2k | subject_public_key: Key::decode(reader)?, | 95 | | }) | 96 | 22.7k | }) |
Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::decode::DecodeValue>::decode_value::<der::reader::slice::SliceReader>::{closure#0}Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<_, _> as der::decode::DecodeValue>::decode_value::<_>::{closure#0} |
97 | 22.8k | } <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::decode::DecodeValue>::decode_value::<der::reader::nested::NestedReader<der::reader::nested::NestedReader<der::reader::slice::SliceReader>>> Line | Count | Source | 90 | 22.8k | fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> { | 91 | 22.8k | reader.read_nested(header.length, |reader| { | 92 | | Ok(Self { | 93 | | algorithm: reader.decode()?, | 94 | | subject_public_key: Key::decode(reader)?, | 95 | | }) | 96 | | }) | 97 | 22.8k | } |
Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::decode::DecodeValue>::decode_value::<der::reader::slice::SliceReader> Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<_, _> as der::decode::DecodeValue>::decode_value::<_> |
98 | | } |
99 | | |
100 | | impl<'a, Params, Key> EncodeValue for SubjectPublicKeyInfo<Params, Key> |
101 | | where |
102 | | Params: Choice<'a> + Encode, |
103 | | Key: Encode, |
104 | | { |
105 | 3.86k | fn value_len(&self) -> der::Result<Length> { |
106 | 3.86k | self.algorithm.encoded_len()? + self.subject_public_key.encoded_len()? |
107 | 3.86k | } <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::encode::EncodeValue>::value_len Line | Count | Source | 105 | 3.86k | fn value_len(&self) -> der::Result<Length> { | 106 | 3.86k | self.algorithm.encoded_len()? + self.subject_public_key.encoded_len()? | 107 | 3.86k | } |
Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<_, _> as der::encode::EncodeValue>::value_len |
108 | | |
109 | 1.28k | fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> { |
110 | 1.28k | self.algorithm.encode(writer)?; |
111 | 1.28k | self.subject_public_key.encode(writer)?; |
112 | 1.28k | Ok(()) |
113 | 1.28k | } <spki::spki::SubjectPublicKeyInfo<der::asn1::any::allocating::Any, der::asn1::bit_string::allocating::BitString> as der::encode::EncodeValue>::encode_value::<der::writer::slice::SliceWriter> Line | Count | Source | 109 | 1.28k | fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> { | 110 | 1.28k | self.algorithm.encode(writer)?; | 111 | 1.28k | self.subject_public_key.encode(writer)?; | 112 | 1.28k | Ok(()) | 113 | 1.28k | } |
Unexecuted instantiation: <spki::spki::SubjectPublicKeyInfo<_, _> as der::encode::EncodeValue>::encode_value::<_> |
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 | | |
130 | 0 | fn try_from(bytes: &'a [u8]) -> Result<Self> { |
131 | 0 | Ok(Self::from_der(bytes)?) |
132 | 0 | } |
133 | | } |
134 | | |
135 | | impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo<Params, Key> |
136 | | where |
137 | | Params: Choice<'a> + DerOrd + Encode, |
138 | | Key: ValueOrd, |
139 | | { |
140 | 0 | fn value_cmp(&self, other: &Self) -> der::Result<Ordering> { |
141 | 0 | match self.algorithm.der_cmp(&other.algorithm)? { |
142 | 0 | Ordering::Equal => self.subject_public_key.value_cmp(&other.subject_public_key), |
143 | 0 | other => Ok(other), |
144 | | } |
145 | 0 | } |
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 | | |
157 | 0 | fn try_from(spki: SubjectPublicKeyInfo<Params, Key>) -> Result<Document> { |
158 | 0 | Self::try_from(&spki) |
159 | 0 | } |
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 | | |
171 | 0 | fn try_from(spki: &SubjectPublicKeyInfo<Params, Key>) -> Result<Document> { |
172 | 0 | Ok(Self::encode_msg(spki)?) |
173 | 0 | } |
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; |
189 | 0 | fn ref_to_owned(&self) -> Self::Owned { |
190 | 0 | SubjectPublicKeyInfo { |
191 | 0 | algorithm: self.algorithm.ref_to_owned(), |
192 | 0 | subject_public_key: self.subject_public_key.ref_to_owned(), |
193 | 0 | } |
194 | 0 | } |
195 | | } |
196 | | |
197 | | impl OwnedToRef for SubjectPublicKeyInfoOwned { |
198 | | type Borrowed<'a> = SubjectPublicKeyInfoRef<'a>; |
199 | 0 | fn owned_to_ref(&self) -> Self::Borrowed<'_> { |
200 | 0 | SubjectPublicKeyInfo { |
201 | 0 | algorithm: self.algorithm.owned_to_ref(), |
202 | 0 | subject_public_key: self.subject_public_key.owned_to_ref(), |
203 | 0 | } |
204 | 0 | } |
205 | | } |
206 | | |
207 | | impl SubjectPublicKeyInfoOwned { |
208 | | /// Create a [`SubjectPublicKeyInfoOwned`] from any object that implements |
209 | | /// [`EncodePublicKey`]. |
210 | 0 | pub fn from_key<T>(source: T) -> Result<Self> |
211 | 0 | where |
212 | 0 | T: EncodePublicKey, |
213 | | { |
214 | 0 | Ok(source.to_public_key_der()?.decode_msg::<Self>()?) |
215 | 0 | } |
216 | | } |
217 | | } |