Skip to main content

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;