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