sequoia_openpgp/serialize/
cert.rs

1use std::{
2    borrow::Cow,
3};
4
5use crate::Result;
6use crate::cert::prelude::*;
7use crate::packet::{
8    header::BodyLength,
9    key,
10    Key,
11    Signature,
12    Tag,
13};
14use crate::seal;
15use crate::serialize::{
16    PacketRef,
17    Marshal, MarshalInto,
18    NetLength,
19    generic_serialize_into, generic_export_into,
20};
21
22
23impl Cert {
24    /// Returns whether the certificate should be exported.
25    ///
26    /// A certificate should only be exported if it has at least one
27    /// exportable direct key signature, or there is at least one user
28    /// ID with at least one exportable self signature.
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// use sequoia_openpgp as openpgp;
34    /// use openpgp::cert::prelude::*;
35    ///
36    /// # fn main() -> openpgp::Result<()> {
37    /// // By default, certificates are exportable.
38    /// let (cert, _) =
39    ///     CertBuilder::general_purpose(Some("alice@example.org"))
40    ///         .generate()?;
41    /// assert!(cert.exportable());
42    ///
43    /// // Setting the exportable flag to false makes them
44    /// // not-exportable.
45    /// let (cert, _) =
46    ///     CertBuilder::general_purpose(Some("alice@example.org"))
47    ///         .set_exportable(false)
48    ///         .generate()?;
49    /// assert!(! cert.exportable());
50    /// # Ok(())
51    /// # }
52    /// ```
53    pub fn exportable(&self) -> bool {
54        let pk = self.primary_key();
55
56        if pk.self_signatures().chain(pk.self_revocations())
57            .any(|sig| sig.exportable().is_ok())
58        {
59            // Exportable direct key signature.  Export it.
60            true
61        } else if self.userids().any(|userid| {
62            userid.self_signatures()
63                .chain(userid.self_revocations())
64                .any(|sig| sig.exportable().is_ok())
65        }) {
66            // User ID with exportable self signature.  Export it.
67            true
68        } else if self.user_attributes().any(|ua| {
69            ua.self_signatures()
70                .chain(ua.self_revocations())
71                .any(|sig| sig.exportable().is_ok())
72        }) {
73            // User attribute with exportable self signature.  Export
74            // it.
75            true
76        } else {
77            // Don't export it.
78            false
79        }
80    }
81
82    /// Serializes or exports the Cert.
83    ///
84    /// If `export` is true, then non-exportable signatures are not
85    /// written, and components without any exportable binding
86    /// signature or revocation are not exported.
87    ///
88    /// The signatures are ordered from authenticated and most
89    /// important to not authenticated and most likely to be abused.
90    /// The order is:
91    ///
92    ///   - Self revocations first.  They are authenticated and the
93    ///     most important information.
94    ///   - Self signatures.  They are authenticated.
95    ///   - Other signatures.  They are not authenticated at this point.
96    ///   - Other revocations.  They are not authenticated, and likely
97    ///     not well-supported in other implementations, hence the
98    ///     least reliable way of revoking keys and therefore least
99    ///     useful and most likely to be abused.
100    fn serialize_common(&self, o: &mut dyn std::io::Write, export: bool)
101                        -> Result<()>
102    {
103        if export && ! self.exportable() {
104            return Ok(())
105        }
106
107        let primary = self.primary_key();
108        PacketRef::PublicKey(primary.key())
109            .serialize(o)?;
110
111        // Writes a signature if it is exportable or `! export`.
112        let serialize_sig =
113            |o: &mut dyn std::io::Write, sig: &Signature| -> Result<()>
114        {
115            if export {
116                if sig.exportable().is_ok() {
117                    PacketRef::Signature(sig).export(o)?;
118                }
119            } else {
120                PacketRef::Signature(sig).serialize(o)?;
121            }
122            Ok(())
123        };
124
125        for s in primary.signatures() {
126            serialize_sig(o, s)?;
127        }
128
129        for u in self.userids() {
130            if export && ! u.self_signatures().chain(u.self_revocations()).any(
131                |s| s.exportable().is_ok())
132            {
133                // No exportable selfsig on this component, skip it.
134                continue;
135            }
136
137            PacketRef::UserID(u.userid()).serialize(o)?;
138            for s in u.signatures() {
139                serialize_sig(o, s)?;
140            }
141        }
142
143        for u in self.user_attributes() {
144            if export && ! u.self_signatures().chain(u.self_revocations()).any(
145                |s| s.exportable().is_ok())
146            {
147                // No exportable selfsig on this component, skip it.
148                continue;
149            }
150
151            PacketRef::UserAttribute(u.user_attribute()).serialize(o)?;
152            for s in u.signatures() {
153                serialize_sig(o, s)?;
154            }
155        }
156
157        for k in self.keys().subkeys() {
158            if export && ! k.self_signatures().chain(k.self_revocations()).any(
159                |s| s.exportable().is_ok())
160            {
161                // No exportable selfsig on this component, skip it.
162                continue;
163            }
164
165            PacketRef::PublicSubkey(k.key()).serialize(o)?;
166            for s in k.signatures() {
167                serialize_sig(o, s)?;
168            }
169        }
170
171        for u in self.unknowns() {
172            if export && ! u.certifications().any(
173                |s| s.exportable().is_ok())
174            {
175                // No exportable selfsig on this component, skip it.
176                continue;
177            }
178
179            PacketRef::Unknown(u.unknown()).serialize(o)?;
180
181            for s in u.signatures() {
182                serialize_sig(o, s)?;
183            }
184        }
185
186        for s in self.bad_signatures() {
187            serialize_sig(o, s)?;
188        }
189
190        Ok(())
191    }
192}
193
194impl crate::serialize::Serialize for Cert {}
195
196impl seal::Sealed for Cert {}
197impl Marshal for Cert {
198    fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
199        self.serialize_common(o, false)
200    }
201
202    fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
203        self.serialize_common(o, true)
204    }
205}
206
207impl crate::serialize::SerializeInto for Cert {}
208
209impl MarshalInto for Cert {
210    fn serialized_len(&self) -> usize {
211        let mut l = 0;
212        let primary = self.primary_key();
213        l += PacketRef::PublicKey(primary.key()).serialized_len();
214
215        for s in primary.signatures() {
216            l += PacketRef::Signature(s).serialized_len();
217        }
218
219        for u in self.userids() {
220            l += PacketRef::UserID(u.userid()).serialized_len();
221
222            for s in u.signatures() {
223                l += PacketRef::Signature(s).serialized_len();
224            }
225        }
226
227        for u in self.user_attributes() {
228            l += PacketRef::UserAttribute(u.user_attribute()).serialized_len();
229
230            for s in u.signatures() {
231                l += PacketRef::Signature(s).serialized_len();
232            }
233        }
234
235        for k in self.keys().subkeys() {
236            l += PacketRef::PublicSubkey(k.key()).serialized_len();
237
238            for s in k.signatures() {
239                l += PacketRef::Signature(s).serialized_len();
240            }
241        }
242
243        for u in self.unknowns() {
244            l += PacketRef::Unknown(u.unknown()).serialized_len();
245
246            for s in u.signatures() {
247                l += PacketRef::Signature(s).serialized_len();
248            }
249        }
250
251        for s in self.bad_signatures() {
252            l += PacketRef::Signature(s).serialized_len();
253        }
254
255        l
256    }
257
258    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
259        generic_serialize_into(self, self.serialized_len(), buf)
260    }
261
262    fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
263        generic_export_into(self, self.serialized_len(), buf)
264    }
265}
266
267impl Cert {
268    /// Derive a [`TSK`] object from this key.
269    ///
270    /// This object writes out secret keys during serialization.
271    ///
272    /// [`TSK`]: crate::serialize::TSK
273    pub fn as_tsk(&self) -> TSK {
274        TSK::new(self)
275    }
276
277    /// Derive a [`TSK`] object from this key that owns the `Cert`.
278    ///
279    /// This object writes out secret keys during serialization.
280    ///
281    /// [`TSK`]: crate::serialize::TSK
282    pub fn into_tsk(self) -> TSK<'static> {
283        TSK::from(self)
284    }
285}
286
287/// A reference to a `Cert` that allows serialization of secret keys.
288///
289/// To avoid accidental leakage, secret keys are not serialized when a
290/// serializing a [`Cert`].  To serialize [`Cert`]s with secret keys,
291/// use [`Cert::as_tsk()`] to create a `TSK`, which is a shim on top
292/// of the `Cert`, and serialize this.
293///
294/// [`Cert`]: crate::cert::Cert
295/// [`Cert::as_tsk()`]: crate::cert::Cert::as_tsk()
296///
297/// # Examples
298///
299/// ```
300/// # use sequoia_openpgp::{*, cert::*, parse::Parse, serialize::Serialize};
301/// # fn main() -> Result<()> {
302/// let (cert, _) = CertBuilder::new().generate()?;
303/// assert!(cert.is_tsk());
304///
305/// let mut buf = Vec::new();
306/// cert.as_tsk().serialize(&mut buf)?;
307///
308/// let cert_ = Cert::from_bytes(&buf)?;
309/// assert!(cert_.is_tsk());
310/// assert_eq!(cert, cert_);
311/// # Ok(()) }
312/// ```
313pub struct TSK<'a> {
314    pub(crate) cert: Cow<'a, Cert>,
315    filter: Box<dyn Fn(&key::UnspecifiedSecret) -> bool + Send + Sync + 'a>,
316    emit_stubs: bool,
317}
318
319impl PartialEq for TSK<'_> {
320    fn eq(&self, other: &Self) -> bool {
321        // First, compare the certs.  If they are not equal, then the
322        // TSK's cannot possibly be equal.
323        if self.cert != other.cert {
324            return false;
325        }
326
327        // Second, consider all the keys.
328        for (a, b) in self.cert.keys()
329            .zip(other.cert.keys())
330        {
331            match (a.has_secret()
332                   && (self.filter)(a.key().parts_as_secret().expect("has secret")),
333                   b.has_secret()
334                   && (other.filter)(b.key().parts_as_secret().expect("has_secret")))
335            {
336                // Both have secrets.  Compare secrets.
337                (true, true) => if a.key().optional_secret() != b.key().optional_secret() {
338                    return false;
339                },
340                // No secrets.  Equal iff both or neither emit stubs.
341                (false, false) => if self.emit_stubs != other.emit_stubs {
342                    return false;
343                },
344                // Otherwise, they differ.
345                _ => return false,
346            }
347        }
348
349        // Everything matched.
350        true
351    }
352}
353
354impl From<Cert> for TSK<'_> {
355    fn from(c: Cert) -> Self {
356        Self {
357            cert: Cow::Owned(c),
358            filter: Box::new(|_| true),
359            emit_stubs: false,
360        }
361    }
362}
363
364impl<'a> TSK<'a> {
365    /// Creates a new view for the given `Cert`.
366    fn new(cert: &'a Cert) -> Self {
367        Self {
368            cert: Cow::Borrowed(cert),
369            filter: Box::new(|_| true),
370            emit_stubs: false,
371        }
372    }
373
374    /// Decomposes the TSK.
375    pub(crate) fn decompose(self)
376                            -> (Cow<'a, Cert>,
377                                Box<dyn Fn(&key::UnspecifiedSecret) -> bool + Send + Sync + 'a>,
378                                bool)
379    {
380        (self.cert, self.filter, self.emit_stubs)
381    }
382
383    /// Returns whether we're emitting secret (sub)key packets when
384    /// serializing.
385    ///
386    /// Computes whether we have secrets, taking the filter into
387    /// account, and whether we are emitting stubs.  This can be used
388    /// to determine the correct armor label to use.
389    pub(crate) fn emits_secret_key_packets(&self) -> bool {
390        self.emit_stubs
391            || self.cert.keys().secret().any(|skb| (self.filter)(skb.key()))
392    }
393
394    /// Filters which secret keys to export using the given predicate.
395    ///
396    /// Note that the given filter replaces any existing filter.
397    ///
398    /// # Examples
399    ///
400    /// This example demonstrates how to create a TSK with a detached
401    /// primary secret key.
402    ///
403    /// ```
404    /// # use sequoia_openpgp::{*, cert::*, parse::Parse, serialize::Serialize};
405    /// use sequoia_openpgp::policy::StandardPolicy;
406    ///
407    /// # fn main() -> Result<()> {
408    /// let p = &StandardPolicy::new();
409    ///
410    /// let (cert, _) = CertBuilder::new().add_signing_subkey().generate()?;
411    /// assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false).secret().count(), 2);
412    ///
413    /// // Only write out the subkey's secret.
414    /// let mut buf = Vec::new();
415    /// cert.as_tsk()
416    ///     .set_filter(|k| k.fingerprint() != cert.fingerprint())
417    ///     .serialize(&mut buf)?;
418    ///
419    /// let cert_ = Cert::from_bytes(&buf)?;
420    /// assert!(! cert_.primary_key().key().has_secret());
421    /// assert_eq!(cert_.keys().with_policy(p, None).alive().revoked(false).secret().count(), 1);
422    /// # Ok(()) }
423    /// ```
424    pub fn set_filter<P>(mut self, predicate: P) -> Self
425        where P: Fn(&key::UnspecifiedSecret)-> bool + Send + Sync + 'a
426    {
427        self.filter = Box::new(predicate);
428        self
429    }
430
431    /// Changes `TSK` to emit secret key stubs.
432    ///
433    /// If [`TSK::set_filter`] is used to selectively export secret
434    /// keys, or if the cert contains both keys without secret key
435    /// material and with secret key material, then are two ways to
436    /// serialize this cert.  Neither is sanctioned by the OpenPGP
437    /// standard.
438    ///
439    /// The default way is to simply emit public key packets when no
440    /// secret key material is available.  While straight forward,
441    /// this may be in violation of [Section 10.2 of RFC 9580].
442    ///
443    /// The alternative is to emit a secret key packet with a
444    /// placeholder secret key value.  GnuPG uses this variant with a
445    /// private [`S2K`] format.  If interoperability with GnuPG is a
446    /// concern, use this variant.
447    ///
448    /// See [this test] for support in other implementations.
449    ///
450    ///   [`TSK::set_filter`]: TSK::set_filter()
451    ///   [Section 10.2 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-10.2
452    ///   [`S2K`]: super::crypto::S2K
453    ///   [this test]: https://tests.sequoia-pgp.org/#Detached_primary_key
454    ///
455    /// # Examples
456    ///
457    /// This example demonstrates how to create a TSK with a detached
458    /// primary secret key, serializing it using secret key stubs.
459    ///
460    /// ```
461    /// # fn main() -> sequoia_openpgp::Result<()> {
462    /// # use std::convert::TryFrom;
463    /// use sequoia_openpgp as openpgp;
464    /// use openpgp::packet::key::*;
465    /// # use openpgp::{types::*, crypto::S2K};
466    /// # use openpgp::{*, cert::*, parse::Parse, serialize::Serialize};
467    ///
468    /// let p = &openpgp::policy::StandardPolicy::new();
469    ///
470    /// let (cert, _) = CertBuilder::new().add_signing_subkey().generate()?;
471    /// assert_eq!(cert.keys().with_policy(p, None)
472    ///            .alive().revoked(false).unencrypted_secret().count(), 2);
473    ///
474    /// // Only write out the subkey's secret, the primary key is "detached".
475    /// let mut buf = Vec::new();
476    /// cert.as_tsk()
477    ///     .set_filter(|k| k.fingerprint() != cert.fingerprint())
478    ///     .emit_secret_key_stubs(true)
479    ///     .serialize(&mut buf)?;
480    ///
481    /// # let pp = PacketPile::from_bytes(&buf)?;
482    /// # assert_eq!(pp.path_ref(&[0]).unwrap().kind(),
483    /// #            Some(packet::Tag::SecretKey));
484    /// let cert_ = Cert::from_bytes(&buf)?;
485    /// // The primary key has an "encrypted" stub.
486    /// assert!(cert_.primary_key().key().has_secret());
487    /// assert_eq!(cert_.keys().with_policy(p, None)
488    ///            .alive().revoked(false).unencrypted_secret().count(), 1);
489    /// # if let Some(SecretKeyMaterial::Encrypted(sec)) =
490    /// #     cert_.primary_key().key().optional_secret()
491    /// # {
492    /// #     assert_eq!(sec.algo(), SymmetricAlgorithm::Unencrypted);
493    /// #     if let S2K::Private { tag, .. } = sec.s2k() {
494    /// #         assert_eq!(*tag, 101);
495    /// #     } else {
496    /// #         panic!("expected proprietary S2K type");
497    /// #     }
498    /// # } else {
499    /// #     panic!("expected ''encrypted'' secret key stub");
500    /// # }
501    /// # Ok(()) }
502    /// ```
503    pub fn emit_secret_key_stubs(mut self, emit_stubs: bool) -> Self {
504        self.emit_stubs = emit_stubs;
505        self
506    }
507
508    /// Adds a GnuPG-style secret key stub to the key.
509    pub(crate) fn add_stub<P, R>(key: Key<P, R>) -> key::UnspecifiedSecret
510    where
511        P: key::KeyParts,
512        R: key::KeyRole,
513    {
514        Self::add_stub_internal(key.parts_into_unspecified()
515                                .role_into_unspecified())
516    }
517
518
519    /// Adds a GnuPG-style secret key stub to the key.
520    pub(crate) fn add_stub_internal(key: key::UnspecifiedKey) -> key::UnspecifiedSecret
521    {
522
523        // Emit a GnuPG-style secret key stub.
524        let stub = crate::crypto::S2K::Private {
525            tag: 101,
526            parameters: Some(vec![
527                0,    // "hash algo"
528                0x47, // 'G'
529                0x4e, // 'N'
530                0x55, // 'U'
531                1     // "mode"
532            ].into()),
533        };
534        key.add_secret(key::SecretKeyMaterial::Encrypted(
535            key::Encrypted::new(
536                stub, 0.into(),
537                // Mirrors more closely what GnuPG 2.1
538                // does (oddly, GnuPG 1.4 emits 0xfe
539                // here).
540                Some(crate::crypto::mpi::SecretKeyChecksum::Sum16),
541                vec![].into())))
542            .0.into()
543    }
544
545    /// Serializes or exports the Cert.
546    ///
547    /// If `export` is true, then non-exportable signatures are not
548    /// written, and components without any exportable binding
549    /// signature or revocation are not exported.
550    fn serialize_common(&self, o: &mut dyn std::io::Write, export: bool)
551                        -> Result<()>
552    {
553        // Writes a signature if it is exportable or `! export`.
554        let serialize_sig =
555            |o: &mut dyn std::io::Write, sig: &Signature| -> Result<()>
556        {
557            if export {
558                if sig.exportable().is_ok() {
559                    PacketRef::Signature(sig).export(o)?;
560                }
561            } else {
562                PacketRef::Signature(sig).serialize(o)?;
563            }
564            Ok(())
565        };
566
567        // Serializes public or secret key depending on the filter.
568        let serialize_key =
569            |o: &mut dyn std::io::Write, key: &'a key::UnspecifiedKey,
570             tag_public, tag_secret|
571        {
572            // We check for secrets here.
573            let tag = if key.has_secret()
574                && (self.filter)(key.try_into().expect("checked for secrets"))
575            {
576                tag_secret
577            } else {
578                tag_public
579            };
580
581            if self.emit_stubs && (tag == Tag::PublicKey
582                                   || tag == Tag::PublicSubkey) {
583                let key_with_stub = Self::add_stub(key.clone());
584                return match tag {
585                    Tag::PublicKey =>
586                        crate::Packet::SecretKey(key_with_stub.into())
587                            .serialize(o),
588                    Tag::PublicSubkey =>
589                        crate::Packet::SecretSubkey(key_with_stub.into())
590                            .serialize(o),
591                    _ => unreachable!(),
592                };
593            }
594
595            match tag {
596                Tag::PublicKey =>
597                    PacketRef::PublicKey(key.into()).serialize(o),
598                Tag::PublicSubkey =>
599                    PacketRef::PublicSubkey(key.into()).serialize(o),
600                Tag::SecretKey => {
601                    PacketRef::SecretKey(
602                        key.try_into().expect("checked for secrets"))
603                        .serialize(o)
604                }
605                Tag::SecretSubkey => {
606                    PacketRef::SecretSubkey(
607                        key.try_into().expect("checked for secrets"))
608                    .serialize(o)
609                }
610                _ => unreachable!(),
611            }
612        };
613
614        if export && ! self.cert.exportable() {
615            return Ok(())
616        }
617
618        let primary = self.cert.primary_key();
619        serialize_key(o, primary.key().into(),
620                      Tag::PublicKey, Tag::SecretKey)?;
621
622        for s in primary.signatures() {
623            serialize_sig(o, s)?;
624        }
625
626        for u in self.cert.userids() {
627            if export && ! u.self_signatures().chain(u.self_revocations()).any(
628                |s| s.exportable().is_ok())
629            {
630                // No exportable selfsig on this component, skip it.
631                continue;
632            }
633
634            PacketRef::UserID(u.userid()).serialize(o)?;
635            for s in u.signatures() {
636                serialize_sig(o, s)?;
637            }
638        }
639
640        for u in self.cert.user_attributes() {
641            if export && ! u.self_signatures().chain(u.self_revocations()).any(
642                |s| s.exportable().is_ok())
643            {
644                // No exportable selfsig on this component, skip it.
645                continue;
646            }
647
648            PacketRef::UserAttribute(u.user_attribute()).serialize(o)?;
649            for s in u.signatures() {
650                serialize_sig(o, s)?;
651            }
652        }
653
654        for k in self.cert.keys().subkeys() {
655            if export && ! k.self_signatures().chain(k.self_revocations()).any(
656                |s| s.exportable().is_ok())
657            {
658                // No exportable selfsig on this component, skip it.
659                continue;
660            }
661
662            serialize_key(o, k.key().into(),
663                          Tag::PublicSubkey, Tag::SecretSubkey)?;
664            for s in k.signatures() {
665                serialize_sig(o, s)?;
666            }
667        }
668
669        for u in self.cert.unknowns() {
670            if export && ! u.certifications().any(
671                |s| s.exportable().is_ok())
672            {
673                // No exportable selfsig on this component, skip it.
674                continue;
675            }
676
677            PacketRef::Unknown(u.unknown()).serialize(o)?;
678
679            for s in u.signatures() {
680                serialize_sig(o, s)?;
681            }
682        }
683
684        for s in self.cert.bad_signatures() {
685            serialize_sig(o, s)?;
686        }
687
688        Ok(())
689    }
690}
691
692impl<'a> crate::serialize::Serialize for TSK<'a> {}
693
694impl<'a> seal::Sealed for TSK<'a> {}
695impl<'a> Marshal for TSK<'a> {
696    fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
697        self.serialize_common(o, false)
698    }
699
700    fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
701        self.serialize_common(o, true)
702    }
703}
704
705impl<'a> crate::serialize::SerializeInto for TSK<'a> {}
706
707impl<'a> MarshalInto for TSK<'a> {
708    fn serialized_len(&self) -> usize {
709        let mut l = 0;
710
711        // Serializes public or secret key depending on the filter.
712        let serialized_len_key
713            = |key: &'a key::UnspecifiedKey, tag_public, tag_secret|
714        {
715            // We check for secrets here.
716            let tag = if key.has_secret() && (self.filter)(key.try_into().expect("have secrets")) {
717                tag_secret
718            } else {
719                tag_public
720            };
721
722            if self.emit_stubs && (tag == Tag::PublicKey
723                                   || tag == Tag::PublicSubkey) {
724                // Emit a GnuPG-style secret key stub.  The stub
725                // extends the public key by 8 bytes (plus 4 secret
726                // length octets for v6).
727                let l = key.parts_as_public().net_len()
728                    + match key.version() {
729                        4 => 8,
730                        6 => 12,
731                        _ => 0, // Serialization will fail anyway.
732                    };
733                return 1 // CTB
734                    + BodyLength::Full(l as u32).serialized_len()
735                    + l;
736            }
737
738            let packet = match tag {
739                Tag::PublicKey => PacketRef::PublicKey(key.into()),
740                Tag::PublicSubkey => PacketRef::PublicSubkey(key.into()),
741                Tag::SecretKey => {
742                    PacketRef::SecretKey(
743                        key.try_into().expect("checked for secrets"))
744                }
745                Tag::SecretSubkey => {
746                    PacketRef::SecretSubkey(
747                        key.try_into().expect("checked for secrets"))
748                }
749                _ => unreachable!(),
750            };
751
752            packet.serialized_len()
753        };
754
755        let primary = self.cert.primary_key();
756        l += serialized_len_key(primary.key().into(),
757                                Tag::PublicKey, Tag::SecretKey);
758
759        for s in primary.signatures() {
760            l += PacketRef::Signature(s).serialized_len();
761        }
762
763        for u in self.cert.userids() {
764            l += PacketRef::UserID(u.userid()).serialized_len();
765
766            for s in u.signatures() {
767                l += PacketRef::Signature(s).serialized_len();
768            }
769        }
770
771        for u in self.cert.user_attributes() {
772            l += PacketRef::UserAttribute(u.user_attribute()).serialized_len();
773
774            for s in u.signatures() {
775                l += PacketRef::Signature(s).serialized_len();
776            }
777        }
778
779        for k in self.cert.keys().subkeys() {
780            l += serialized_len_key(k.key().into(),
781                                    Tag::PublicSubkey, Tag::SecretSubkey);
782
783            for s in k.signatures() {
784                l += PacketRef::Signature(s).serialized_len();
785            }
786        }
787
788        for u in self.cert.unknowns() {
789            l += PacketRef::Unknown(u.unknown()).serialized_len();
790
791            for s in u.signatures() {
792                l += PacketRef::Signature(s).serialized_len();
793            }
794        }
795
796        for s in self.cert.bad_signatures() {
797            l += PacketRef::Signature(s).serialized_len();
798        }
799
800        l
801    }
802
803    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
804        generic_serialize_into(self, self.serialized_len(), buf)
805    }
806
807    fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
808        generic_export_into(self, self.serialized_len(), buf)
809    }
810}
811
812#[cfg(test)]
813mod test {
814    use super::*;
815    use crate::vec_truncate;
816    use crate::parse::Parse;
817    use crate::packet::key;
818    use crate::policy::StandardPolicy as P;
819
820    /// Demonstrates that public keys and all components are
821    /// serialized.
822    #[test]
823    fn roundtrip_cert() {
824        for test in crate::tests::CERTS {
825            let cert = match Cert::from_bytes(test.bytes) {
826                Ok(t) => t,
827                Err(_) => continue,
828            };
829            assert!(! cert.is_tsk());
830            let buf = cert.as_tsk().to_vec().unwrap();
831            let cert_ = Cert::from_bytes(&buf).unwrap();
832
833            assert_eq!(cert, cert_, "roundtripping {}.pgp failed", test);
834        }
835    }
836
837    /// Demonstrates that secret keys and all components are
838    /// serialized.
839    #[test]
840    fn roundtrip_tsk() {
841        for test in crate::tests::TSKS {
842            let cert = Cert::from_bytes(test.bytes).unwrap();
843            assert!(cert.is_tsk());
844
845            let mut buf = Vec::new();
846            cert.as_tsk().serialize(&mut buf).unwrap();
847            let cert_ = Cert::from_bytes(&buf).unwrap();
848
849            assert_eq!(cert, cert_, "roundtripping {}-private.pgp failed", test);
850
851            // This time, use a trivial filter.
852            let mut buf = Vec::new();
853            cert.as_tsk().set_filter(|_| true).serialize(&mut buf).unwrap();
854            let cert_ = Cert::from_bytes(&buf).unwrap();
855
856            assert_eq!(cert, cert_, "roundtripping {}-private.pgp failed", test);
857        }
858    }
859
860    /// Demonstrates that TSK::serialize() with the right filter
861    /// reduces to Cert::serialize().
862    #[test]
863    fn reduce_to_cert_serialize() {
864        for test in crate::tests::TSKS {
865            let cert = Cert::from_bytes(test.bytes).unwrap();
866            assert!(cert.is_tsk());
867
868            // First, use Cert::serialize().
869            let mut buf_cert = Vec::new();
870            cert.serialize(&mut buf_cert).unwrap();
871
872            // When serializing using TSK::serialize, filter out all
873            // secret keys.
874            let mut buf_tsk = Vec::new();
875            cert.as_tsk().set_filter(|_| false).serialize(&mut buf_tsk).unwrap();
876
877            // Check for equality.
878            let cert_ = Cert::from_bytes(&buf_cert).unwrap();
879            let tsk_ = Cert::from_bytes(&buf_tsk).unwrap();
880            assert_eq!(cert_, tsk_,
881                       "reducing failed on {}-private.pgp: not Cert::eq",
882                       test);
883
884            // Check for identinty.
885            assert_eq!(buf_cert, buf_tsk,
886                       "reducing failed on {}-private.pgp: serialized identity",
887                       test);
888        }
889    }
890
891    #[test]
892    fn export() {
893        use crate::Packet;
894        use crate::cert::prelude::*;
895        use crate::types::{Curve, KeyFlags, SignatureType};
896        use crate::packet::{
897            signature, UserID, user_attribute::{UserAttribute, Subpacket},
898            key::Key6,
899        };
900
901        let p = &P::new();
902
903        let (cert, _) = CertBuilder::new().generate().unwrap();
904        let mut keypair = cert.primary_key().key().clone().parts_into_secret()
905            .unwrap().into_keypair().unwrap();
906
907        let key: key::SecretSubkey =
908            Key6::generate_ecc(false, Curve::Cv25519).unwrap().into();
909        let key_binding = key.bind(
910            &mut keypair, &cert,
911            signature::SignatureBuilder::new(SignatureType::SubkeyBinding)
912                .set_key_flags(
913                    KeyFlags::empty().set_transport_encryption())
914                .unwrap()
915                .set_exportable_certification(false).unwrap()).unwrap();
916
917        let uid = UserID::from("foo");
918        let uid_binding = uid.bind(
919            &mut keypair, &cert,
920            signature::SignatureBuilder::from(
921                cert.primary_key().with_policy(p, None).unwrap()
922                    .direct_key_signature().unwrap().clone())
923                    .set_type(SignatureType::PositiveCertification)
924                    .preserve_signature_creation_time().unwrap()
925                    .set_exportable_certification(false).unwrap()).unwrap();
926
927        let ua = UserAttribute::new(&[
928            Subpacket::Unknown(2, b"foo".to_vec().into_boxed_slice()),
929        ]).unwrap();
930        let ua_binding = ua.bind(
931            &mut keypair, &cert,
932            signature::SignatureBuilder::from(
933                cert.primary_key().with_policy(p, None).unwrap()
934                    .direct_key_signature().unwrap().clone())
935                .set_type(SignatureType::PositiveCertification)
936                .preserve_signature_creation_time().unwrap()
937                .set_exportable_certification(false).unwrap()).unwrap();
938
939        let cert = cert.insert_packets(vec![
940            Packet::SecretSubkey(key), key_binding.into(),
941            uid.into(), uid_binding.into(),
942            ua.into(), ua_binding.into(),
943        ]).unwrap().0;
944
945        assert_eq!(cert.subkeys().count(), 1);
946        cert.subkeys().next().unwrap().binding_signature(p, None).unwrap();
947        assert_eq!(cert.userids().count(), 1);
948        assert!(cert.userids().with_policy(p, None).next().is_some());
949        assert_eq!(cert.user_attributes().count(), 1);
950        assert!(cert.user_attributes().with_policy(p, None).next().is_some());
951
952        // The binding signature is not exportable, so when we export
953        // and re-parse, we expect the userid to be gone.
954        let mut buf = Vec::new();
955        cert.export(&mut buf).unwrap();
956        let cert_ = Cert::from_bytes(&buf).unwrap();
957        assert_eq!(cert_.subkeys().count(), 0);
958        assert_eq!(cert_.userids().count(), 0);
959        assert_eq!(cert_.user_attributes().count(), 0);
960
961        let mut buf = vec![0; cert.serialized_len()];
962        let l = cert.export_into(&mut buf).unwrap();
963        vec_truncate(&mut buf, l);
964        let cert_ = Cert::from_bytes(&buf).unwrap();
965        assert_eq!(cert_.subkeys().count(), 0);
966        assert_eq!(cert_.userids().count(), 0);
967        assert_eq!(cert_.user_attributes().count(), 0);
968
969        let cert_ = Cert::from_bytes(&cert.export_to_vec().unwrap()).unwrap();
970        assert_eq!(cert_.subkeys().count(), 0);
971        assert_eq!(cert_.userids().count(), 0);
972        assert_eq!(cert_.user_attributes().count(), 0);
973
974        // Same, this time using the armor encoder.
975        let mut buf = Vec::new();
976        cert.armored().export(&mut buf).unwrap();
977        let cert_ = Cert::from_bytes(&buf).unwrap();
978        assert_eq!(cert_.subkeys().count(), 0);
979        assert_eq!(cert_.userids().count(), 0);
980        assert_eq!(cert_.user_attributes().count(), 0);
981
982        let mut buf = vec![0; cert.serialized_len()];
983        let l = cert.armored().export_into(&mut buf).unwrap();
984        vec_truncate(&mut buf, l);
985        let cert_ = Cert::from_bytes(&buf).unwrap();
986        assert_eq!(cert_.subkeys().count(), 0);
987        assert_eq!(cert_.userids().count(), 0);
988        assert_eq!(cert_.user_attributes().count(), 0);
989
990        let cert_ =
991            Cert::from_bytes(&cert.armored().export_to_vec().unwrap()).unwrap();
992        assert_eq!(cert_.subkeys().count(), 0);
993        assert_eq!(cert_.userids().count(), 0);
994        assert_eq!(cert_.user_attributes().count(), 0);
995
996        // Same, this time as TSKs.
997        let mut buf = Vec::new();
998        cert.as_tsk().export(&mut buf).unwrap();
999        let cert_ = Cert::from_bytes(&buf).unwrap();
1000        assert_eq!(cert_.subkeys().count(), 0);
1001        assert_eq!(cert_.userids().count(), 0);
1002        assert_eq!(cert_.user_attributes().count(), 0);
1003
1004        let mut buf = vec![0; cert.serialized_len()];
1005        let l = cert.as_tsk().export_into(&mut buf).unwrap();
1006        vec_truncate(&mut buf, l);
1007        let cert_ = Cert::from_bytes(&buf).unwrap();
1008        assert_eq!(cert_.subkeys().count(), 0);
1009        assert_eq!(cert_.userids().count(), 0);
1010        assert_eq!(cert_.user_attributes().count(), 0);
1011
1012        let cert_ =
1013            Cert::from_bytes(&cert.as_tsk().export_to_vec().unwrap()).unwrap();
1014        assert_eq!(cert_.subkeys().count(), 0);
1015        assert_eq!(cert_.userids().count(), 0);
1016        assert_eq!(cert_.user_attributes().count(), 0);
1017    }
1018
1019    /// Tests that GnuPG-style stubs are preserved when roundtripping.
1020    #[test]
1021    fn issue_613() -> Result<()> {
1022        use crate::packet::key::*;
1023        use crate::{types::*, crypto::S2K};
1024        use crate::{*, cert::*, parse::Parse};
1025        let p = &crate::policy::StandardPolicy::new();
1026
1027        let (cert, _) = CertBuilder::new().add_signing_subkey().generate()?;
1028        assert_eq!(cert.keys().with_policy(p, None)
1029                   .alive().revoked(false).unencrypted_secret().count(), 2);
1030
1031        // Only write out the subkey's secret, the primary key is "detached".
1032        let buf = cert.as_tsk()
1033            .set_filter(|k| k.fingerprint() != cert.fingerprint())
1034            .emit_secret_key_stubs(true)
1035            .to_vec()?;
1036
1037        // Try parsing it.
1038        let cert_ = Cert::from_bytes(&buf)?;
1039
1040        // The primary key has an "encrypted" stub.
1041        assert!(cert_.primary_key().has_secret());
1042        assert_eq!(cert_.keys().with_policy(p, None)
1043                   .alive().revoked(false).unencrypted_secret().count(), 1);
1044        if let Some(SecretKeyMaterial::Encrypted(sec)) =
1045            cert_.primary_key().key().optional_secret()
1046        {
1047            assert_eq!(sec.algo(), SymmetricAlgorithm::Unencrypted);
1048            if let S2K::Private { tag, .. } = sec.s2k() {
1049                assert_eq!(*tag, 101);
1050            } else {
1051                panic!("expected proprietary S2K type");
1052            }
1053        } else {
1054            panic!("expected ''encrypted'' secret key stub");
1055        }
1056
1057        // When roundtripping such a key, the stub should be preserved.
1058        let buf_ = cert_.as_tsk().to_vec()?;
1059        assert_eq!(buf, buf_);
1060        Ok(())
1061    }
1062
1063    /// Checks partial equality of certificates and TSKs.
1064    #[test]
1065    fn issue_701() -> Result<()> {
1066        let cert_0 = Cert::from_bytes(crate::tests::key("testy.pgp"))?;
1067        let cert_1 = Cert::from_bytes(crate::tests::key("testy.pgp"))?;
1068        let tsk_0 = Cert::from_bytes(crate::tests::key("testy-private.pgp"))?;
1069        let tsk_1 = Cert::from_bytes(crate::tests::key("testy-private.pgp"))?;
1070
1071        // We define equality by equality of the serialized form.
1072        // This macro checks that.
1073        macro_rules! check {
1074            ($a: expr, $b: expr, $expectation: expr) => {{
1075                let a = $a;
1076                let b = $b;
1077                let eq = a == b;
1078                let serialized_eq = a.to_vec()? == b.to_vec()?;
1079                let armored_eq = a.armored().to_vec()? == b.armored().to_vec()?;
1080                assert_eq!(serialized_eq, eq);
1081                assert_eq!(armored_eq, eq);
1082                assert_eq!(eq, $expectation);
1083            }};
1084        }
1085
1086        // Equal as certs, because equality is defined by equality of
1087        // the serialized form, and serializing a cert never writes
1088        // out any secrets.
1089        check!(&cert_0, &cert_1, true);
1090        check!(&cert_0, &tsk_0, true);
1091
1092        // Filters out secrets.
1093        let no_secrets = |_: &_| false;
1094
1095        // TSK's equality.
1096        check!(tsk_0.as_tsk(), tsk_1.as_tsk(), true);
1097
1098        // Without secrets.
1099        check!(tsk_0.as_tsk().set_filter(no_secrets),
1100               tsk_1.as_tsk().set_filter(no_secrets),
1101               true);
1102
1103        // Still equal if one uses stubs and the other one does not if
1104        // every key has a secret, i.e. stubs are not in fact used.
1105        check!(
1106            tsk_0.as_tsk().emit_secret_key_stubs(true),
1107            tsk_1.as_tsk(),
1108            true);
1109
1110        // No longer equal if one actually emits stubs.
1111        check!(
1112            tsk_0.as_tsk().emit_secret_key_stubs(true).set_filter(no_secrets),
1113            tsk_1.as_tsk(),
1114            false);
1115
1116        // Certs are not equal to TSKs, because here the secrets are
1117        // written out when serialized.
1118        check!(cert_0.as_tsk(), tsk_0.as_tsk(), false);
1119
1120        // Equal, if we filter out the secrets.
1121        check!(cert_0.as_tsk(),
1122               tsk_0.as_tsk().set_filter(no_secrets),
1123               true);
1124
1125        Ok(())
1126    }
1127
1128    #[test]
1129    fn issue_1075() -> Result<()> {
1130        let cert = Cert::from_bytes(crate::tests::key("testy.pgp"))?;
1131        let tsk = Cert::from_bytes(crate::tests::key("testy-private.pgp"))?;
1132
1133        // Filters out secrets.
1134        let no_secrets = |_: &_| false;
1135
1136        assert!(! cert.as_tsk().emits_secret_key_packets());
1137        assert!(cert.as_tsk().emit_secret_key_stubs(true)
1138                .emits_secret_key_packets());
1139        assert!(tsk.as_tsk().emits_secret_key_packets());
1140        assert!(! tsk.as_tsk().set_filter(no_secrets)
1141                .emits_secret_key_packets());
1142
1143        assert!(cert.armored().to_vec()? != tsk.as_tsk().armored().to_vec()?);
1144        assert_eq!(cert.armored().to_vec()?,
1145                   cert.as_tsk().armored().to_vec()?);
1146        assert_eq!(cert.armored().to_vec()?,
1147                   tsk.as_tsk().set_filter(no_secrets).armored().to_vec()?);
1148
1149        Ok(())
1150    }
1151
1152    #[test]
1153    fn into_packets() -> Result<()> {
1154        let cert = Cert::from_bytes(crate::tests::key("testy-private.pgp"))?;
1155
1156        fn t(tsk: TSK) {
1157            let a = tsk.to_vec().unwrap();
1158            let b = {
1159                let mut b = Vec::new();
1160                tsk.into_packets().for_each(|p| p.serialize(&mut b).unwrap());
1161                b
1162            };
1163            assert_eq!(a, b);
1164        }
1165
1166        let tsk = cert.clone().into_tsk();
1167        t(tsk);
1168
1169        let tsk = cert.clone().into_tsk().set_filter(|_| false);
1170        t(tsk);
1171
1172        let tsk = cert.clone().into_tsk()
1173            .set_filter(|k| k.fingerprint() == cert.fingerprint());
1174        t(tsk);
1175
1176        let tsk = cert.clone().into_tsk()
1177            .set_filter(|k| k.fingerprint() == cert.fingerprint())
1178            .emit_secret_key_stubs(true);
1179        t(tsk);
1180
1181        Ok(())
1182    }
1183}