sequoia_openpgp/cert/amalgamation/key/iter.rs
1use std::fmt;
2use std::convert::TryInto;
3use std::time::SystemTime;
4use std::borrow::Borrow;
5use std::slice;
6
7use crate::{
8 KeyHandle,
9 types::RevocationStatus,
10 packet::key,
11 types::KeyFlags,
12 cert::prelude::*,
13 policy::Policy,
14};
15
16/// Evaluates whether to skip the use of a secret key when filtering.
17///
18/// This function takes three optional boolean values, indicating whether
19/// an encrypted secret is present,
20/// whether to filter for encrypted secret keys
21/// and whether to filter for unencrypted secret keys.
22///
23/// An optional string provides context in the case where a key is skipped.
24fn skip_secret(
25 have_secret_encrypted: Option<bool>,
26 want_encrypted_key: Option<bool>,
27 want_unencrypted_secret: Option<bool>,
28) -> Option<&'static str> {
29 match (have_secret_encrypted, want_encrypted_key, want_unencrypted_secret) {
30 (Some(_), Some(true), Some(true))
31 | (_, None, None)
32 | (Some(true), Some(true), _)
33 | (Some(true), None, Some(false))
34 | (Some(false), _, Some(true))
35 | (Some(false), Some(false), None) => None, // do not skip the key
36 (Some(true), Some(false), _) | (Some(true), None, Some(true)) => {
37 Some("Encrypted secret... skipping.")
38 }
39 (Some(false), _, Some(false)) | (Some(false), Some(true), None) => {
40 Some("Unencrypted secret... skipping.")
41 }
42 (None, Some(_), None)
43 | (None, None, Some(_))
44 | (None, Some(_), Some(_)) => {
45 Some("No secret... skipping.")
46 }
47 }
48}
49
50/// An iterator over `Key`s.
51///
52/// An iterator over [`KeyAmalgamation`]s.
53///
54/// A `KeyAmalgamationIter` is like a [`ComponentAmalgamationIter`],
55/// but specialized for keys. Refer to the [module documentation] for
56/// an explanation of why a different type is necessary.
57///
58/// Using the [`KeyAmalgamationIter::with_policy`], it is possible to
59/// change the iterator to only return [`KeyAmalgamation`]s for valid
60/// `Key`s. In this case, `KeyAmalgamationIter::with_policy`
61/// transforms the `KeyAmalgamationIter` into a
62/// [`ValidKeyAmalgamationIter`], which returns
63/// [`ValidKeyAmalgamation`]s. `ValidKeyAmalgamation` offers
64/// additional filters.
65///
66/// `KeyAmalgamationIter` supports other filters. For instance
67/// [`KeyAmalgamationIter::secret`] filters on whether secret key
68/// material is present, [`KeyAmalgamationIter::encrypted_secret`]
69/// filters on whether secret key material is present and encrypted, and
70/// [`KeyAmalgamationIter::unencrypted_secret`] filters on whether
71/// secret key material is present and unencrypted. Of course, since
72/// `KeyAmalgamationIter` implements `Iterator`, it is possible to use
73/// [`Iterator::filter`] to implement custom filters.
74///
75/// `KeyAmalgamationIter` follows the builder pattern. There is no
76/// need to explicitly finalize it: it already implements the
77/// `Iterator` trait.
78///
79/// A `KeyAmalgamationIter` is returned by [`Cert::keys`].
80///
81/// [`ComponentAmalgamationIter`]: super::super::ComponentAmalgamationIter
82/// [module documentation]: super
83/// [`KeyAmalgamationIter::with_policy`]: super::ValidateAmalgamation
84/// [`KeyAmalgamationIter::secret`]: KeyAmalgamationIter::secret()
85/// [`KeyAmalgamationIter::unencrypted_secret`]: KeyAmalgamationIter::unencrypted_secret()
86/// [`Iterator::filter`]: std::iter::Iterator::filter()
87/// [`Cert::keys`]: super::super::Cert::keys()
88pub struct KeyAmalgamationIter<'a, P, R>
89 where P: key::KeyParts,
90 R: key::KeyRole,
91{
92 // This is an option to make it easier to create an empty KeyAmalgamationIter.
93 cert: Option<&'a Cert>,
94 primary: bool,
95 subkey_iter: slice::Iter<'a, KeyBundle<key::PublicParts,
96 key::SubordinateRole>>,
97
98 // If not None, filters by whether a key has an encrypted secret.
99 encrypted_secret: Option<bool>,
100
101 // If not None, filters by whether a key has an unencrypted
102 // secret.
103 unencrypted_secret: Option<bool>,
104
105 /// Only return keys in this set.
106 key_handles: Vec<KeyHandle>,
107
108 // If not None, filters by whether we support the key's asymmetric
109 // algorithm.
110 supported: Option<bool>,
111
112 _p: std::marker::PhantomData<P>,
113 _r: std::marker::PhantomData<R>,
114}
115assert_send_and_sync!(KeyAmalgamationIter<'_, P, R>
116 where P: key::KeyParts,
117 R: key::KeyRole,
118);
119
120impl<'a, P, R> fmt::Debug for KeyAmalgamationIter<'a, P, R>
121 where P: key::KeyParts,
122 R: key::KeyRole,
123{
124 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125 f.debug_struct("KeyAmalgamationIter")
126 .field("encrypted_secret", &self.encrypted_secret)
127 .field("unencrypted_secret", &self.unencrypted_secret)
128 .field("key_handles", &self.key_handles)
129 .field("supported", &self.supported)
130 .finish()
131 }
132}
133
134macro_rules! impl_iterator {
135 ($parts:path, $role:path, $item:ty) => {
136 impl<'a> Iterator for KeyAmalgamationIter<'a, $parts, $role>
137 {
138 type Item = $item;
139
140 fn next(&mut self) -> Option<Self::Item> {
141 // We unwrap the result of the conversion. But, this
142 // is safe by construction: next_common only returns
143 // keys that can be correctly converted.
144 self.next_common().map(|k| k.try_into().expect("filtered"))
145 }
146 }
147 }
148}
149
150impl_iterator!(key::PublicParts, key::PrimaryRole,
151 PrimaryKeyAmalgamation<'a, key::PublicParts>);
152impl_iterator!(key::SecretParts, key::PrimaryRole,
153 PrimaryKeyAmalgamation<'a, key::SecretParts>);
154impl_iterator!(key::UnspecifiedParts, key::PrimaryRole,
155 PrimaryKeyAmalgamation<'a, key::UnspecifiedParts>);
156
157impl_iterator!(key::PublicParts, key::SubordinateRole,
158 SubordinateKeyAmalgamation<'a, key::PublicParts>);
159impl_iterator!(key::SecretParts, key::SubordinateRole,
160 SubordinateKeyAmalgamation<'a, key::SecretParts>);
161impl_iterator!(key::UnspecifiedParts, key::SubordinateRole,
162 SubordinateKeyAmalgamation<'a, key::UnspecifiedParts>);
163
164impl_iterator!(key::PublicParts, key::UnspecifiedRole,
165 ErasedKeyAmalgamation<'a, key::PublicParts>);
166impl_iterator!(key::SecretParts, key::UnspecifiedRole,
167 ErasedKeyAmalgamation<'a, key::SecretParts>);
168impl_iterator!(key::UnspecifiedParts, key::UnspecifiedRole,
169 ErasedKeyAmalgamation<'a, key::UnspecifiedParts>);
170
171impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
172 where P: key::KeyParts,
173 R: key::KeyRole,
174{
175 fn next_common(&mut self) -> Option<ErasedKeyAmalgamation<'a, key::PublicParts>>
176 {
177 tracer!(false, "KeyAmalgamationIter::next", 0);
178 t!("KeyAmalgamationIter: {:?}", self);
179
180 let cert = self.cert?;
181
182 loop {
183 let ka : ErasedKeyAmalgamation<key::PublicParts>
184 = if ! self.primary {
185 self.primary = true;
186 PrimaryKeyAmalgamation::new(cert).into()
187 } else {
188 SubordinateKeyAmalgamation::new(
189 cert, self.subkey_iter.next()?).into()
190 };
191
192 t!("Considering key: {:?}", ka.key());
193
194 if ! self.key_handles.is_empty()
195 && ! self.key_handles.iter()
196 .any(|h| h.aliases(ka.key().key_handle()))
197 {
198 t!("{} is not one of the keys that we are looking for ({:?})",
199 ka.key().fingerprint(), self.key_handles);
200 continue;
201 }
202
203 if let Some(want_supported) = self.supported {
204 if ka.key().pk_algo().is_supported() {
205 // It is supported.
206 if ! want_supported {
207 t!("PK algo is supported... skipping.");
208 continue;
209 }
210 } else if want_supported {
211 t!("PK algo is not supported... skipping.");
212 continue;
213 }
214 }
215
216 if let Some(msg) = skip_secret(
217 ka.key().optional_secret().map(|x| x.is_encrypted()),
218 self.encrypted_secret,
219 self.unencrypted_secret,
220 ) {
221 t!(msg);
222 continue;
223 }
224
225 return Some(ka);
226 }
227 }
228}
229
230impl<'a, P, R> KeyAmalgamationIter<'a, P, R>
231 where P: key::KeyParts,
232 R: key::KeyRole,
233{
234 /// Returns a new `KeyAmalgamationIter` instance.
235 pub(crate) fn new(cert: &'a Cert) -> Self where Self: 'a {
236 KeyAmalgamationIter {
237 cert: Some(cert),
238 primary: false,
239 subkey_iter: cert.subkeys.iter(),
240
241 // The filters.
242 encrypted_secret: None,
243 unencrypted_secret: None,
244 key_handles: Default::default(),
245 supported: None,
246
247 _p: std::marker::PhantomData,
248 _r: std::marker::PhantomData,
249 }
250 }
251
252 /// Changes the iterator to only return keys with secret key
253 /// material.
254 ///
255 /// # Examples
256 ///
257 /// ```rust
258 /// # use sequoia_openpgp as openpgp;
259 /// # use openpgp::Result;
260 /// # use openpgp::cert::prelude::*;
261 /// # fn main() -> Result<()> {
262 /// # let (cert, _) =
263 /// # CertBuilder::new().set_password(Some("password".into()))
264 /// # .generate()?;
265 /// for ka in cert.keys().secret() {
266 /// // Use it.
267 /// }
268 /// # assert!(cert.keys().secret().count() == 1);
269 /// #
270 /// # let (cert, _) = CertBuilder::new().generate()?;
271 /// # assert!(cert.keys().secret().count() == 1);
272 /// # Ok(())
273 /// # }
274 /// ```
275 pub fn secret(self) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
276 KeyAmalgamationIter {
277 cert: self.cert,
278 primary: self.primary,
279 subkey_iter: self.subkey_iter,
280
281 // The filters.
282 encrypted_secret: Some(true),
283 unencrypted_secret: Some(true),
284 key_handles: self.key_handles,
285 supported: self.supported,
286
287 _p: std::marker::PhantomData,
288 _r: std::marker::PhantomData,
289 }
290 }
291
292 /// Changes the iterator to only return keys with encrypted secret key
293 /// material.
294 ///
295 /// # Examples
296 ///
297 /// ```rust
298 /// # use sequoia_openpgp as openpgp;
299 /// # use openpgp::Result;
300 /// # use openpgp::cert::prelude::*;
301 /// # fn main() -> Result<()> {
302 /// # let (cert, _) =
303 /// # CertBuilder::new().set_password(Some("password".into()))
304 /// # .generate()?;
305 /// for ka in cert.keys().encrypted_secret() {
306 /// // Use it.
307 /// }
308 /// # assert!(cert.keys().encrypted_secret().count() == 1);
309 /// # Ok(())
310 /// # }
311 /// ```
312 pub fn encrypted_secret(
313 self,
314 ) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
315 KeyAmalgamationIter {
316 cert: self.cert,
317 primary: self.primary,
318 subkey_iter: self.subkey_iter,
319
320 // The filters.
321 encrypted_secret: Some(true),
322 unencrypted_secret: self.unencrypted_secret,
323 key_handles: self.key_handles,
324 supported: self.supported,
325
326 _p: std::marker::PhantomData,
327 _r: std::marker::PhantomData,
328 }
329 }
330
331 /// Changes the iterator to only return keys with unencrypted
332 /// secret key material.
333 ///
334 /// # Examples
335 ///
336 /// ```rust
337 /// # use sequoia_openpgp as openpgp;
338 /// # use openpgp::Result;
339 /// # use openpgp::cert::prelude::*;
340 /// # fn main() -> Result<()> {
341 /// # let (cert, _) =
342 /// # CertBuilder::new().generate()?;
343 /// for ka in cert.keys().unencrypted_secret() {
344 /// // Use it.
345 /// }
346 /// # assert!(cert.keys().secret().unencrypted_secret().count() == 1);
347 /// # Ok(())
348 /// # }
349 /// ```
350 pub fn unencrypted_secret(self) -> KeyAmalgamationIter<'a, key::SecretParts, R> {
351 KeyAmalgamationIter {
352 cert: self.cert,
353 primary: self.primary,
354 subkey_iter: self.subkey_iter,
355
356 // The filters.
357 encrypted_secret: self.encrypted_secret,
358 unencrypted_secret: Some(true),
359 key_handles: self.key_handles,
360 supported: self.supported,
361
362 _p: std::marker::PhantomData,
363 _r: std::marker::PhantomData,
364 }
365 }
366
367 /// Changes the iterator to only return a key if it matches one of
368 /// the specified `KeyHandle`s.
369 ///
370 /// This function is cumulative. If you call this function (or
371 /// [`key_handles`]) multiple times, then the iterator returns a key
372 /// if it matches *any* of the specified [`KeyHandle`s].
373 ///
374 /// This function uses [`KeyHandle::aliases`] to compare key
375 /// handles.
376 ///
377 /// # Examples
378 ///
379 /// ```rust
380 /// # use sequoia_openpgp as openpgp;
381 /// # use openpgp::Result;
382 /// # use openpgp::cert::prelude::*;
383 /// # fn main() -> Result<()> {
384 /// # let (cert, _) =
385 /// # CertBuilder::general_purpose(Some("alice@example.org"))
386 /// # .generate()?;
387 /// # let key_handle = cert.primary_key().key().key_handle();
388 /// # let mut i = 0;
389 /// for ka in cert.keys().key_handle(key_handle) {
390 /// // Use it.
391 /// # i += 1;
392 /// }
393 /// # assert_eq!(i, 1);
394 /// # Ok(())
395 /// # }
396 /// ```
397 ///
398 /// [`KeyHandle`s]: super::super::super::KeyHandle
399 /// [`key_handles`]: KeyAmalgamationIter::key_handles()
400 /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
401 pub fn key_handle<H>(mut self, h: H) -> Self
402 where H: Into<KeyHandle>
403 {
404 self.key_handles.push(h.into());
405 self
406 }
407
408 /// Changes the iterator to only return a key if it matches one of
409 /// the specified `KeyHandle`s.
410 ///
411 /// If the given `handles` iterator is empty, the set of returned
412 /// keys is not constrained.
413 ///
414 /// This function is cumulative. If you call this function (or
415 /// [`key_handle`]) multiple times, then the iterator returns a key
416 /// if it matches *any* of the specified [`KeyHandle`s].
417 ///
418 /// This function uses [`KeyHandle::aliases`] to compare key
419 /// handles.
420 ///
421 /// # Examples
422 ///
423 /// ```rust
424 /// # use sequoia_openpgp as openpgp;
425 /// # use openpgp::Result;
426 /// # use openpgp::cert::prelude::*;
427 /// # fn main() -> Result<()> {
428 /// # let (cert, _) =
429 /// # CertBuilder::general_purpose(Some("alice@example.org"))
430 /// # .generate()?;
431 /// # let key_handles = &[cert.primary_key().key().key_handle()][..];
432 /// # let mut i = 0;
433 /// for ka in cert.keys().key_handles(key_handles) {
434 /// // Use it.
435 /// # i += 1;
436 /// }
437 /// # assert_eq!(i, 1);
438 /// # Ok(())
439 /// # }
440 /// ```
441 ///
442 /// [`KeyHandle`s]: super::super::super::KeyHandle
443 /// [`key_handle`]: KeyAmalgamationIter::key_handle()
444 /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
445 pub fn key_handles<H, K>(mut self, handles: H) -> Self
446 where
447 H: IntoIterator<Item=K>,
448 K: Borrow<KeyHandle>,
449 {
450 let mut handles = handles.into_iter()
451 .map(|h| h.borrow().clone())
452 .collect::<Vec<_>>();
453
454 self.key_handles.append(&mut handles);
455 self
456 }
457
458 /// Changes the iterator to only return a key if it is supported
459 /// by Sequoia's cryptographic backend.
460 ///
461 /// Which public key encryption algorithms Sequoia supports
462 /// depends on the cryptographic backend selected at compile time.
463 /// This filter makes sure that only supported keys are returned.
464 ///
465 /// # Examples
466 ///
467 /// ```rust
468 /// # fn main() -> sequoia_openpgp::Result<()> {
469 /// # use sequoia_openpgp as openpgp;
470 /// # use openpgp::cert::prelude::*;
471 /// # let (cert, _) =
472 /// # CertBuilder::general_purpose(Some("alice@example.org"))
473 /// # .generate()?;
474 /// # let mut i = 0;
475 /// for ka in cert.keys().supported() {
476 /// // Use it.
477 /// # i += 1;
478 /// }
479 /// # assert_eq!(i, 3);
480 /// # Ok(()) }
481 /// ```
482 pub fn supported(mut self) -> Self {
483 self.supported = Some(true);
484 self
485 }
486
487 /// Changes the iterator to only return subkeys.
488 ///
489 /// This function also changes the return type. Instead of the
490 /// iterator returning a [`ErasedKeyAmalgamation`], it returns a
491 /// [`SubordinateKeyAmalgamation`].
492 ///
493 /// # Examples
494 ///
495 /// ```rust
496 /// # use sequoia_openpgp as openpgp;
497 /// # use openpgp::Result;
498 /// # use openpgp::cert::prelude::*;
499 /// #
500 /// # fn main() -> Result<()> {
501 /// # let (cert, _) = CertBuilder::new()
502 /// # .add_signing_subkey()
503 /// # .add_certification_subkey()
504 /// # .add_transport_encryption_subkey()
505 /// # .add_storage_encryption_subkey()
506 /// # .add_authentication_subkey()
507 /// # .generate()?;
508 /// # let mut i = 0;
509 /// for ka in cert.keys().subkeys() {
510 /// // Use it.
511 /// assert!(! ka.primary());
512 /// # i += 1;
513 /// }
514 /// # assert_eq!(i, 5);
515 /// # Ok(())
516 /// # }
517 /// ```
518 ///
519 pub fn subkeys(self) -> KeyAmalgamationIter<'a, P, key::SubordinateRole> {
520 KeyAmalgamationIter {
521 cert: self.cert,
522 primary: true,
523 subkey_iter: self.subkey_iter,
524
525 // The filters.
526 encrypted_secret: self.encrypted_secret,
527 unencrypted_secret: self.unencrypted_secret,
528 key_handles: self.key_handles,
529 supported: self.supported,
530
531 _p: std::marker::PhantomData,
532 _r: std::marker::PhantomData,
533 }
534 }
535
536 /// Changes the iterator to only return valid `Key`s.
537 ///
538 /// If `time` is None, then the current time is used.
539 ///
540 /// This also makes a number of additional filters like [`alive`]
541 /// and [`revoked`] available.
542 ///
543 /// Refer to the [`ValidateAmalgamation`] trait for a definition
544 /// of a valid component.
545 ///
546 /// # Examples
547 ///
548 /// ```
549 /// # use sequoia_openpgp as openpgp;
550 /// # use openpgp::cert::prelude::*;
551 /// use openpgp::policy::StandardPolicy;
552 /// #
553 /// # fn main() -> openpgp::Result<()> {
554 /// let p = &StandardPolicy::new();
555 ///
556 /// # let (cert, _) =
557 /// # CertBuilder::general_purpose(Some("alice@example.org"))
558 /// # .generate()?;
559 /// # let fpr = cert.fingerprint();
560 /// // Iterate over all valid User Attributes.
561 /// for ka in cert.keys().with_policy(p, None) {
562 /// // ka is a `ValidKeyAmalgamation`, specifically, an
563 /// // `ValidErasedKeyAmalgamation`.
564 /// }
565 /// # Ok(())
566 /// # }
567 /// ```
568 ///
569 /// [`ValidateAmalgamation`]: super::ValidateAmalgamation
570 /// [`alive`]: ValidKeyAmalgamationIter::alive()
571 /// [`revoked`]: ValidKeyAmalgamationIter::revoked()
572 pub fn with_policy<T>(self, policy: &'a dyn Policy, time: T)
573 -> ValidKeyAmalgamationIter<'a, P, R>
574 where T: Into<Option<SystemTime>>
575 {
576 ValidKeyAmalgamationIter {
577 cert: self.cert,
578 primary: self.primary,
579 subkey_iter: self.subkey_iter,
580
581 policy,
582 time: time.into().unwrap_or_else(crate::now),
583
584 // The filters.
585 encrypted_secret: self.encrypted_secret,
586 unencrypted_secret: self.unencrypted_secret,
587 key_handles: self.key_handles,
588 supported: self.supported,
589 flags: None,
590 alive: None,
591 revoked: None,
592
593 _p: self._p,
594 _r: self._r,
595 }
596 }
597}
598
599/// An iterator over valid `Key`s.
600///
601/// An iterator over [`ValidKeyAmalgamation`]s.
602///
603/// A `ValidKeyAmalgamationIter` is a [`KeyAmalgamationIter`]
604/// that includes a [`Policy`] and a reference time, which it firstly
605/// uses to only return valid `Key`s. (For a definition of valid
606/// keys, see the documentation for [`ValidateAmalgamation`].)
607///
608/// A `ValidKeyAmalgamationIter` also provides additional
609/// filters based on information available in the `Key`s' binding
610/// signatures. For instance, [`ValidKeyAmalgamationIter::revoked`]
611/// filters the returned `Key`s by whether they are revoked.
612/// And, [`ValidKeyAmalgamationIter::alive`] changes the iterator to
613/// only return `Key`s that are live.
614///
615/// `ValidKeyAmalgamationIter` follows the builder pattern. But,
616/// there is no need to explicitly finalize it: it already implements
617/// the `Iterator` trait.
618///
619/// A `ValidKeyAmalgamationIter` is returned by
620/// [`KeyAmalgamationIter::with_policy`] and [`ValidCert::keys`].
621///
622/// # Examples
623///
624/// Find a key that we can use to sign a document:
625///
626/// ```
627/// # use sequoia_openpgp as openpgp;
628/// # use openpgp::cert::prelude::*;
629/// use openpgp::policy::StandardPolicy;
630/// use openpgp::types::RevocationStatus;
631///
632/// # fn main() -> openpgp::Result<()> {
633/// let p = &StandardPolicy::new();
634///
635/// # let (cert, _) =
636/// # CertBuilder::general_purpose(Some("alice@example.org"))
637/// # .generate()?;
638/// # let mut i = 0;
639/// // The certificate *and* keys need to be valid.
640/// let cert = cert.with_policy(p, None)?;
641///
642/// if let RevocationStatus::Revoked(_) = cert.revocation_status() {
643/// // Certificate is revoked.
644/// } else if let Err(_err) = cert.alive() {
645/// // The certificate is not alive.
646/// } else {
647/// // Iterate over all valid keys.
648/// //
649/// // Note: using the combinator interface (instead of checking
650/// // the individual keys) makes it harder to report exactly why no
651/// // key was usable.
652/// for ka in cert.keys()
653/// // Not revoked.
654/// .revoked(false)
655/// // Alive.
656/// .alive()
657/// // Be signing capable.
658/// .for_signing()
659/// // And have unencrypted secret material.
660/// .unencrypted_secret()
661/// {
662/// // We can use it.
663/// # i += 1;
664/// }
665/// }
666/// # assert_eq!(i, 1);
667/// # Ok(())
668/// # }
669/// ```
670///
671/// [`Policy`]: crate::policy::Policy
672/// [`ValidateAmalgamation`]: super::ValidateAmalgamation
673/// [`ValidKeyAmalgamationIter::revoked`]: ValidKeyAmalgamationIter::revoked()
674/// [`ValidKeyAmalgamationIter::alive`]: ValidKeyAmalgamationIter::alive()
675/// [`KeyAmalgamationIter::with_policy`]: KeyAmalgamationIter::with_policy()
676/// [`ValidCert::keys`]: super::super::ValidCert::keys()
677pub struct ValidKeyAmalgamationIter<'a, P, R>
678 where P: key::KeyParts,
679 R: key::KeyRole,
680{
681 // This is an option to make it easier to create an empty ValidKeyAmalgamationIter.
682 cert: Option<&'a Cert>,
683 primary: bool,
684 subkey_iter: slice::Iter<'a, KeyBundle<key::PublicParts,
685 key::SubordinateRole>>,
686
687 // The policy.
688 policy: &'a dyn Policy,
689
690 // The time.
691 time: SystemTime,
692
693 // If not None, filters by whether a key has an encrypted secret.
694 encrypted_secret: Option<bool>,
695
696 // If not None, filters by whether a key has an unencrypted
697 // secret.
698 unencrypted_secret: Option<bool>,
699
700 /// Only return keys in this set.
701 key_handles: Vec<KeyHandle>,
702
703 // If not None, filters by whether we support the key's asymmetric
704 // algorithm.
705 supported: Option<bool>,
706
707 // If not None, only returns keys with the specified flags.
708 flags: Option<KeyFlags>,
709
710 // If not None, filters by whether a key is alive at time `t`.
711 alive: Option<()>,
712
713 // If not None, filters by whether the key is revoked or not at
714 // time `t`.
715 revoked: Option<bool>,
716
717 _p: std::marker::PhantomData<P>,
718 _r: std::marker::PhantomData<R>,
719}
720assert_send_and_sync!(ValidKeyAmalgamationIter<'_, P, R>
721 where P: key::KeyParts,
722 R: key::KeyRole,
723);
724
725impl<'a, P, R> fmt::Debug for ValidKeyAmalgamationIter<'a, P, R>
726 where P: key::KeyParts,
727 R: key::KeyRole,
728{
729 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
730 f.debug_struct("ValidKeyAmalgamationIter")
731 .field("policy", &self.policy)
732 .field("time", &self.time)
733 .field("encrypted_secret", &self.encrypted_secret)
734 .field("unencrypted_secret", &self.unencrypted_secret)
735 .field("key_handles", &self.key_handles)
736 .field("supported", &self.supported)
737 .field("flags", &self.flags)
738 .field("alive", &self.alive)
739 .field("revoked", &self.revoked)
740 .finish()
741 }
742}
743
744macro_rules! impl_iterator {
745 ($parts:path, $role:path, $item:ty) => {
746 impl<'a> Iterator for ValidKeyAmalgamationIter<'a, $parts, $role>
747 {
748 type Item = $item;
749
750 fn next(&mut self) -> Option<Self::Item> {
751 // We unwrap the result of the conversion. But, this
752 // is safe by construction: next_common only returns
753 // keys that can be correctly converted.
754 self.next_common().map(|k| k.try_into().expect("filtered"))
755 }
756 }
757 }
758}
759
760impl_iterator!(key::PublicParts, key::PrimaryRole,
761 ValidPrimaryKeyAmalgamation<'a, key::PublicParts>);
762impl_iterator!(key::SecretParts, key::PrimaryRole,
763 ValidPrimaryKeyAmalgamation<'a, key::SecretParts>);
764impl_iterator!(key::UnspecifiedParts, key::PrimaryRole,
765 ValidPrimaryKeyAmalgamation<'a, key::UnspecifiedParts>);
766
767impl_iterator!(key::PublicParts, key::SubordinateRole,
768 ValidSubordinateKeyAmalgamation<'a, key::PublicParts>);
769impl_iterator!(key::SecretParts, key::SubordinateRole,
770 ValidSubordinateKeyAmalgamation<'a, key::SecretParts>);
771impl_iterator!(key::UnspecifiedParts, key::SubordinateRole,
772 ValidSubordinateKeyAmalgamation<'a, key::UnspecifiedParts>);
773
774impl_iterator!(key::PublicParts, key::UnspecifiedRole,
775 ValidErasedKeyAmalgamation<'a, key::PublicParts>);
776impl_iterator!(key::SecretParts, key::UnspecifiedRole,
777 ValidErasedKeyAmalgamation<'a, key::SecretParts>);
778impl_iterator!(key::UnspecifiedParts, key::UnspecifiedRole,
779 ValidErasedKeyAmalgamation<'a, key::UnspecifiedParts>);
780
781impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
782 where P: key::KeyParts,
783 R: key::KeyRole,
784{
785 fn next_common(&mut self)
786 -> Option<ValidErasedKeyAmalgamation<'a, key::PublicParts>>
787 {
788 tracer!(false, "ValidKeyAmalgamationIter::next", 0);
789 t!("ValidKeyAmalgamationIter: {:?}", self);
790
791 let cert = self.cert?;
792
793 if let Some(flags) = self.flags.as_ref() {
794 if flags.is_empty() {
795 // Nothing to do.
796 t!("short circuiting: flags is empty");
797 return None;
798 }
799 }
800
801 loop {
802 let ka = if ! self.primary {
803 self.primary = true;
804 let ka : ErasedKeyAmalgamation<'a, key::PublicParts>
805 = PrimaryKeyAmalgamation::new(cert).into();
806 match ka.with_policy(self.policy, self.time) {
807 Ok(ka) => ka,
808 Err(err) => {
809 // The primary key is bad. Abort.
810 t!("Getting primary key: {:?}", err);
811 return None;
812 }
813 }
814 } else {
815 let ka : ErasedKeyAmalgamation<'a, key::PublicParts>
816 = SubordinateKeyAmalgamation::new(
817 cert, self.subkey_iter.next()?).into();
818 match ka.with_policy(self.policy, self.time) {
819 Ok(ka) => ka,
820 Err(err) => {
821 // The subkey is bad, abort.
822 t!("Getting subkey: {:?}", err);
823 continue;
824 }
825 }
826 };
827
828 let key = ka.key();
829 t!("Considering key: {:?}", key);
830
831 if ! self.key_handles.is_empty()
832 && ! self.key_handles.iter()
833 .any(|h| h.aliases(key.key_handle()))
834 {
835 t!("{} is not one of the keys that we are looking for ({:?})",
836 key.key_handle(), self.key_handles);
837 continue;
838 }
839
840 if let Some(want_supported) = self.supported {
841 if ka.key().pk_algo().is_supported() {
842 // It is supported.
843 if ! want_supported {
844 t!("PK algo is supported... skipping.");
845 continue;
846 }
847 } else if want_supported {
848 t!("PK algo is not supported... skipping.");
849 continue;
850 }
851 }
852
853 if let Some(flags) = self.flags.as_ref() {
854 if !ka.has_any_key_flag(flags) {
855 t!("Have flags: {:?}, want flags: {:?}... skipping.",
856 ka.key_flags(), flags);
857 continue;
858 }
859 }
860
861 if let Some(()) = self.alive {
862 if let Err(err) = ka.alive() {
863 t!("Key not alive: {:?}", err);
864 continue;
865 }
866 }
867
868 if let Some(want_revoked) = self.revoked {
869 if let RevocationStatus::Revoked(_) = ka.revocation_status() {
870 // The key is definitely revoked.
871 if ! want_revoked {
872 t!("Key revoked... skipping.");
873 continue;
874 }
875 } else {
876 // The key is probably not revoked.
877 if want_revoked {
878 t!("Key not revoked... skipping.");
879 continue;
880 }
881 }
882 }
883
884 if let Some(msg) = skip_secret(
885 ka.key().optional_secret().map(|x| x.is_encrypted()),
886 self.encrypted_secret,
887 self.unencrypted_secret,
888 ) {
889 t!(msg);
890 continue;
891 }
892
893 return Some(ka);
894 }
895 }
896}
897
898impl<'a, P, R> ValidKeyAmalgamationIter<'a, P, R>
899 where P: key::KeyParts,
900 R: key::KeyRole,
901{
902 /// Returns keys that have the at least one of the flags specified
903 /// in `flags`.
904 ///
905 /// If you call this function (or one of `for_certification`,
906 /// `for_signing`, etc.) multiple times, the *union* of
907 /// the values is used.
908 ///
909 /// Note: [Section 10.1 of RFC 9580] says that the primary key is
910 /// certification capable independent of the `Key Flags`
911 /// subpacket:
912 ///
913 /// > In a V4 key, the primary key MUST be a key capable of
914 /// > certification.
915 ///
916 /// This function only reflects what is stored in the `Key Flags`
917 /// packet; it does not implicitly set this flag. In practice,
918 /// there are keys whose primary key's `Key Flags` do not have the
919 /// certification capable flag set. Some versions of netpgp, for
920 /// instance, create keys like this. Sequoia's higher-level
921 /// functionality correctly handles these keys by always
922 /// considering the primary key to be certification capable.
923 /// Users of this interface should too.
924 ///
925 /// The key flags are looked up as described in
926 /// [`ValidKeyAmalgamation::key_flags`].
927 ///
928 /// # Examples
929 ///
930 /// ```
931 /// # use sequoia_openpgp as openpgp;
932 /// # use openpgp::cert::prelude::*;
933 /// use openpgp::policy::StandardPolicy;
934 /// use openpgp::types::KeyFlags;
935 ///
936 /// # fn main() -> openpgp::Result<()> {
937 /// let p = &StandardPolicy::new();
938 ///
939 /// # let (cert, _) = CertBuilder::new()
940 /// # .add_signing_subkey()
941 /// # .add_certification_subkey()
942 /// # .add_transport_encryption_subkey()
943 /// # .add_storage_encryption_subkey()
944 /// # .add_authentication_subkey()
945 /// # .generate()?;
946 /// # let mut i = 0;
947 /// for ka in cert.keys()
948 /// .with_policy(p, None)
949 /// .key_flags(KeyFlags::empty()
950 /// .set_transport_encryption()
951 /// .set_storage_encryption())
952 /// {
953 /// // Valid encryption-capable keys.
954 /// # i += 1;
955 /// }
956 /// # assert_eq!(i, 2);
957 /// # Ok(()) }
958 /// ```
959 ///
960 /// [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
961 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
962 pub fn key_flags<F>(mut self, flags: F) -> Self
963 where F: Borrow<KeyFlags>
964 {
965 let flags = flags.borrow();
966 if let Some(flags_old) = self.flags {
967 self.flags = Some(flags | &flags_old);
968 } else {
969 self.flags = Some(flags.clone());
970 }
971 self
972 }
973
974 /// Returns certification-capable keys.
975 ///
976 /// If you call this function (or one of `key_flags`,
977 /// `for_signing`, etc.) multiple times, the *union* of
978 /// the values is used.
979 ///
980 /// Note: [Section 10.1 of RFC 9580] says that the primary key is
981 /// certification capable independent of the `Key Flags`
982 /// subpacket:
983 ///
984 /// > In a V4 key, the primary key MUST be a key capable of
985 /// > certification.
986 ///
987 /// This function only reflects what is stored in the `Key Flags`
988 /// packet; it does not implicitly set this flag. In practice,
989 /// there are keys whose primary key's `Key Flags` do not have the
990 /// certification capable flag set. Some versions of netpgp, for
991 /// instance, create keys like this. Sequoia's higher-level
992 /// functionality correctly handles these keys by always
993 /// considering the primary key to be certification capable.
994 /// Users of this interface should too.
995 ///
996 /// The key flags are looked up as described in
997 /// [`ValidKeyAmalgamation::key_flags`].
998 ///
999 /// # Examples
1000 ///
1001 /// ```
1002 /// # use sequoia_openpgp as openpgp;
1003 /// # use openpgp::cert::prelude::*;
1004 /// use openpgp::policy::StandardPolicy;
1005 ///
1006 /// # fn main() -> openpgp::Result<()> {
1007 /// let p = &StandardPolicy::new();
1008 ///
1009 /// # let (cert, _) = CertBuilder::new()
1010 /// # .add_signing_subkey()
1011 /// # .add_certification_subkey()
1012 /// # .add_transport_encryption_subkey()
1013 /// # .add_storage_encryption_subkey()
1014 /// # .add_authentication_subkey()
1015 /// # .generate()?;
1016 /// # let mut i = 0;
1017 /// for ka in cert.keys()
1018 /// .with_policy(p, None)
1019 /// .for_certification()
1020 /// {
1021 /// // Valid certification-capable keys.
1022 /// # i += 1;
1023 /// }
1024 /// # assert_eq!(i, 2);
1025 /// # Ok(()) }
1026 /// ```
1027 ///
1028 /// [`ValidKeyAmalgamation::for_certification`]: ValidKeyAmalgamation::for_certification()
1029 /// [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
1030 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
1031 pub fn for_certification(self) -> Self {
1032 self.key_flags(KeyFlags::empty().set_certification())
1033 }
1034
1035 /// Returns signing-capable keys.
1036 ///
1037 /// If you call this function (or one of `key_flags`,
1038 /// `for_certification`, etc.) multiple times, the *union* of
1039 /// the values is used.
1040 ///
1041 /// Refer to [`ValidKeyAmalgamation::for_signing`] for additional
1042 /// details and caveats.
1043 ///
1044 /// # Examples
1045 ///
1046 /// ```
1047 /// # use sequoia_openpgp as openpgp;
1048 /// # use openpgp::cert::prelude::*;
1049 /// use openpgp::policy::StandardPolicy;
1050 ///
1051 /// # fn main() -> openpgp::Result<()> {
1052 /// let p = &StandardPolicy::new();
1053 ///
1054 /// # let (cert, _) = CertBuilder::new()
1055 /// # .add_signing_subkey()
1056 /// # .add_certification_subkey()
1057 /// # .add_transport_encryption_subkey()
1058 /// # .add_storage_encryption_subkey()
1059 /// # .add_authentication_subkey()
1060 /// # .generate()?;
1061 /// # let mut i = 0;
1062 /// for ka in cert.keys()
1063 /// .with_policy(p, None)
1064 /// .for_signing()
1065 /// {
1066 /// // Valid signing-capable keys.
1067 /// # i += 1;
1068 /// }
1069 /// # assert_eq!(i, 1);
1070 /// # Ok(()) }
1071 /// ```
1072 ///
1073 /// [`ValidKeyAmalgamation::for_signing`]: ValidKeyAmalgamation::for_signing()
1074 pub fn for_signing(self) -> Self {
1075 self.key_flags(KeyFlags::empty().set_signing())
1076 }
1077
1078 /// Returns authentication-capable keys.
1079 ///
1080 /// If you call this function (or one of `key_flags`,
1081 /// `for_certification`, etc.) multiple times, the
1082 /// *union* of the values is used.
1083 ///
1084 /// Refer to [`ValidKeyAmalgamation::for_authentication`] for
1085 /// additional details and caveats.
1086 ///
1087 /// # Examples
1088 ///
1089 /// ```
1090 /// # use sequoia_openpgp as openpgp;
1091 /// # use openpgp::cert::prelude::*;
1092 /// use openpgp::policy::StandardPolicy;
1093 ///
1094 /// # fn main() -> openpgp::Result<()> {
1095 /// let p = &StandardPolicy::new();
1096 ///
1097 /// # let (cert, _) = CertBuilder::new()
1098 /// # .add_authentication_subkey()
1099 /// # .add_certification_subkey()
1100 /// # .add_transport_encryption_subkey()
1101 /// # .add_storage_encryption_subkey()
1102 /// # .add_authentication_subkey()
1103 /// # .generate()?;
1104 /// # let mut i = 0;
1105 /// for ka in cert.keys()
1106 /// .with_policy(p, None)
1107 /// .for_authentication()
1108 /// {
1109 /// // Valid authentication-capable keys.
1110 /// # i += 1;
1111 /// }
1112 /// # assert_eq!(i, 2);
1113 /// # Ok(()) }
1114 /// ```
1115 ///
1116 /// [`ValidKeyAmalgamation::for_authentication`]: ValidKeyAmalgamation::for_authentication()
1117 pub fn for_authentication(self) -> Self {
1118 self.key_flags(KeyFlags::empty().set_authentication())
1119 }
1120
1121 /// Returns encryption-capable keys for data at rest.
1122 ///
1123 /// If you call this function (or one of `key_flags`,
1124 /// `for_certification`, etc.) multiple times, the
1125 /// *union* of the values is used.
1126 ///
1127 /// Refer to [`ValidKeyAmalgamation::for_storage_encryption`] for
1128 /// additional details and caveats.
1129 ///
1130 /// # Examples
1131 ///
1132 /// ```
1133 /// # use sequoia_openpgp as openpgp;
1134 /// # use openpgp::cert::prelude::*;
1135 /// use openpgp::policy::StandardPolicy;
1136 ///
1137 /// # fn main() -> openpgp::Result<()> {
1138 /// let p = &StandardPolicy::new();
1139 ///
1140 /// # let (cert, _) = CertBuilder::new()
1141 /// # .add_authentication_subkey()
1142 /// # .add_certification_subkey()
1143 /// # .add_transport_encryption_subkey()
1144 /// # .add_storage_encryption_subkey()
1145 /// # .add_authentication_subkey()
1146 /// # .generate()?;
1147 /// # let mut i = 0;
1148 /// for ka in cert.keys()
1149 /// .with_policy(p, None)
1150 /// .for_storage_encryption()
1151 /// {
1152 /// // Valid encryption-capable keys for data at rest.
1153 /// # i += 1;
1154 /// }
1155 /// # assert_eq!(i, 1);
1156 /// # Ok(()) }
1157 /// ```
1158 ///
1159 /// [`ValidKeyAmalgamation::for_storage_encryption`]: ValidKeyAmalgamation::for_storage_encryption()
1160 pub fn for_storage_encryption(self) -> Self {
1161 self.key_flags(KeyFlags::empty().set_storage_encryption())
1162 }
1163
1164 /// Returns encryption-capable keys for data in transit.
1165 ///
1166 /// If you call this function (or one of `key_flags`,
1167 /// `for_certification`, etc.) multiple times, the
1168 /// *union* of the values is used.
1169 ///
1170 /// Refer to [`ValidKeyAmalgamation::for_transport_encryption`] for
1171 /// additional details and caveats.
1172 ///
1173 /// # Examples
1174 ///
1175 /// ```
1176 /// # use sequoia_openpgp as openpgp;
1177 /// # use openpgp::cert::prelude::*;
1178 /// use openpgp::policy::StandardPolicy;
1179 ///
1180 /// # fn main() -> openpgp::Result<()> {
1181 /// let p = &StandardPolicy::new();
1182 ///
1183 /// # let (cert, _) = CertBuilder::new()
1184 /// # .add_authentication_subkey()
1185 /// # .add_certification_subkey()
1186 /// # .add_transport_encryption_subkey()
1187 /// # .add_transport_encryption_subkey()
1188 /// # .add_authentication_subkey()
1189 /// # .generate()?;
1190 /// # let mut i = 0;
1191 /// for ka in cert.keys()
1192 /// .with_policy(p, None)
1193 /// .for_transport_encryption()
1194 /// {
1195 /// // Valid encryption-capable keys for data in transit.
1196 /// # i += 1;
1197 /// }
1198 /// # assert_eq!(i, 2);
1199 /// # Ok(()) }
1200 /// ```
1201 ///
1202 /// [`ValidKeyAmalgamation::for_transport_encryption`]: ValidKeyAmalgamation::for_transport_encryption()
1203 pub fn for_transport_encryption(self) -> Self {
1204 self.key_flags(KeyFlags::empty().set_transport_encryption())
1205 }
1206
1207 /// Returns keys that are alive.
1208 ///
1209 /// A `ValidKeyAmalgamation` is guaranteed to have a live *binding
1210 /// signature*. This is independent of whether the *key* is live,
1211 /// or the *certificate* is live, i.e., if you care about those
1212 /// things, you need to check them too.
1213 ///
1214 /// For a definition of liveness, see the [`key_alive`] method.
1215 ///
1216 /// # Examples
1217 ///
1218 /// ```
1219 /// # use sequoia_openpgp as openpgp;
1220 /// # use openpgp::cert::prelude::*;
1221 /// use openpgp::policy::StandardPolicy;
1222 ///
1223 /// # fn main() -> openpgp::Result<()> {
1224 /// let p = &StandardPolicy::new();
1225 ///
1226 /// # let (cert, _) = CertBuilder::new()
1227 /// # .add_authentication_subkey()
1228 /// # .add_certification_subkey()
1229 /// # .add_transport_encryption_subkey()
1230 /// # .add_transport_encryption_subkey()
1231 /// # .add_authentication_subkey()
1232 /// # .generate()?;
1233 /// for ka in cert.keys()
1234 /// .with_policy(p, None)
1235 /// .alive()
1236 /// {
1237 /// // ka is alive.
1238 /// }
1239 /// # Ok(()) }
1240 /// ```
1241 ///
1242 /// [`key_alive`]: crate::packet::signature::subpacket::SubpacketAreas::key_alive()
1243 pub fn alive(mut self) -> Self
1244 {
1245 self.alive = Some(());
1246 self
1247 }
1248
1249 /// Returns keys based on their revocation status.
1250 ///
1251 /// A value of `None` disables this filter.
1252 ///
1253 /// If you call this function multiple times on the same
1254 /// `ValidKeyAmalgamationIter`, only the last value is used.
1255 ///
1256 /// This filter checks the key's revocation status; it does
1257 /// not check the certificate's revocation status.
1258 ///
1259 /// This filter only checks whether the key has no valid-self
1260 /// revocations at the specified time. It does not check
1261 /// third-party revocations.
1262 ///
1263 /// # Examples
1264 ///
1265 /// ```
1266 /// # use sequoia_openpgp as openpgp;
1267 /// # use openpgp::cert::prelude::*;
1268 /// use openpgp::policy::StandardPolicy;
1269 ///
1270 /// # fn main() -> openpgp::Result<()> {
1271 /// let p = &StandardPolicy::new();
1272 ///
1273 /// # let (cert, _) = CertBuilder::new()
1274 /// # .add_authentication_subkey()
1275 /// # .add_certification_subkey()
1276 /// # .add_transport_encryption_subkey()
1277 /// # .add_transport_encryption_subkey()
1278 /// # .add_authentication_subkey()
1279 /// # .generate()?;
1280 /// for ka in cert.keys()
1281 /// .with_policy(p, None)
1282 /// .revoked(false)
1283 /// {
1284 /// // ka has no self-revocations; recall: this filter doesn't check
1285 /// // third-party revocations.
1286 /// }
1287 /// # Ok(()) }
1288 /// ```
1289 ///
1290 /// This filter checks whether a key's revocation status is
1291 /// `RevocationStatus::Revoked` or not.
1292 /// `ValidKeyAmalgamationIter::revoked(false)` is equivalent to:
1293 ///
1294 /// ```rust
1295 /// # use sequoia_openpgp as openpgp;
1296 /// # use openpgp::Result;
1297 /// use openpgp::types::RevocationStatus;
1298 /// # use openpgp::cert::prelude::*;
1299 /// use openpgp::policy::StandardPolicy;
1300 ///
1301 /// # fn main() -> Result<()> {
1302 /// # let (cert, _) =
1303 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1304 /// # .generate()?;
1305 /// let p = &StandardPolicy::new();
1306 ///
1307 /// # let timestamp = None;
1308 /// let non_revoked_keys = cert
1309 /// .keys()
1310 /// .with_policy(p, timestamp)
1311 /// .filter(|ka| {
1312 /// match ka.revocation_status() {
1313 /// RevocationStatus::Revoked(_) =>
1314 /// // It's definitely revoked, skip it.
1315 /// false,
1316 /// RevocationStatus::CouldBe(_) =>
1317 /// // There is a designated revoker that we
1318 /// // could check, but don't (or can't). To
1319 /// // avoid a denial-of-service attack arising from
1320 /// // fake revocations, we assume that the key has
1321 /// // not been revoked and return it.
1322 /// true,
1323 /// RevocationStatus::NotAsFarAsWeKnow =>
1324 /// // We have no evidence to suggest that the key
1325 /// // is revoked.
1326 /// true,
1327 /// }
1328 /// })
1329 /// .map(|ka| ka.key())
1330 /// .collect::<Vec<_>>();
1331 /// # Ok(())
1332 /// # }
1333 /// ```
1334 ///
1335 /// As the example shows, this filter is significantly less
1336 /// flexible than using `KeyAmalgamation::revocation_status`.
1337 /// However, this filter implements a typical policy, and does not
1338 /// preclude using something like `Iter::filter` to implement
1339 /// alternative policies.
1340 pub fn revoked<T>(mut self, revoked: T) -> Self
1341 where T: Into<Option<bool>>
1342 {
1343 self.revoked = revoked.into();
1344 self
1345 }
1346
1347 /// Changes the iterator to only return keys with secret key
1348 /// material.
1349 ///
1350 /// # Examples
1351 ///
1352 /// ```rust
1353 /// # use sequoia_openpgp as openpgp;
1354 /// # use openpgp::Result;
1355 /// # use openpgp::cert::prelude::*;
1356 /// use openpgp::policy::StandardPolicy;
1357 ///
1358 /// # fn main() -> Result<()> {
1359 /// let p = &StandardPolicy::new();
1360 ///
1361 /// # let (cert, _) =
1362 /// # CertBuilder::new().set_password(Some("password".into()))
1363 /// # .generate()?;
1364 /// for ka in cert.keys().with_policy(p, None).secret() {
1365 /// // Use it.
1366 /// }
1367 /// # assert!(cert.keys().with_policy(p, None).secret().count() == 1);
1368 /// #
1369 /// # let (cert, _) = CertBuilder::new().generate()?;
1370 /// # assert!(cert.keys().with_policy(p, None).secret().count() == 1);
1371 /// # Ok(())
1372 /// # }
1373 /// ```
1374 pub fn secret(self) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1375 ValidKeyAmalgamationIter {
1376 cert: self.cert,
1377 primary: self.primary,
1378 subkey_iter: self.subkey_iter,
1379
1380 time: self.time,
1381 policy: self.policy,
1382
1383 // The filters.
1384 encrypted_secret: Some(true),
1385 unencrypted_secret: Some(true),
1386 key_handles: self.key_handles,
1387 supported: self.supported,
1388 flags: self.flags,
1389 alive: self.alive,
1390 revoked: self.revoked,
1391
1392 _p: std::marker::PhantomData,
1393 _r: std::marker::PhantomData,
1394 }
1395 }
1396
1397 /// Changes the iterator to only return keys with encrypted secret key
1398 /// material.
1399 ///
1400 /// # Examples
1401 ///
1402 /// ```rust
1403 /// # use sequoia_openpgp as openpgp;
1404 /// # use openpgp::Result;
1405 /// # use openpgp::cert::prelude::*;
1406 /// use openpgp::policy::StandardPolicy;
1407 ///
1408 /// # fn main() -> Result<()> {
1409 /// let p = &StandardPolicy::new();
1410 ///
1411 /// # let (cert, _) =
1412 /// # CertBuilder::new().set_password(Some("password".into()))
1413 /// # .generate()?;
1414 /// for ka in cert.keys().with_policy(p, None).encrypted_secret() {
1415 /// // Use it.
1416 /// }
1417 /// # assert!(cert.keys().with_policy(p, None).encrypted_secret().count() == 1);
1418 /// # Ok(())
1419 /// # }
1420 /// ```
1421 pub fn encrypted_secret(
1422 self,
1423 ) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1424 ValidKeyAmalgamationIter {
1425 cert: self.cert,
1426 primary: self.primary,
1427 subkey_iter: self.subkey_iter,
1428
1429 time: self.time,
1430 policy: self.policy,
1431
1432 // The filters.
1433 encrypted_secret: Some(true),
1434 unencrypted_secret: self.unencrypted_secret,
1435 key_handles: self.key_handles,
1436 supported: self.supported,
1437 flags: self.flags,
1438 alive: self.alive,
1439 revoked: self.revoked,
1440
1441 _p: std::marker::PhantomData,
1442 _r: std::marker::PhantomData,
1443 }
1444 }
1445
1446 /// Changes the iterator to only return keys with unencrypted
1447 /// secret key material.
1448 ///
1449 /// # Examples
1450 ///
1451 /// ```rust
1452 /// # use sequoia_openpgp as openpgp;
1453 /// # use openpgp::Result;
1454 /// # use openpgp::cert::prelude::*;
1455 /// use openpgp::policy::StandardPolicy;
1456 ///
1457 /// # fn main() -> Result<()> {
1458 /// let p = &StandardPolicy::new();
1459 ///
1460 /// # let (cert, _) = CertBuilder::new().generate()?;
1461 /// for ka in cert.keys().with_policy(p, None).unencrypted_secret() {
1462 /// // Use it.
1463 /// }
1464 /// # assert!(cert.keys().with_policy(p, None).unencrypted_secret().count() == 1);
1465 /// # Ok(())
1466 /// # }
1467 /// ```
1468 pub fn unencrypted_secret(self) -> ValidKeyAmalgamationIter<'a, key::SecretParts, R> {
1469 ValidKeyAmalgamationIter {
1470 cert: self.cert,
1471 primary: self.primary,
1472 subkey_iter: self.subkey_iter,
1473
1474 time: self.time,
1475 policy: self.policy,
1476
1477 // The filters.
1478 encrypted_secret: self.encrypted_secret,
1479 unencrypted_secret: Some(true),
1480 key_handles: self.key_handles,
1481 supported: self.supported,
1482 flags: self.flags,
1483 alive: self.alive,
1484 revoked: self.revoked,
1485
1486 _p: std::marker::PhantomData,
1487 _r: std::marker::PhantomData,
1488 }
1489 }
1490
1491 /// Changes the iterator to only return a key if it matches one of
1492 /// the specified `KeyHandle`s.
1493 ///
1494 /// This function is cumulative. If you call this function (or
1495 /// [`key_handles`]) multiple times, then the iterator returns a
1496 /// key if it matches *any* of the specified [`KeyHandle`s].
1497 ///
1498 /// This function uses [`KeyHandle::aliases`] to compare key
1499 /// handles.
1500 ///
1501 /// # Examples
1502 ///
1503 /// ```rust
1504 /// # use sequoia_openpgp as openpgp;
1505 /// # use openpgp::Result;
1506 /// # use openpgp::cert::prelude::*;
1507 /// use openpgp::policy::StandardPolicy;
1508 ///
1509 /// # fn main() -> Result<()> {
1510 /// let p = &StandardPolicy::new();
1511 ///
1512 /// # let (cert, _) =
1513 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1514 /// # .generate()?;
1515 /// # let key_handle = cert.primary_key().key().key_handle();
1516 /// # let mut i = 0;
1517 /// for ka in cert.keys().with_policy(p, None).key_handle(key_handle) {
1518 /// // Use it.
1519 /// # i += 1;
1520 /// }
1521 /// # assert_eq!(i, 1);
1522 /// # Ok(())
1523 /// # }
1524 /// ```
1525 ///
1526 /// [`KeyHandle`s]: super::super::super::KeyHandle
1527 /// [`key_handles`]: ValidKeyAmalgamationIter::key_handles()
1528 /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
1529 pub fn key_handle<H>(mut self, h: H) -> Self
1530 where H: Into<KeyHandle>
1531 {
1532 self.key_handles.push(h.into());
1533 self
1534 }
1535
1536 /// Changes the iterator to only return a key if it matches one of
1537 /// the specified `KeyHandle`s.
1538 ///
1539 /// If the given `handles` iterator is empty, the set of returned
1540 /// keys is not constrained.
1541 ///
1542 /// This function is cumulative. If you call this function (or
1543 /// [`key_handle`]) multiple times, then the iterator returns a key
1544 /// if it matches *any* of the specified [`KeyHandle`s].
1545 ///
1546 /// This function uses [`KeyHandle::aliases`] to compare key
1547 /// handles.
1548 ///
1549 /// # Examples
1550 ///
1551 /// ```rust
1552 /// # use sequoia_openpgp as openpgp;
1553 /// # use openpgp::Result;
1554 /// # use openpgp::cert::prelude::*;
1555 /// use openpgp::policy::StandardPolicy;
1556 ///
1557 /// # fn main() -> Result<()> {
1558 /// let p = &StandardPolicy::new();
1559 ///
1560 /// # let (cert, _) =
1561 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1562 /// # .generate()?;
1563 /// # let key_handles = &[cert.primary_key().key().key_handle()][..];
1564 /// # let mut i = 0;
1565 /// for ka in cert.keys().with_policy(p, None).key_handles(key_handles) {
1566 /// // Use it.
1567 /// # i += 1;
1568 /// }
1569 /// # assert_eq!(i, 1);
1570 /// # Ok(())
1571 /// # }
1572 /// ```
1573 ///
1574 /// [`KeyHandle`s]: super::super::super::KeyHandle
1575 /// [`key_handle`]: KeyAmalgamationIter::key_handle()
1576 /// [`KeyHandle::aliases`]: super::super::super::KeyHandle::aliases()
1577 pub fn key_handles<H, K>(mut self, handles: H) -> Self
1578 where
1579 H: IntoIterator<Item=K>,
1580 K: Borrow<KeyHandle>,
1581 {
1582 let mut handles = handles.into_iter()
1583 .map(|h| h.borrow().clone())
1584 .collect::<Vec<_>>();
1585
1586 self.key_handles.append(&mut handles);
1587 self
1588 }
1589
1590 /// Changes the iterator to only return a key if it is supported
1591 /// by Sequoia's cryptographic backend.
1592 ///
1593 /// Which public key encryption algorithms Sequoia supports
1594 /// depends on the cryptographic backend selected at compile time.
1595 /// This filter makes sure that only supported keys are returned.
1596 ///
1597 /// # Examples
1598 ///
1599 /// ```rust
1600 /// # fn main() -> sequoia_openpgp::Result<()> {
1601 /// # use sequoia_openpgp as openpgp;
1602 /// # use openpgp::cert::prelude::*;
1603 /// # let (cert, _) =
1604 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1605 /// # .generate()?;
1606 /// # let mut i = 0;
1607 /// use openpgp::policy::StandardPolicy;
1608 ///
1609 /// let p = &StandardPolicy::new();
1610 ///
1611 /// for ka in cert.keys().with_policy(p, None).supported() {
1612 /// // Use it.
1613 /// # i += 1;
1614 /// }
1615 /// # assert_eq!(i, 3);
1616 /// # Ok(()) }
1617 /// ```
1618 pub fn supported(mut self) -> Self {
1619 self.supported = Some(true);
1620 self
1621 }
1622
1623 /// Changes the iterator to skip the primary key.
1624 ///
1625 /// This also changes the iterator's return type. Instead of
1626 /// returning a [`ValidErasedKeyAmalgamation`], it returns a
1627 /// [`ValidSubordinateKeyAmalgamation`].
1628 ///
1629 /// # Examples
1630 ///
1631 /// ```
1632 /// # use sequoia_openpgp as openpgp;
1633 /// # use openpgp::cert::prelude::*;
1634 /// use openpgp::policy::StandardPolicy;
1635 ///
1636 /// # fn main() -> openpgp::Result<()> {
1637 /// let p = &StandardPolicy::new();
1638 ///
1639 /// # let (cert, _) = CertBuilder::new()
1640 /// # .add_signing_subkey()
1641 /// # .add_certification_subkey()
1642 /// # .add_transport_encryption_subkey()
1643 /// # .add_storage_encryption_subkey()
1644 /// # .add_authentication_subkey()
1645 /// # .generate()?;
1646 /// # let mut i = 0;
1647 /// for ka in cert.keys().with_policy(p, None).subkeys() {
1648 /// assert!(! ka.primary());
1649 /// # i += 1;
1650 /// }
1651 /// # assert_eq!(cert.keys().count(), 6);
1652 /// # assert_eq!(i, 5);
1653 /// # Ok(()) }
1654 /// ```
1655 ///
1656 pub fn subkeys(self) -> ValidKeyAmalgamationIter<'a, P, key::SubordinateRole> {
1657 ValidKeyAmalgamationIter {
1658 cert: self.cert,
1659 primary: true,
1660 subkey_iter: self.subkey_iter,
1661
1662 time: self.time,
1663 policy: self.policy,
1664
1665 // The filters.
1666 encrypted_secret: self.encrypted_secret,
1667 unencrypted_secret: self.unencrypted_secret,
1668 key_handles: self.key_handles,
1669 supported: self.supported,
1670 flags: self.flags,
1671 alive: self.alive,
1672 revoked: self.revoked,
1673
1674 _p: std::marker::PhantomData,
1675 _r: std::marker::PhantomData,
1676 }
1677 }
1678}
1679
1680#[cfg(test)]
1681mod test {
1682 use super::*;
1683 use crate::{
1684 parse::Parse,
1685 cert::builder::CertBuilder,
1686 };
1687 use crate::policy::StandardPolicy as P;
1688
1689 #[test]
1690 fn key_iter_test() {
1691 let key = Cert::from_bytes(crate::tests::key("neal.pgp")).unwrap();
1692 assert_eq!(1 + key.subkeys().count(),
1693 key.keys().count());
1694 }
1695
1696 #[test]
1697 fn select_no_keys() {
1698 let p = &P::new();
1699 let (cert, _) = CertBuilder::new()
1700 .generate().unwrap();
1701 let flags = KeyFlags::empty().set_transport_encryption();
1702
1703 assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 0);
1704 }
1705
1706 #[test]
1707 fn select_valid_and_right_flags() {
1708 let p = &P::new();
1709 let (cert, _) = CertBuilder::new()
1710 .add_transport_encryption_subkey()
1711 .generate().unwrap();
1712 let flags = KeyFlags::empty().set_transport_encryption();
1713
1714 assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
1715 }
1716
1717 #[test]
1718 fn select_valid_and_wrong_flags() {
1719 let p = &P::new();
1720 let (cert, _) = CertBuilder::new()
1721 .add_transport_encryption_subkey()
1722 .add_signing_subkey()
1723 .generate().unwrap();
1724 let flags = KeyFlags::empty().set_transport_encryption();
1725
1726 assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(), 1);
1727 }
1728
1729 #[test]
1730 fn select_invalid_and_right_flags() {
1731 let p = &P::new();
1732 let (cert, _) = CertBuilder::new()
1733 .add_transport_encryption_subkey()
1734 .generate().unwrap();
1735 let flags = KeyFlags::empty().set_transport_encryption();
1736
1737 let now = crate::now()
1738 - std::time::Duration::new(52 * 7 * 24 * 60 * 60, 0);
1739 assert_eq!(cert.keys().with_policy(p, now).key_flags(flags).alive().count(),
1740 0);
1741 }
1742
1743 #[test]
1744 fn select_primary() {
1745 let p = &P::new();
1746 let (cert, _) = CertBuilder::new()
1747 .add_certification_subkey()
1748 .generate().unwrap();
1749 let flags = KeyFlags::empty().set_certification();
1750
1751 assert_eq!(cert.keys().with_policy(p, None).key_flags(flags).count(),
1752 2);
1753 }
1754
1755 #[test]
1756 fn selectors() {
1757 let p = &P::new();
1758 let (cert, _) = CertBuilder::new()
1759 .add_signing_subkey()
1760 .add_certification_subkey()
1761 .add_transport_encryption_subkey()
1762 .add_storage_encryption_subkey()
1763 .add_authentication_subkey()
1764 .generate().unwrap();
1765 assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1766 .for_certification().count(),
1767 2);
1768 assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1769 .for_transport_encryption().count(),
1770 1);
1771 assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1772 .for_storage_encryption().count(),
1773 1);
1774
1775 assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1776 .for_signing().count(),
1777 1);
1778 assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
1779 .key_flags(KeyFlags::empty().set_authentication())
1780 .count(),
1781 1);
1782 }
1783
1784 #[test]
1785 fn select_key_handle() {
1786 let p = &P::new();
1787
1788 let (cert, _) = CertBuilder::new()
1789 .add_signing_subkey()
1790 .add_certification_subkey()
1791 .add_transport_encryption_subkey()
1792 .add_storage_encryption_subkey()
1793 .add_authentication_subkey()
1794 .generate().unwrap();
1795
1796 let keys = cert.keys().count();
1797 assert_eq!(keys, 6);
1798
1799 let keyids = cert.keys().map(|ka| ka.key().keyid()).collect::<Vec<_>>();
1800
1801 fn check(got: &[KeyHandle], expected: &[KeyHandle]) {
1802 if expected.len() != got.len() {
1803 panic!("Got {}, expected {} handles",
1804 got.len(), expected.len());
1805 }
1806
1807 for (g, e) in got.iter().zip(expected.iter()) {
1808 if !e.aliases(g) {
1809 panic!(" Got: {:?}\nExpected: {:?}",
1810 got, expected);
1811 }
1812 }
1813 }
1814
1815 for i in 1..keys {
1816 for keyids in keyids[..].windows(i) {
1817 let keyids : Vec<KeyHandle>
1818 = keyids.iter().map(Into::into).collect();
1819 assert_eq!(keyids.len(), i);
1820
1821 check(
1822 &cert.keys().key_handles(keyids.iter())
1823 .map(|ka| ka.key().key_handle())
1824 .collect::<Vec<KeyHandle>>(),
1825 &keyids);
1826 check(
1827 &cert.keys().with_policy(p, None).key_handles(keyids.iter())
1828 .map(|ka| ka.key().key_handle())
1829 .collect::<Vec<KeyHandle>>(),
1830 &keyids);
1831 check(
1832 &cert.keys().key_handles(keyids.iter()).with_policy(p, None)
1833 .map(|ka| ka.key().key_handle())
1834 .collect::<Vec<KeyHandle>>(),
1835 &keyids);
1836 }
1837 }
1838 }
1839
1840 #[test]
1841 #[allow(deprecated)]
1842 fn select_supported() -> crate::Result<()> {
1843 use crate::types::PublicKeyAlgorithm;
1844 if ! PublicKeyAlgorithm::DSA.is_supported()
1845 || PublicKeyAlgorithm::ElGamalEncrypt.is_supported()
1846 {
1847 return Ok(()); // Skip on this backend.
1848 }
1849
1850 let cert =
1851 Cert::from_bytes(crate::tests::key("dsa2048-elgamal3072.pgp"))?;
1852 assert_eq!(cert.keys().count(), 2);
1853 assert_eq!(cert.keys().supported().count(), 1);
1854 let p = unsafe { &crate::policy::NullPolicy::new() };
1855 assert_eq!(cert.keys().with_policy(p, None).count(), 2);
1856 assert_eq!(cert.keys().with_policy(p, None).supported().count(), 1);
1857 Ok(())
1858 }
1859}