Coverage Report

Created: 2026-09-01 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/src/traits.rs
Line
Count
Source
1
//! Traits for encoding/decoding SPKI public keys.
2
3
use crate::{AlgorithmIdentifier, Error, Result, SubjectPublicKeyInfoRef};
4
use der::{EncodeValue, Tagged};
5
6
#[cfg(feature = "alloc")]
7
use {
8
    crate::AlgorithmIdentifierOwned,
9
    der::{asn1::BitString, Any, Document},
10
};
11
12
#[cfg(feature = "pem")]
13
use {
14
    alloc::string::String,
15
    der::pem::{LineEnding, PemLabel},
16
};
17
18
#[cfg(feature = "std")]
19
use std::path::Path;
20
21
#[cfg(doc)]
22
use crate::SubjectPublicKeyInfo;
23
24
/// Parse a public key object from an encoded SPKI document.
25
pub trait DecodePublicKey: Sized {
26
    /// Deserialize object from ASN.1 DER-encoded [`SubjectPublicKeyInfo`]
27
    /// (binary format).
28
    fn from_public_key_der(bytes: &[u8]) -> Result<Self>;
29
30
    /// Deserialize PEM-encoded [`SubjectPublicKeyInfo`].
31
    ///
32
    /// Keys in this format begin with the following delimiter:
33
    ///
34
    /// ```text
35
    /// -----BEGIN PUBLIC KEY-----
36
    /// ```
37
    #[cfg(feature = "pem")]
38
    fn from_public_key_pem(s: &str) -> Result<Self> {
39
        let (label, doc) = Document::from_pem(s)?;
40
        SubjectPublicKeyInfoRef::validate_pem_label(label)?;
41
        Self::from_public_key_der(doc.as_bytes())
42
    }
43
44
    /// Load public key object from an ASN.1 DER-encoded file on the local
45
    /// filesystem (binary format).
46
    #[cfg(feature = "std")]
47
    fn read_public_key_der_file(path: impl AsRef<Path>) -> Result<Self> {
48
        let doc = Document::read_der_file(path)?;
49
        Self::from_public_key_der(doc.as_bytes())
50
    }
51
52
    /// Load public key object from a PEM-encoded file on the local filesystem.
53
    #[cfg(all(feature = "pem", feature = "std"))]
54
    fn read_public_key_pem_file(path: impl AsRef<Path>) -> Result<Self> {
55
        let (label, doc) = Document::read_pem_file(path)?;
56
        SubjectPublicKeyInfoRef::validate_pem_label(&label)?;
57
        Self::from_public_key_der(doc.as_bytes())
58
    }
59
}
60
61
impl<T> DecodePublicKey for T
62
where
63
    T: for<'a> TryFrom<SubjectPublicKeyInfoRef<'a>, Error = Error>,
64
{
65
0
    fn from_public_key_der(bytes: &[u8]) -> Result<Self> {
66
0
        Self::try_from(SubjectPublicKeyInfoRef::try_from(bytes)?)
67
0
    }
68
}
69
70
/// Serialize a public key object to a SPKI-encoded document.
71
#[cfg(feature = "alloc")]
72
pub trait EncodePublicKey {
73
    /// Serialize a [`Document`] containing a SPKI-encoded public key.
74
    fn to_public_key_der(&self) -> Result<Document>;
75
76
    /// Serialize this public key as PEM-encoded SPKI with the given [`LineEnding`].
77
    #[cfg(feature = "pem")]
78
    fn to_public_key_pem(&self, line_ending: LineEnding) -> Result<String> {
79
        let doc = self.to_public_key_der()?;
80
        Ok(doc.to_pem(SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
81
    }
82
83
    /// Write ASN.1 DER-encoded public key to the given path
84
    #[cfg(feature = "std")]
85
    fn write_public_key_der_file(&self, path: impl AsRef<Path>) -> Result<()> {
86
        Ok(self.to_public_key_der()?.write_der_file(path)?)
87
    }
88
89
    /// Write ASN.1 DER-encoded public key to the given path
90
    #[cfg(all(feature = "pem", feature = "std"))]
91
    fn write_public_key_pem_file(
92
        &self,
93
        path: impl AsRef<Path>,
94
        line_ending: LineEnding,
95
    ) -> Result<()> {
96
        let doc = self.to_public_key_der()?;
97
        Ok(doc.write_pem_file(path, SubjectPublicKeyInfoRef::PEM_LABEL, line_ending)?)
98
    }
99
}
100
101
/// Returns `AlgorithmIdentifier` associated with the structure.
102
///
103
/// This is useful for e.g. keys for digital signature algorithms.
104
pub trait AssociatedAlgorithmIdentifier {
105
    /// Algorithm parameters.
106
    type Params: Tagged + EncodeValue;
107
108
    /// `AlgorithmIdentifier` for this structure.
109
    const ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
110
}
111
112
/// Returns `AlgorithmIdentifier` associated with the structure.
113
///
114
/// This is useful for e.g. keys for digital signature algorithms.
115
#[cfg(feature = "alloc")]
116
pub trait DynAssociatedAlgorithmIdentifier {
117
    /// `AlgorithmIdentifier` for this structure.
118
    fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
119
}
120
121
#[cfg(feature = "alloc")]
122
impl<T> DynAssociatedAlgorithmIdentifier for T
123
where
124
    T: AssociatedAlgorithmIdentifier,
125
{
126
0
    fn algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
127
        Ok(AlgorithmIdentifierOwned {
128
0
            oid: T::ALGORITHM_IDENTIFIER.oid,
129
0
            parameters: T::ALGORITHM_IDENTIFIER
130
0
                .parameters
131
0
                .as_ref()
132
0
                .map(Any::encode_from)
133
0
                .transpose()?,
134
        })
135
0
    }
136
}
137
138
/// Returns `AlgorithmIdentifier` associated with the signature system.
139
///
140
/// Unlike AssociatedAlgorithmIdentifier this is intended to be implemented for public and/or
141
/// private keys.
142
pub trait SignatureAlgorithmIdentifier {
143
    /// Algorithm parameters.
144
    type Params: Tagged + EncodeValue;
145
146
    /// `AlgorithmIdentifier` for the corresponding singature system.
147
    const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier<Self::Params>;
148
}
149
150
/// Returns `AlgorithmIdentifier` associated with the signature system.
151
///
152
/// Unlike AssociatedAlgorithmIdentifier this is intended to be implemented for public and/or
153
/// private keys.
154
#[cfg(feature = "alloc")]
155
pub trait DynSignatureAlgorithmIdentifier {
156
    /// `AlgorithmIdentifier` for the corresponding singature system.
157
    fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned>;
158
}
159
160
#[cfg(feature = "alloc")]
161
impl<T> DynSignatureAlgorithmIdentifier for T
162
where
163
    T: SignatureAlgorithmIdentifier,
164
{
165
0
    fn signature_algorithm_identifier(&self) -> Result<AlgorithmIdentifierOwned> {
166
        Ok(AlgorithmIdentifierOwned {
167
0
            oid: T::SIGNATURE_ALGORITHM_IDENTIFIER.oid,
168
0
            parameters: T::SIGNATURE_ALGORITHM_IDENTIFIER
169
0
                .parameters
170
0
                .as_ref()
171
0
                .map(Any::encode_from)
172
0
                .transpose()?,
173
        })
174
0
    }
175
}
176
177
/// Returns the `BitString` encoding of the signature.
178
///
179
/// X.509 and CSR structures require signatures to be BitString encoded.
180
#[cfg(feature = "alloc")]
181
pub trait SignatureBitStringEncoding {
182
    /// `BitString` encoding for this signature.
183
    fn to_bitstring(&self) -> der::Result<BitString>;
184
}