1 | //! This crate provides types for representing X.509 certificates, keys and other types as |
2 | //! commonly used in the rustls ecosystem. It is intended to be used by crates that need to work |
3 | //! with such X.509 types, such as [rustls](https://crates.io/crates/rustls), |
4 | //! [rustls-webpki](https://crates.io/crates/rustls-webpki), |
5 | //! [rustls-pemfile](https://crates.io/crates/rustls-pemfile), and others. |
6 | //! |
7 | //! Some of these crates used to define their own trivial wrappers around DER-encoded bytes. |
8 | //! However, in order to avoid inconvenient dependency edges, these were all disconnected. By |
9 | //! using a common low-level crate of types with long-term stable API, we hope to avoid the |
10 | //! downsides of unnecessary dependency edges while providing good interoperability between crates. |
11 | //! |
12 | //! ## DER and PEM |
13 | //! |
14 | //! Many of the types defined in this crate represent DER-encoded data. DER is a binary encoding of |
15 | //! the ASN.1 format commonly used in web PKI specifications. It is a binary encoding, so it is |
16 | //! relatively compact when stored in memory. However, as a binary format, it is not very easy to |
17 | //! work with for humans and in contexts where binary data is inconvenient. For this reason, |
18 | //! many tools and protocols use a ASCII-based encoding of DER, called PEM. In addition to the |
19 | //! base64-encoded DER, PEM objects are delimited by header and footer lines which indicate the type |
20 | //! of object contained in the PEM blob. |
21 | //! |
22 | //! The [rustls-pemfile](https://docs.rs/rustls-pemfile) crate can be used to parse PEM files. |
23 | //! |
24 | //! ## Creating new certificates and keys |
25 | //! |
26 | //! This crate does not provide any functionality for creating new certificates or keys. However, |
27 | //! the [rcgen](https://docs.rs/rcgen) crate can be used to create new certificates and keys. |
28 | //! |
29 | //! ## Cloning private keys |
30 | //! |
31 | //! This crate intentionally **does not** implement `Clone` on private key types in |
32 | //! order to minimize the exposure of private key data in memory. |
33 | //! |
34 | //! If you want to extend the lifetime of a `PrivateKeyDer<'_>`, consider [`PrivateKeyDer::clone_key()`]. |
35 | //! Alternatively since these types are immutable, consider wrapping the `PrivateKeyDer<'_>` in a [`Rc`] |
36 | //! or an [`Arc`]. |
37 | //! |
38 | //! [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html |
39 | //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html |
40 | //! [`PrivateKeyDer::clone_key()`]: https://docs.rs/rustls-pki-types/latest/rustls_pki_types/enum.PrivateKeyDer.html#method.clone_key |
41 | |
42 | #![cfg_attr (not(feature = "std" ), no_std)] |
43 | #![warn (unreachable_pub, clippy::use_self)] |
44 | #![deny (missing_docs)] |
45 | #![cfg_attr (docsrs, feature(doc_cfg, doc_auto_cfg))] |
46 | |
47 | #[cfg (feature = "alloc" )] |
48 | extern crate alloc; |
49 | |
50 | #[cfg (feature = "alloc" )] |
51 | use alloc::vec::Vec; |
52 | use core::fmt; |
53 | use core::ops::Deref; |
54 | use core::time::Duration; |
55 | #[cfg (feature = "std" )] |
56 | use std::time::SystemTime; |
57 | |
58 | mod server_name; |
59 | pub use server_name::{ |
60 | AddrParseError, DnsName, InvalidDnsNameError, IpAddr, Ipv4Addr, Ipv6Addr, ServerName, |
61 | }; |
62 | |
63 | /// A DER-encoded X.509 private key, in one of several formats |
64 | /// |
65 | /// See variant inner types for more detailed information. |
66 | #[non_exhaustive ] |
67 | #[derive (Debug, PartialEq, Eq)] |
68 | pub enum PrivateKeyDer<'a> { |
69 | /// An RSA private key |
70 | Pkcs1(PrivatePkcs1KeyDer<'a>), |
71 | /// A Sec1 private key |
72 | Sec1(PrivateSec1KeyDer<'a>), |
73 | /// A PKCS#8 private key |
74 | Pkcs8(PrivatePkcs8KeyDer<'a>), |
75 | } |
76 | |
77 | impl<'a> PrivateKeyDer<'a> { |
78 | /// Clone the private key to a `'static` value |
79 | #[cfg (feature = "alloc" )] |
80 | pub fn clone_key(&self) -> PrivateKeyDer<'static> { |
81 | use PrivateKeyDer::*; |
82 | match self { |
83 | Pkcs1(key: &PrivatePkcs1KeyDer<'_>) => Pkcs1(key.clone_key()), |
84 | Sec1(key: &PrivateSec1KeyDer<'_>) => Sec1(key.clone_key()), |
85 | Pkcs8(key: &PrivatePkcs8KeyDer<'_>) => Pkcs8(key.clone_key()), |
86 | } |
87 | } |
88 | |
89 | /// Yield the DER-encoded bytes of the private key |
90 | pub fn secret_der(&self) -> &[u8] { |
91 | match self { |
92 | PrivateKeyDer::Pkcs1(key: &PrivatePkcs1KeyDer<'_>) => key.secret_pkcs1_der(), |
93 | PrivateKeyDer::Sec1(key: &PrivateSec1KeyDer<'_>) => key.secret_sec1_der(), |
94 | PrivateKeyDer::Pkcs8(key: &PrivatePkcs8KeyDer<'_>) => key.secret_pkcs8_der(), |
95 | } |
96 | } |
97 | } |
98 | |
99 | impl<'a> From<PrivatePkcs1KeyDer<'a>> for PrivateKeyDer<'a> { |
100 | fn from(key: PrivatePkcs1KeyDer<'a>) -> Self { |
101 | Self::Pkcs1(key) |
102 | } |
103 | } |
104 | |
105 | impl<'a> From<PrivateSec1KeyDer<'a>> for PrivateKeyDer<'a> { |
106 | fn from(key: PrivateSec1KeyDer<'a>) -> Self { |
107 | Self::Sec1(key) |
108 | } |
109 | } |
110 | |
111 | impl<'a> From<PrivatePkcs8KeyDer<'a>> for PrivateKeyDer<'a> { |
112 | fn from(key: PrivatePkcs8KeyDer<'a>) -> Self { |
113 | Self::Pkcs8(key) |
114 | } |
115 | } |
116 | |
117 | /// A DER-encoded plaintext RSA private key; as specified in PKCS#1/RFC 3447 |
118 | /// |
119 | /// RSA private keys are identified in PEM context as `RSA PRIVATE KEY` and when stored in a |
120 | /// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate |
121 | /// documentation. |
122 | #[derive (PartialEq, Eq)] |
123 | pub struct PrivatePkcs1KeyDer<'a>(Der<'a>); |
124 | |
125 | impl PrivatePkcs1KeyDer<'_> { |
126 | /// Clone the private key to a `'static` value |
127 | #[cfg (feature = "alloc" )] |
128 | pub fn clone_key(&self) -> PrivatePkcs1KeyDer<'static> { |
129 | PrivatePkcs1KeyDer::from(self.0.as_ref().to_vec()) |
130 | } |
131 | |
132 | /// Yield the DER-encoded bytes of the private key |
133 | pub fn secret_pkcs1_der(&self) -> &[u8] { |
134 | self.0.as_ref() |
135 | } |
136 | } |
137 | |
138 | impl<'a> From<&'a [u8]> for PrivatePkcs1KeyDer<'a> { |
139 | fn from(slice: &'a [u8]) -> Self { |
140 | Self(Der(DerInner::Borrowed(slice))) |
141 | } |
142 | } |
143 | |
144 | #[cfg (feature = "alloc" )] |
145 | impl<'a> From<Vec<u8>> for PrivatePkcs1KeyDer<'a> { |
146 | fn from(vec: Vec<u8>) -> Self { |
147 | Self(Der(DerInner::Owned(vec))) |
148 | } |
149 | } |
150 | |
151 | impl fmt::Debug for PrivatePkcs1KeyDer<'_> { |
152 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
153 | f&mut DebugTuple<'_, '_>.debug_tuple(name:"PrivatePkcs1KeyDer" ) |
154 | .field(&"[secret key elided]" ) |
155 | .finish() |
156 | } |
157 | } |
158 | |
159 | /// A Sec1-encoded plaintext private key; as specified in RFC 5915 |
160 | /// |
161 | /// Sec1 private keys are identified in PEM context as `EC PRIVATE KEY` and when stored in a |
162 | /// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate |
163 | /// documentation. |
164 | #[derive (PartialEq, Eq)] |
165 | pub struct PrivateSec1KeyDer<'a>(Der<'a>); |
166 | |
167 | impl PrivateSec1KeyDer<'_> { |
168 | /// Clone the private key to a `'static` value |
169 | #[cfg (feature = "alloc" )] |
170 | pub fn clone_key(&self) -> PrivateSec1KeyDer<'static> { |
171 | PrivateSec1KeyDer::from(self.0.as_ref().to_vec()) |
172 | } |
173 | |
174 | /// Yield the DER-encoded bytes of the private key |
175 | pub fn secret_sec1_der(&self) -> &[u8] { |
176 | self.0.as_ref() |
177 | } |
178 | } |
179 | |
180 | impl<'a> From<&'a [u8]> for PrivateSec1KeyDer<'a> { |
181 | fn from(slice: &'a [u8]) -> Self { |
182 | Self(Der(DerInner::Borrowed(slice))) |
183 | } |
184 | } |
185 | |
186 | #[cfg (feature = "alloc" )] |
187 | impl<'a> From<Vec<u8>> for PrivateSec1KeyDer<'a> { |
188 | fn from(vec: Vec<u8>) -> Self { |
189 | Self(Der(DerInner::Owned(vec))) |
190 | } |
191 | } |
192 | |
193 | impl fmt::Debug for PrivateSec1KeyDer<'_> { |
194 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
195 | f&mut DebugTuple<'_, '_>.debug_tuple(name:"PrivateSec1KeyDer" ) |
196 | .field(&"[secret key elided]" ) |
197 | .finish() |
198 | } |
199 | } |
200 | |
201 | /// A DER-encoded plaintext private key; as specified in PKCS#8/RFC 5958 |
202 | /// |
203 | /// PKCS#8 private keys are identified in PEM context as `PRIVATE KEY` and when stored in a |
204 | /// file usually use a `.pem` or `.key` extension. For more on PEM files, refer to the crate |
205 | /// documentation. |
206 | #[derive (PartialEq, Eq)] |
207 | pub struct PrivatePkcs8KeyDer<'a>(Der<'a>); |
208 | |
209 | impl PrivatePkcs8KeyDer<'_> { |
210 | /// Clone the private key to a `'static` value |
211 | #[cfg (feature = "alloc" )] |
212 | pub fn clone_key(&self) -> PrivatePkcs8KeyDer<'static> { |
213 | PrivatePkcs8KeyDer::from(self.0.as_ref().to_vec()) |
214 | } |
215 | |
216 | /// Yield the DER-encoded bytes of the private key |
217 | pub fn secret_pkcs8_der(&self) -> &[u8] { |
218 | self.0.as_ref() |
219 | } |
220 | } |
221 | |
222 | impl<'a> From<&'a [u8]> for PrivatePkcs8KeyDer<'a> { |
223 | fn from(slice: &'a [u8]) -> Self { |
224 | Self(Der(DerInner::Borrowed(slice))) |
225 | } |
226 | } |
227 | |
228 | #[cfg (feature = "alloc" )] |
229 | impl<'a> From<Vec<u8>> for PrivatePkcs8KeyDer<'a> { |
230 | fn from(vec: Vec<u8>) -> Self { |
231 | Self(Der(DerInner::Owned(vec))) |
232 | } |
233 | } |
234 | |
235 | impl fmt::Debug for PrivatePkcs8KeyDer<'_> { |
236 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
237 | f&mut DebugTuple<'_, '_>.debug_tuple(name:"PrivatePkcs8KeyDer" ) |
238 | .field(&"[secret key elided]" ) |
239 | .finish() |
240 | } |
241 | } |
242 | |
243 | /// A trust anchor (a.k.a. root CA) |
244 | /// |
245 | /// Traditionally, certificate verification libraries have represented trust anchors as full X.509 |
246 | /// root certificates. However, those certificates contain a lot more data than is needed for |
247 | /// verifying certificates. The [`TrustAnchor`] representation allows an application to store |
248 | /// just the essential elements of trust anchors. |
249 | /// |
250 | /// The most common way to get one of these is to call [`rustls_webpki::anchor_from_trusted_cert()`]. |
251 | /// |
252 | /// [`rustls_webpki::anchor_from_trusted_cert()`]: https://docs.rs/rustls-webpki/latest/webpki/fn.anchor_from_trusted_cert.html |
253 | #[derive (Clone, Debug, PartialEq, Eq)] |
254 | pub struct TrustAnchor<'a> { |
255 | /// Value of the `subject` field of the trust anchor |
256 | pub subject: Der<'a>, |
257 | /// Value of the `subjectPublicKeyInfo` field of the trust anchor |
258 | pub subject_public_key_info: Der<'a>, |
259 | /// Value of DER-encoded `NameConstraints`, containing name constraints to the trust anchor, if any |
260 | pub name_constraints: Option<Der<'a>>, |
261 | } |
262 | |
263 | impl TrustAnchor<'_> { |
264 | /// Yield a `'static` lifetime of the `TrustAnchor` by allocating owned `Der` variants |
265 | #[cfg (feature = "alloc" )] |
266 | pub fn to_owned(&self) -> TrustAnchor<'static> { |
267 | #[cfg (not(feature = "std" ))] |
268 | use alloc::borrow::ToOwned; |
269 | TrustAnchor { |
270 | subject: self.subject.as_ref().to_owned().into(), |
271 | subject_public_key_info: self.subject_public_key_info.as_ref().to_owned().into(), |
272 | name_constraints: self |
273 | .name_constraints |
274 | .as_ref() |
275 | .map(|nc: &Der<'_>| nc.as_ref().to_owned().into()), |
276 | } |
277 | } |
278 | } |
279 | |
280 | /// A Certificate Revocation List; as specified in RFC 5280 |
281 | /// |
282 | /// Certificate revocation lists are identified in PEM context as `X509 CRL` and when stored in a |
283 | /// file usually use a `.crl` extension. For more on PEM files, refer to the crate documentation. |
284 | #[derive (Clone, Debug, PartialEq, Eq)] |
285 | pub struct CertificateRevocationListDer<'a>(Der<'a>); |
286 | |
287 | impl AsRef<[u8]> for CertificateRevocationListDer<'_> { |
288 | fn as_ref(&self) -> &[u8] { |
289 | self.0.as_ref() |
290 | } |
291 | } |
292 | |
293 | impl Deref for CertificateRevocationListDer<'_> { |
294 | type Target = [u8]; |
295 | |
296 | fn deref(&self) -> &Self::Target { |
297 | self.as_ref() |
298 | } |
299 | } |
300 | |
301 | impl<'a> From<&'a [u8]> for CertificateRevocationListDer<'a> { |
302 | fn from(slice: &'a [u8]) -> Self { |
303 | Self(Der::from(slice)) |
304 | } |
305 | } |
306 | |
307 | #[cfg (feature = "alloc" )] |
308 | impl<'a> From<Vec<u8>> for CertificateRevocationListDer<'a> { |
309 | fn from(vec: Vec<u8>) -> Self { |
310 | Self(Der::from(vec)) |
311 | } |
312 | } |
313 | |
314 | /// A Certificate Signing Request; as specified in RFC 2986 |
315 | /// |
316 | /// Certificate signing requests are identified in PEM context as `CERTIFICATE REQUEST` and when stored in a |
317 | /// file usually use a `.csr` extension. For more on PEM files, refer to the crate documentation. |
318 | #[derive (Clone, Debug, PartialEq, Eq)] |
319 | pub struct CertificateSigningRequestDer<'a>(Der<'a>); |
320 | |
321 | impl AsRef<[u8]> for CertificateSigningRequestDer<'_> { |
322 | fn as_ref(&self) -> &[u8] { |
323 | self.0.as_ref() |
324 | } |
325 | } |
326 | |
327 | impl Deref for CertificateSigningRequestDer<'_> { |
328 | type Target = [u8]; |
329 | |
330 | fn deref(&self) -> &Self::Target { |
331 | self.as_ref() |
332 | } |
333 | } |
334 | |
335 | impl<'a> From<&'a [u8]> for CertificateSigningRequestDer<'a> { |
336 | fn from(slice: &'a [u8]) -> Self { |
337 | Self(Der::from(slice)) |
338 | } |
339 | } |
340 | |
341 | #[cfg (feature = "alloc" )] |
342 | impl<'a> From<Vec<u8>> for CertificateSigningRequestDer<'a> { |
343 | fn from(vec: Vec<u8>) -> Self { |
344 | Self(Der::from(vec)) |
345 | } |
346 | } |
347 | |
348 | /// A DER-encoded X.509 certificate; as specified in RFC 5280 |
349 | /// |
350 | /// Certificates are identified in PEM context as `CERTIFICATE` and when stored in a |
351 | /// file usually use a `.pem`, `.cer` or `.crt` extension. For more on PEM files, refer to the |
352 | /// crate documentation. |
353 | #[derive (Clone, Debug, PartialEq, Eq)] |
354 | pub struct CertificateDer<'a>(Der<'a>); |
355 | |
356 | impl AsRef<[u8]> for CertificateDer<'_> { |
357 | fn as_ref(&self) -> &[u8] { |
358 | self.0.as_ref() |
359 | } |
360 | } |
361 | |
362 | impl Deref for CertificateDer<'_> { |
363 | type Target = [u8]; |
364 | |
365 | fn deref(&self) -> &Self::Target { |
366 | self.as_ref() |
367 | } |
368 | } |
369 | |
370 | impl<'a> From<&'a [u8]> for CertificateDer<'a> { |
371 | fn from(slice: &'a [u8]) -> Self { |
372 | Self(Der::from(slice)) |
373 | } |
374 | } |
375 | |
376 | #[cfg (feature = "alloc" )] |
377 | impl<'a> From<Vec<u8>> for CertificateDer<'a> { |
378 | fn from(vec: Vec<u8>) -> Self { |
379 | Self(Der::from(vec)) |
380 | } |
381 | } |
382 | |
383 | impl CertificateDer<'_> { |
384 | /// Converts this certificate into its owned variant, unfreezing borrowed content (if any) |
385 | #[cfg (feature = "alloc" )] |
386 | pub fn into_owned(self) -> CertificateDer<'static> { |
387 | CertificateDer(Der(self.0 .0.into_owned())) |
388 | } |
389 | } |
390 | |
391 | /// An abstract signature verification algorithm. |
392 | /// |
393 | /// One of these is needed per supported pair of public key type (identified |
394 | /// with `public_key_alg_id()`) and `signatureAlgorithm` (identified with |
395 | /// `signature_alg_id()`). Note that both of these `AlgorithmIdentifier`s include |
396 | /// the parameters encoding, so separate `SignatureVerificationAlgorithm`s are needed |
397 | /// for each possible public key or signature parameters. |
398 | /// |
399 | /// Debug implementations should list the public key algorithm identifier and |
400 | /// signature algorithm identifier in human friendly form (i.e. not encoded bytes), |
401 | /// along with the name of the implementing library (to distinguish different |
402 | /// implementations of the same algorithms). |
403 | pub trait SignatureVerificationAlgorithm: Send + Sync + fmt::Debug { |
404 | /// Verify a signature. |
405 | /// |
406 | /// `public_key` is the `subjectPublicKey` value from a `SubjectPublicKeyInfo` encoding |
407 | /// and is untrusted. The key's `subjectPublicKeyInfo` matches the [`AlgorithmIdentifier`] |
408 | /// returned by `public_key_alg_id()`. |
409 | /// |
410 | /// `message` is the data over which the signature was allegedly computed. |
411 | /// It is not hashed; implementations of this trait function must do hashing |
412 | /// if that is required by the algorithm they implement. |
413 | /// |
414 | /// `signature` is the signature allegedly over `message`. |
415 | /// |
416 | /// Return `Ok(())` only if `signature` is a valid signature on `message`. |
417 | /// |
418 | /// Return `Err(InvalidSignature)` if the signature is invalid, including if the `public_key` |
419 | /// encoding is invalid. There is no need or opportunity to produce errors |
420 | /// that are more specific than this. |
421 | fn verify_signature( |
422 | &self, |
423 | public_key: &[u8], |
424 | message: &[u8], |
425 | signature: &[u8], |
426 | ) -> Result<(), InvalidSignature>; |
427 | |
428 | /// Return the `AlgorithmIdentifier` that must equal a public key's |
429 | /// `subjectPublicKeyInfo` value for this `SignatureVerificationAlgorithm` |
430 | /// to be used for signature verification. |
431 | fn public_key_alg_id(&self) -> AlgorithmIdentifier; |
432 | |
433 | /// Return the `AlgorithmIdentifier` that must equal the `signatureAlgorithm` value |
434 | /// on the data to be verified for this `SignatureVerificationAlgorithm` to be used |
435 | /// for signature verification. |
436 | fn signature_alg_id(&self) -> AlgorithmIdentifier; |
437 | |
438 | /// Return `true` if this is backed by a FIPS-approved implementation. |
439 | fn fips(&self) -> bool { |
440 | false |
441 | } |
442 | } |
443 | |
444 | /// A detail-less error when a signature is not valid. |
445 | #[derive (Debug, Copy, Clone)] |
446 | pub struct InvalidSignature; |
447 | |
448 | /// A DER encoding of the PKIX AlgorithmIdentifier type: |
449 | /// |
450 | /// ```ASN.1 |
451 | /// AlgorithmIdentifier ::= SEQUENCE { |
452 | /// algorithm OBJECT IDENTIFIER, |
453 | /// parameters ANY DEFINED BY algorithm OPTIONAL } |
454 | /// -- contains a value of the type |
455 | /// -- registered for use with the |
456 | /// -- algorithm object identifier value |
457 | /// ``` |
458 | /// (from <https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2>) |
459 | /// |
460 | /// The outer sequence encoding is *not included*, so this is the DER encoding |
461 | /// of an OID for `algorithm` plus the `parameters` value. |
462 | /// |
463 | /// For example, this is the `rsaEncryption` algorithm: |
464 | /// |
465 | /// ``` |
466 | /// let rsa_encryption = rustls_pki_types::AlgorithmIdentifier::from_slice( |
467 | /// &[ |
468 | /// // algorithm: 1.2.840.113549.1.1.1 |
469 | /// 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, |
470 | /// // parameters: NULL |
471 | /// 0x05, 0x00 |
472 | /// ] |
473 | /// ); |
474 | /// ``` |
475 | #[derive (Clone, Copy, PartialEq, Eq)] |
476 | pub struct AlgorithmIdentifier(&'static [u8]); |
477 | |
478 | impl AlgorithmIdentifier { |
479 | /// Makes a new `AlgorithmIdentifier` from a static octet slice. |
480 | /// |
481 | /// This does not validate the contents of the slice. |
482 | pub const fn from_slice(bytes: &'static [u8]) -> Self { |
483 | Self(bytes) |
484 | } |
485 | } |
486 | |
487 | impl AsRef<[u8]> for AlgorithmIdentifier { |
488 | fn as_ref(&self) -> &[u8] { |
489 | self.0 |
490 | } |
491 | } |
492 | |
493 | impl fmt::Debug for AlgorithmIdentifier { |
494 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
495 | hex(f, self.0) |
496 | } |
497 | } |
498 | |
499 | impl Deref for AlgorithmIdentifier { |
500 | type Target = [u8]; |
501 | |
502 | fn deref(&self) -> &Self::Target { |
503 | self.as_ref() |
504 | } |
505 | } |
506 | |
507 | /// A timestamp, tracking the number of non-leap seconds since the Unix epoch. |
508 | /// |
509 | /// The Unix epoch is defined January 1, 1970 00:00:00 UTC. |
510 | #[derive (Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] |
511 | pub struct UnixTime(u64); |
512 | |
513 | impl UnixTime { |
514 | /// The current time, as a `UnixTime` |
515 | #[cfg (feature = "std" )] |
516 | pub fn now() -> Self { |
517 | Self::since_unix_epoch( |
518 | duration:SystemTime::now() |
519 | .duration_since(earlier:SystemTime::UNIX_EPOCH) |
520 | .unwrap(), // Safe: this code did not exist before 1970. |
521 | ) |
522 | } |
523 | |
524 | /// Convert a `Duration` since the start of 1970 to a `UnixTime` |
525 | /// |
526 | /// The `duration` must be relative to the Unix epoch. |
527 | pub fn since_unix_epoch(duration: Duration) -> Self { |
528 | Self(duration.as_secs()) |
529 | } |
530 | |
531 | /// Number of seconds since the Unix epoch |
532 | pub fn as_secs(&self) -> u64 { |
533 | self.0 |
534 | } |
535 | } |
536 | |
537 | /// DER-encoded data, either owned or borrowed |
538 | /// |
539 | /// This wrapper type is used to represent DER-encoded data in a way that is agnostic to whether |
540 | /// the data is owned (by a `Vec<u8>`) or borrowed (by a `&[u8]`). Support for the owned |
541 | /// variant is only available when the `alloc` feature is enabled. |
542 | #[derive (Clone)] |
543 | pub struct Der<'a>(DerInner<'a>); |
544 | |
545 | impl<'a> Der<'a> { |
546 | /// A const constructor to create a `Der` from a borrowed slice |
547 | pub const fn from_slice(der: &'a [u8]) -> Self { |
548 | Self(DerInner::Borrowed(der)) |
549 | } |
550 | } |
551 | |
552 | impl AsRef<[u8]> for Der<'_> { |
553 | fn as_ref(&self) -> &[u8] { |
554 | match &self.0 { |
555 | #[cfg (feature = "alloc" )] |
556 | DerInner::Owned(vec: &Vec) => vec.as_ref(), |
557 | DerInner::Borrowed(slice: &&[u8]) => slice, |
558 | } |
559 | } |
560 | } |
561 | |
562 | impl Deref for Der<'_> { |
563 | type Target = [u8]; |
564 | |
565 | fn deref(&self) -> &Self::Target { |
566 | self.as_ref() |
567 | } |
568 | } |
569 | |
570 | impl<'a> From<&'a [u8]> for Der<'a> { |
571 | fn from(slice: &'a [u8]) -> Self { |
572 | Self(DerInner::Borrowed(slice)) |
573 | } |
574 | } |
575 | |
576 | #[cfg (feature = "alloc" )] |
577 | impl From<Vec<u8>> for Der<'static> { |
578 | fn from(vec: Vec<u8>) -> Self { |
579 | Self(DerInner::Owned(vec)) |
580 | } |
581 | } |
582 | |
583 | impl fmt::Debug for Der<'_> { |
584 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
585 | hex(f, self.as_ref()) |
586 | } |
587 | } |
588 | |
589 | impl PartialEq for Der<'_> { |
590 | fn eq(&self, other: &Self) -> bool { |
591 | self.as_ref().eq(other.as_ref()) |
592 | } |
593 | } |
594 | |
595 | impl Eq for Der<'_> {} |
596 | |
597 | #[derive (Clone)] |
598 | enum DerInner<'a> { |
599 | #[cfg (feature = "alloc" )] |
600 | Owned(Vec<u8>), |
601 | Borrowed(&'a [u8]), |
602 | } |
603 | |
604 | #[cfg (feature = "alloc" )] |
605 | impl DerInner<'_> { |
606 | fn into_owned(self) -> DerInner<'static> { |
607 | DerInner::Owned(match self { |
608 | Self::Owned(vec: Vec) => vec, |
609 | Self::Borrowed(slice: &[u8]) => slice.to_vec(), |
610 | }) |
611 | } |
612 | } |
613 | |
614 | // Format an iterator of u8 into a hex string |
615 | fn hex<'a>(f: &mut fmt::Formatter<'_>, payload: impl IntoIterator<Item = &'a u8>) -> fmt::Result { |
616 | for (i: usize, b: &u8) in payload.into_iter().enumerate() { |
617 | if i == 0 { |
618 | write!(f, "0x" )?; |
619 | } |
620 | write!(f, " {:02x}" , b)?; |
621 | } |
622 | Ok(()) |
623 | } |
624 | |
625 | #[cfg (all(test, feature = "std" ))] |
626 | mod tests { |
627 | use super::*; |
628 | |
629 | #[test ] |
630 | fn der_debug() { |
631 | let der = Der::from_slice(&[0x01, 0x02, 0x03]); |
632 | assert_eq!(format!(" {:?}" , der), "0x010203" ); |
633 | } |
634 | |
635 | #[test ] |
636 | fn alg_id_debug() { |
637 | let alg_id = AlgorithmIdentifier::from_slice(&[0x01, 0x02, 0x03]); |
638 | assert_eq!(format!(" {:?}" , alg_id), "0x010203" ); |
639 | } |
640 | } |
641 | |