/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 | | } |