structured_pkix/key.rs
1//! The public key a certificate carries.
2//!
3//! The key stays as it was encoded. Interpreting it is the algorithm
4//! registry's work, and re-encoding it here would change what a key identifier
5//! is computed over.
6
7use crate::algorithm::{self, AlgorithmIdentifier};
8use crate::error::{Error, ErrorCode, Located, Result};
9use structured_asn1::{BitString, Element, Reader, Tag, universal};
10
11/// A public key and the algorithm it belongs to.
12#[derive(Debug, Clone, Copy)]
13pub struct PublicKeyInfo<'a> {
14 algorithm: AlgorithmIdentifier<'a>,
15 key: BitString<'a>,
16 der: &'a [u8],
17}
18
19impl<'a> PublicKeyInfo<'a> {
20 /// Which algorithm this key belongs to.
21 #[must_use]
22 pub fn algorithm(self) -> AlgorithmIdentifier<'a> {
23 self.algorithm
24 }
25
26 /// The key itself.
27 #[must_use]
28 pub fn key(self) -> BitString<'a> {
29 self.key
30 }
31
32 /// The key bytes, where the key is a whole number of octets, which it is
33 /// for every algorithm a certificate carries.
34 #[must_use]
35 pub fn key_octets(self) -> Option<&'a [u8]> {
36 self.key.octets()
37 }
38
39 /// The whole structure as it was encoded.
40 ///
41 /// What a fingerprint over the key information is taken of. The key
42 /// identifier the profile describes is a digest of [`Self::key_octets`]
43 /// instead, and the two are different values over different bytes.
44 #[must_use]
45 pub fn as_bytes(self) -> &'a [u8] {
46 self.der
47 }
48 /// Reads SPKI from an element in the caller's reader, retaining its budget.
49 ///
50 /// The structure follows RFC 5280 section 4.1.2.7:
51 /// <https://www.rfc-editor.org/rfc/rfc5280.html#section-4.1.2.7>.
52 /// Algorithm-specific restrictions belong to the cryptographic consumer.
53 /// No key bytes are copied or re-encoded, and no new parser budget is created.
54 ///
55 /// # Errors
56 ///
57 /// Reports malformed structure, trailing fields or an exhausted parent budget.
58 pub fn read_element(
59 parent: &Reader<'a>,
60 element: &Element<'a>,
61 field: &'static str,
62 ) -> Result<PublicKeyInfo<'a>> {
63 let fail = |code| Error::new(code, field, element.span().start);
64
65 if element.tag() != Tag::constructed(universal::SEQUENCE) {
66 return Err(fail(ErrorCode::Encoding(
67 structured_asn1::ErrorCode::UnexpectedTag,
68 )));
69 }
70
71 let mut inside = parent.enter(element).field(field)?;
72 let algorithm_element = inside
73 .next_element()
74 .field(field)?
75 .ok_or_else(|| fail(ErrorCode::MissingField))?;
76 let algorithm = algorithm::read(&inside, &algorithm_element, field)?;
77 let key = inside.read_bit_string().field(field)?;
78
79 if !inside.is_empty() {
80 return Err(fail(ErrorCode::TrailingData));
81 }
82
83 Ok(PublicKeyInfo {
84 algorithm,
85 key,
86 der: element.as_bytes(),
87 })
88 }
89}
90
91#[cfg(test)]
92mod tests;