sequoia_openpgp/cert/
bindings.rs

1use std::time;
2
3use crate::Error;
4use crate::Result;
5use crate::Cert;
6use crate::types::{HashAlgorithm, SignatureType};
7use crate::crypto::Signer;
8use crate::packet::{UserID, UserAttribute, key, Key, signature, Signature};
9
10impl<P: key::KeyParts> Key<P, key::SubordinateRole> {
11    /// Creates a binding signature.
12    ///
13    /// The signature binds this subkey to `cert`. `signer` will be used
14    /// to create a signature using `signature` as builder.
15    /// The`hash_algo` defaults to SHA512, `creation_time` to the
16    /// current time.
17    ///
18    /// Note that subkeys with signing capabilities need a [primary
19    /// key binding signature].  If you are creating this binding
20    /// signature from a previous binding signature, you can reuse the
21    /// primary key binding signature if it is still valid and meets
22    /// current algorithm requirements.  Otherwise, you can create one
23    /// using [`SignatureBuilder::sign_primary_key_binding`].
24    ///
25    ///   [primary key binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
26    ///   [`SignatureBuilder::sign_primary_key_binding`]: signature::SignatureBuilder::sign_primary_key_binding()
27    ///
28    /// This function adds a creation time subpacket, an issuer
29    /// fingerprint subpacket, and an issuer subpacket to the
30    /// signature.
31    ///
32    /// # Examples
33    ///
34    /// This example demonstrates how to bind this key to a Cert.  Note
35    /// that in general, the `CertBuilder` is a better way to add
36    /// subkeys to a Cert.
37    ///
38    /// ```
39    /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*};
40    /// # fn main() -> Result<()> {
41    /// use sequoia_openpgp::policy::StandardPolicy;
42    /// let p = &StandardPolicy::new();
43    ///
44    /// // Generate a Cert, and create a keypair from the primary key.
45    /// let (cert, _) = CertBuilder::new().generate()?;
46    /// let mut keypair = cert.primary_key().key().clone()
47    ///     .parts_into_secret()?.into_keypair()?;
48    ///
49    /// // Let's add an encryption subkey.
50    /// let flags = KeyFlags::empty().set_storage_encryption();
51    /// assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
52    ///                .key_flags(&flags).count(),
53    ///            0);
54    ///
55    /// // Generate a subkey and a binding signature.
56    /// let subkey: Key<_, key::SubordinateRole> =
57    ///     Key6::generate_ecc(false, Curve::Cv25519)?
58    ///     .into();
59    /// let builder = signature::SignatureBuilder::new(SignatureType::SubkeyBinding)
60    ///     .set_key_flags(flags.clone())?;
61    /// let binding = subkey.bind(&mut keypair, &cert, builder)?;
62    ///
63    /// // Now merge the key and binding signature into the Cert.
64    /// let cert = cert.insert_packets(vec![Packet::from(subkey),
65    ///                                    binding.into()])?.0;
66    ///
67    /// // Check that we have an encryption subkey.
68    /// assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
69    ///                .key_flags(flags).count(),
70    ///            1);
71    /// # Ok(()) }
72    pub fn bind(&self, signer: &mut dyn Signer, cert: &Cert,
73                signature: signature::SignatureBuilder)
74        -> Result<Signature>
75    {
76        signature.sign_subkey_binding(
77            signer, cert.primary_key().key(), self)
78    }
79}
80
81impl UserID {
82    /// Creates a binding signature.
83    ///
84    /// The signature binds this User ID to `cert`. `signer` will be used
85    /// to create a signature using `signature` as builder.
86    /// The`hash_algo` defaults to SHA512, `creation_time` to the
87    /// current time.
88    ///
89    /// This function adds a creation time subpacket, an issuer
90    /// fingerprint subpacket, and an issuer subpacket to the
91    /// signature.
92    ///
93    /// # Examples
94    ///
95    /// This example demonstrates how to bind this User ID to a Cert.
96    /// Note that in general, the `CertBuilder` is a better way to add
97    /// User IDs to a Cert.
98    ///
99    /// ```
100    /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*};
101    /// # fn main() -> Result<()> {
102    /// // Generate a Cert, and create a keypair from the primary key.
103    /// let (cert, _) = CertBuilder::new().generate()?;
104    /// let mut keypair = cert.primary_key().key().clone()
105    ///     .parts_into_secret()?.into_keypair()?;
106    /// assert_eq!(cert.userids().len(), 0);
107    ///
108    /// // Generate a User ID and a binding signature.
109    /// let userid = UserID::from("test@example.org");
110    /// let builder =
111    ///     signature::SignatureBuilder::new(SignatureType::PositiveCertification);
112    /// let binding = userid.bind(&mut keypair, &cert, builder)?;
113    ///
114    /// // Now merge the User ID and binding signature into the Cert.
115    /// let cert = cert.insert_packets(vec![Packet::from(userid),
116    ///                                    binding.into()])?.0;
117    ///
118    /// // Check that we have a User ID.
119    /// assert_eq!(cert.userids().len(), 1);
120    /// # Ok(()) }
121    pub fn bind(&self, signer: &mut dyn Signer, cert: &Cert,
122                signature: signature::SignatureBuilder)
123                -> Result<Signature>
124    {
125        signature.sign_userid_binding(
126            signer, cert.primary_key().key(), self)
127    }
128
129    /// Returns a certification for the User ID.
130    ///
131    /// The signature binds this User ID to `cert`. `signer` will be
132    /// used to create a certification signature of type
133    /// `signature_type`.  `signature_type` defaults to
134    /// `SignatureType::GenericCertification`, `hash_algo` to SHA512,
135    /// `creation_time` to the current time.
136    ///
137    /// This function adds a creation time subpacket, an issuer
138    /// fingerprint subpacket, and an issuer subpacket to the
139    /// signature.
140    ///
141    /// # Errors
142    ///
143    /// Returns `Error::InvalidArgument` if `signature_type` is not
144    /// one of `SignatureType::{Generic, Persona, Casual,
145    /// Positive}Certification`
146    ///
147    /// # Examples
148    ///
149    /// This example demonstrates how to certify a User ID.
150    ///
151    /// ```
152    /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*};
153    /// # fn main() -> Result<()> {
154    /// // Generate a Cert, and create a keypair from the primary key.
155    /// let (alice, _) = CertBuilder::new()
156    ///     .set_primary_key_flags(KeyFlags::empty().set_certification())
157    ///     .add_userid("alice@example.org")
158    ///     .generate()?;
159    /// let mut keypair = alice.primary_key().key().clone()
160    ///     .parts_into_secret()?.into_keypair()?;
161    ///
162    /// // Generate a Cert for Bob.
163    /// let (bob, _) = CertBuilder::new()
164    ///     .set_primary_key_flags(KeyFlags::empty().set_certification())
165    ///     .add_userid("bob@example.org")
166    ///     .generate()?;
167    ///
168    /// // Alice now certifies the binding between `bob@example.org` and `bob`.
169    /// let certification =
170    ///     bob.userids().nth(0).unwrap()
171    ///     .userid()
172    ///     .certify(&mut keypair, &bob, SignatureType::PositiveCertification,
173    ///              None, None)?;
174    ///
175    /// // `certification` can now be used, e.g. by merging it into `bob`.
176    /// let bob = bob.insert_packets(certification)?.0;
177    ///
178    /// // Check that we have a certification on the User ID.
179    /// assert_eq!(bob.userids().nth(0).unwrap()
180    ///            .certifications().count(), 1);
181    /// # Ok(()) }
182    pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert,
183                            signature_type: S,
184                            hash_algo: H, creation_time: T)
185        -> Result<Signature>
186        where S: Into<Option<SignatureType>>,
187              H: Into<Option<HashAlgorithm>>,
188              T: Into<Option<time::SystemTime>>
189    {
190        let typ = signature_type.into();
191        let typ = match typ {
192            Some(SignatureType::GenericCertification)
193                | Some(SignatureType::PersonaCertification)
194                | Some(SignatureType::CasualCertification)
195                | Some(SignatureType::PositiveCertification) => typ.unwrap(),
196            Some(t) => return Err(Error::InvalidArgument(
197                format!("Invalid signature type: {}", t)).into()),
198            None => SignatureType::GenericCertification,
199        };
200        let mut sig = signature::SignatureBuilder::new(typ);
201        if let Some(algo) = hash_algo.into() {
202            sig = sig.set_hash_algo(algo);
203        }
204        if let Some(creation_time) = creation_time.into() {
205            sig = sig.set_signature_creation_time(creation_time)?;
206        }
207        self.bind(signer, cert, sig)
208    }
209}
210
211impl UserAttribute {
212    /// Creates a binding signature.
213    ///
214    /// The signature binds this user attribute to `cert`. `signer`
215    /// will be used to create a signature using `signature` as
216    /// builder.  The`hash_algo` defaults to SHA512, `creation_time`
217    /// to the current time.
218    ///
219    /// This function adds a creation time subpacket, an issuer
220    /// fingerprint subpacket, and an issuer subpacket to the
221    /// signature.
222    ///
223    /// # Examples
224    ///
225    /// This example demonstrates how to bind this user attribute to a
226    /// Cert.  Note that in general, the `CertBuilder` is a better way
227    /// to add User IDs to a Cert.
228    ///
229    /// ```
230    /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*,
231    /// #                       packet::user_attribute::*};
232    /// # fn main() -> Result<()> {
233    /// // Generate a Cert, and create a keypair from the primary key.
234    /// let (cert, _) = CertBuilder::new()
235    ///     .generate()?;
236    /// let mut keypair = cert.primary_key().key().clone()
237    ///     .parts_into_secret()?.into_keypair()?;
238    /// assert_eq!(cert.userids().len(), 0);
239    ///
240    /// // Generate a user attribute and a binding signature.
241    /// let user_attr = UserAttribute::new(&[
242    ///     Subpacket::Image(
243    ///         Image::Private(100, vec![0, 1, 2].into_boxed_slice())),
244    /// ])?;
245    /// let builder =
246    ///     signature::SignatureBuilder::new(SignatureType::PositiveCertification);
247    /// let binding = user_attr.bind(&mut keypair, &cert, builder)?;
248    ///
249    /// // Now merge the user attribute and binding signature into the Cert.
250    /// let cert = cert.insert_packets(vec![Packet::from(user_attr),
251    ///                                    binding.into()])?.0;
252    ///
253    /// // Check that we have a user attribute.
254    /// assert_eq!(cert.user_attributes().count(), 1);
255    /// # Ok(()) }
256    pub fn bind(&self, signer: &mut dyn Signer, cert: &Cert,
257                signature: signature::SignatureBuilder)
258        -> Result<Signature>
259    {
260        signature.sign_user_attribute_binding(
261            signer, cert.primary_key().key(), self)
262    }
263
264    /// Returns a certification for the user attribute.
265    ///
266    /// The signature binds this user attribute to `cert`. `signer` will be
267    /// used to create a certification signature of type
268    /// `signature_type`.  `signature_type` defaults to
269    /// `SignatureType::GenericCertification`, `hash_algo` to SHA512,
270    /// `creation_time` to the current time.
271    ///
272    /// This function adds a creation time subpacket, an issuer
273    /// fingerprint subpacket, and an issuer subpacket to the
274    /// signature.
275    ///
276    /// # Errors
277    ///
278    /// Returns `Error::InvalidArgument` if `signature_type` is not
279    /// one of `SignatureType::{Generic, Persona, Casual,
280    /// Positive}Certification`
281    ///
282    /// # Examples
283    ///
284    /// This example demonstrates how to certify a User ID.
285    ///
286    /// ```
287    /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*,
288    /// #                       packet::user_attribute::*};
289    /// # fn main() -> Result<()> {
290    /// // Generate a Cert, and create a keypair from the primary key.
291    /// let (alice, _) = CertBuilder::new()
292    ///     .add_userid("alice@example.org")
293    ///     .generate()?;
294    /// let mut keypair = alice.primary_key().key().clone()
295    ///     .parts_into_secret()?.into_keypair()?;
296    ///
297    /// // Generate a Cert for Bob.
298    /// let user_attr = UserAttribute::new(&[
299    ///     Subpacket::Image(
300    ///         Image::Private(100, vec![0, 1, 2].into_boxed_slice())),
301    /// ])?;
302    /// let (bob, _) = CertBuilder::new()
303    ///     .set_primary_key_flags(KeyFlags::empty().set_certification())
304    ///     .add_user_attribute(user_attr)
305    ///     .generate()?;
306    ///
307    /// // Alice now certifies the binding between `bob@example.org` and `bob`.
308    /// let certification =
309    ///     bob.user_attributes().nth(0).unwrap()
310    ///     .user_attribute()
311    ///     .certify(&mut keypair, &bob, SignatureType::PositiveCertification,
312    ///              None, None)?;
313    ///
314    /// // `certification` can now be used, e.g. by merging it into `bob`.
315    /// let bob = bob.insert_packets(certification)?.0;
316    ///
317    /// // Check that we have a certification on the User ID.
318    /// assert_eq!(bob.user_attributes().nth(0).unwrap()
319    ///            .certifications().count(),
320    ///            1);
321    /// # Ok(()) }
322    pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert,
323                            signature_type: S,
324                            hash_algo: H, creation_time: T)
325        -> Result<Signature>
326        where S: Into<Option<SignatureType>>,
327              H: Into<Option<HashAlgorithm>>,
328              T: Into<Option<time::SystemTime>>
329    {
330        let typ = signature_type.into();
331        let typ = match typ {
332            Some(SignatureType::GenericCertification)
333                | Some(SignatureType::PersonaCertification)
334                | Some(SignatureType::CasualCertification)
335                | Some(SignatureType::PositiveCertification) => typ.unwrap(),
336            Some(t) => return Err(Error::InvalidArgument(
337                format!("Invalid signature type: {}", t)).into()),
338            None => SignatureType::GenericCertification,
339        };
340        let mut sig = signature::SignatureBuilder::new(typ);
341        if let Some(algo) = hash_algo.into() {
342            sig = sig.set_hash_algo(algo);
343        }
344        if let Some(creation_time) = creation_time.into() {
345            sig = sig.set_signature_creation_time(creation_time)?;
346        }
347        self.bind(signer, cert, sig)
348    }
349}