sequoia_openpgp/packet/signature/subpacket.rs
1//! Signature subpackets.
2//!
3//! OpenPGP signature packets include a set of key-value attributes
4//! called subpackets. These subpackets are used to indicate when a
5//! signature was created, who created the signature, user &
6//! implementation preferences, etc. The full details are in [Section
7//! 5.2.3.7 of RFC 9580].
8//!
9//! [Section 5.2.3.7 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.7
10//!
11//! The standard assigns each subpacket a numeric id, and describes
12//! the format of its value. One subpacket is called Notation Data
13//! and is intended as a generic key-value store. The combined size
14//! of the subpackets (including notation data) is limited to 64 KB.
15//!
16//! Subpackets and notations can be marked as critical. If an OpenPGP
17//! implementation processes a packet that includes critical
18//! subpackets or notations that it does not understand, it is
19//! required to abort processing. This allows for forwards compatible
20//! changes by indicating whether it is safe to ignore an unknown
21//! subpacket or notation.
22//!
23//! A number of methods are defined on [`Signature`] for working with
24//! subpackets.
25//!
26//! [`Signature`]: super::super::Signature
27//!
28//! # Examples
29//!
30//! Print any Issuer Fingerprint subpackets:
31//!
32//! ```rust
33//! # use sequoia_openpgp as openpgp;
34//! # use openpgp::Result;
35//! # use openpgp::Packet;
36//! # use openpgp::parse::{Parse, PacketParserResult, PacketParser};
37//! #
38//! # f(include_bytes!("../../../tests/data/messages/signed.pgp"));
39//! #
40//! # fn f(message_data: &[u8]) -> Result<()> {
41//! let mut ppr = PacketParser::from_bytes(message_data)?;
42//! while let PacketParserResult::Some(mut pp) = ppr {
43//! if let Packet::Signature(ref sig) = pp.packet {
44//! for fp in sig.issuer_fingerprints() {
45//! eprintln!("Signature allegedly issued by: {}", fp.to_string());
46//! }
47//! }
48//!
49//! // Get the next packet.
50//! ppr = pp.recurse()?.1;
51//! }
52//! # Ok(())
53//! # }
54//! ```
55
56use std::cmp::Ordering;
57use std::convert::{TryInto, TryFrom};
58use std::hash::{Hash, Hasher};
59use std::ops::{Deref, DerefMut};
60use std::fmt;
61use std::cmp;
62use std::sync::atomic;
63use std::time;
64
65#[cfg(test)]
66use quickcheck::{Arbitrary, Gen};
67#[cfg(test)]
68use crate::packet::signature::ArbitraryBounded;
69
70use crate::{
71 Error,
72 Result,
73 packet::header::BodyLength,
74 packet::Signature,
75 packet::signature::{self, Signature4},
76 packet::key,
77 packet::Key,
78 Fingerprint,
79 KeyID,
80 serialize::MarshalInto,
81};
82use crate::types::{
83 AEADAlgorithm,
84 CompressionAlgorithm,
85 Duration,
86 Features,
87 HashAlgorithm,
88 KeyFlags,
89 KeyServerPreferences,
90 PublicKeyAlgorithm,
91 ReasonForRevocation,
92 RevocationKey,
93 SymmetricAlgorithm,
94 Timestamp,
95};
96
97/// The default amount of tolerance to use when comparing
98/// some timestamps.
99///
100/// Used by `Subpacket::signature_alive`.
101///
102/// When determining whether a timestamp generated on another
103/// machine is valid *now*, we need to account for clock skew.
104/// (Note: you don't normally need to consider clock skew when
105/// evaluating a signature's validity at some time in the past.)
106///
107/// We tolerate half an hour of skew based on the following
108/// anecdote: In 2019, a developer using Sequoia in a Windows VM
109/// running inside Virtual Box on Mac OS X reported that he
110/// typically observed a few minutes of clock skew and
111/// occasionally saw over 20 minutes of clock skew.
112///
113/// Note: when new messages override older messages, and their
114/// signatures are evaluated at some arbitrary point in time, an
115/// application may not see a consistent state if it uses a
116/// tolerance. Consider an application that has two messages and
117/// wants to get the current message at time te:
118///
119/// - t0: message 0
120/// - te: "get current message"
121/// - t1: message 1
122///
123/// If te is close to t1, then t1 may be considered valid, which
124/// is probably not what you want.
125pub const CLOCK_SKEW_TOLERANCE: time::Duration
126 = time::Duration::new(30 * 60, 0);
127
128/// The subpacket types.
129///
130/// The `SubpacketTag` enum holds a [`Subpacket`]'s identifier, the
131/// so-called tag.
132#[non_exhaustive]
133#[derive(Debug)]
134#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
135#[derive(Clone, Copy)]
136pub enum SubpacketTag {
137 /// The time the signature was made.
138 ///
139 /// See [Section 5.2.3.11 of RFC 9580] for details.
140 ///
141 /// [Section 5.2.3.11 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
142 SignatureCreationTime,
143 /// The validity period of the signature.
144 ///
145 /// The validity is relative to the time stored in the signature's
146 /// Signature Creation Time subpacket.
147 ///
148 /// See [Section 5.2.3.18 of RFC 9580] for details.
149 ///
150 /// [Section 5.2.3.18 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
151 SignatureExpirationTime,
152 /// Whether a signature should be published.
153 ///
154 /// See [Section 5.2.3.19 of RFC 9580] for details.
155 ///
156 /// [Section 5.2.3.19 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.19
157 ExportableCertification,
158 /// Signer asserts that the key is not only valid but also trustworthy at
159 /// the specified level.
160 ///
161 /// See [Section 5.2.3.21 of RFC 9580] for details.
162 ///
163 /// [Section 5.2.3.21 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
164 TrustSignature,
165 /// Used in conjunction with Trust Signature packets (of level > 0) to
166 /// limit the scope of trust that is extended.
167 ///
168 /// See [Section 5.2.3.22 of RFC 9580] for details.
169 ///
170 /// [Section 5.2.3.22 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.22
171 RegularExpression,
172 /// Whether a signature can later be revoked.
173 ///
174 /// See [Section 5.2.3.20 of RFC 9580] for details.
175 ///
176 /// [Section 5.2.3.20 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.20
177 Revocable,
178 /// The validity period of the key.
179 ///
180 /// The validity period is relative to the key's (not the signature's) creation time.
181 ///
182 /// See [Section 5.2.3.13 of RFC 9580] for details.
183 ///
184 /// [Section 5.2.3.13 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
185 KeyExpirationTime,
186 /// Deprecated
187 PlaceholderForBackwardCompatibility,
188 /// The Symmetric algorithms that the certificate holder prefers.
189 ///
190 /// See [Section 5.2.3.14 of RFC 9580] for details.
191 ///
192 /// [Section 5.2.3.14 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.14
193 PreferredSymmetricAlgorithms,
194 /// Authorizes the specified key to issue revocation signatures for this
195 /// certificate.
196 ///
197 /// See [Section 5.2.3.23 of RFC 9580] for details.
198 ///
199 /// [Section 5.2.3.23 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
200 RevocationKey,
201 /// The OpenPGP Key ID of the key issuing the signature.
202 ///
203 /// See [Section 5.2.3.12 of RFC 9580] for details.
204 ///
205 /// [Section 5.2.3.12 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
206 Issuer,
207 /// A "notation" on the signature.
208 ///
209 /// See [Section 5.2.3.24 of RFC 9580] for details.
210 ///
211 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
212 NotationData,
213 /// The Hash algorithms that the certificate holder prefers.
214 ///
215 /// See [Section 5.2.3.16 of RFC 9580] for details.
216 ///
217 /// [Section 5.2.3.16 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.16
218 PreferredHashAlgorithms,
219 /// The compression algorithms that the certificate holder prefers.
220 ///
221 /// See [Section 5.2.3.17 of RFC 9580] for details.
222 ///
223 /// [Section 5.2.3.17 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.17
224 PreferredCompressionAlgorithms,
225 /// A list of flags that indicate preferences that the certificate
226 /// holder has about how the key is handled by a key server.
227 ///
228 /// See [Section 5.2.3.25 of RFC 9580] for details.
229 ///
230 /// [Section 5.2.3.25 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.25
231 KeyServerPreferences,
232 /// The URI of a key server where the certificate holder keeps
233 /// their certificate up to date.
234 ///
235 /// See [Section 5.2.3.26 of RFC 9580] for details.
236 ///
237 /// [Section 5.2.3.26 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.26
238 PreferredKeyServer,
239 /// A flag in a User ID's self-signature that states whether this
240 /// User ID is the primary User ID for this certificate.
241 ///
242 /// See [Section 5.2.3.27 of RFC 9580] for details.
243 ///
244 /// [Section 5.2.3.27 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
245 PrimaryUserID,
246 /// The URI of a document that describes the policy under which
247 /// the signature was issued.
248 ///
249 /// See [Section 5.2.3.28 of RFC 9580] for details.
250 ///
251 /// [Section 5.2.3.28 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.28
252 PolicyURI,
253 /// A list of flags that hold information about a key.
254 ///
255 /// See [Section 5.2.3.29 of RFC 9580] for details.
256 ///
257 /// [Section 5.2.3.29 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
258 KeyFlags,
259 /// The User ID that is responsible for the signature.
260 ///
261 /// See [Section 5.2.3.30 of RFC 9580] for details.
262 ///
263 /// [Section 5.2.3.30 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.30
264 SignersUserID,
265 /// The reason for a revocation, used in key revocations and
266 /// certification revocation signatures.
267 ///
268 /// See [Section 5.2.3.31 of RFC 9580] for details.
269 ///
270 /// [Section 5.2.3.31 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.31
271 ReasonForRevocation,
272 /// The OpenPGP features a user's implementation supports.
273 ///
274 /// See [Section 5.2.3.32 of RFC 9580] for details.
275 ///
276 /// [Section 5.2.3.32 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.32
277 Features,
278 /// A signature to which this signature refers.
279 ///
280 /// See [Section 5.2.3.33 of RFC 9580] for details.
281 ///
282 /// [Section 5.2.3.33 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
283 SignatureTarget,
284 /// A complete Signature packet body.
285 ///
286 /// This is used to store a backsig in a subkey binding signature.
287 ///
288 /// See [Section 5.2.3.34 of RFC 9580] for details.
289 ///
290 /// [Section 5.2.3.34 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.34
291 EmbeddedSignature,
292
293 /// The Fingerprint of the key that issued the signature.
294 ///
295 /// See [Section 5.2.3.35 of RFC 9580] for details.
296 ///
297 /// [Section 5.2.3.35 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
298 IssuerFingerprint,
299
300 /// Reserved (was: AEAD algorithms that the certificate holder prefers).
301 #[deprecated(note = "Use PreferredAEADCiphersuites instead")]
302 PreferredAEADAlgorithms,
303
304 /// Who the signed message was intended for.
305 ///
306 /// See [Section 5.2.3.36 of RFC 9580] for details.
307 ///
308 /// [Section 5.2.3.36 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
309 IntendedRecipient,
310
311 /// The Approved Certifications subpacket (experimental).
312 ///
313 /// Allows the certificate holder to attest to third party
314 /// certifications, allowing them to be distributed with the
315 /// certificate. This can be used to address certificate flooding
316 /// concerns.
317 ///
318 /// See [Section 2.2 of draft-dkg-openpgp-1pa3pc-02] for details.
319 ///
320 /// [Section 2.2 of draft-dkg-openpgp-1pa3pc-02]: https://www.ietf.org/archive/id/draft-dkg-openpgp-1pa3pc-02.html#approved-certifications-subpacket
321 ApprovedCertifications,
322
323 /// The AEAD Ciphersuites that the certificate holder prefers.
324 ///
325 /// A series of paired algorithm identifiers indicating how the
326 /// keyholder prefers to receive version 2 Symmetrically Encrypted
327 /// Integrity Protected Data. Each pair of octets indicates a
328 /// combination of a symmetric cipher and an AEAD mode that the
329 /// key holder prefers to use.
330 ///
331 /// It is assumed that only the combinations of algorithms listed
332 /// are supported by the recipient's software, with the exception
333 /// of the mandatory-to-implement combination of AES-128 and OCB.
334 /// If AES-128 and OCB are not found in the subpacket, it is
335 /// implicitly listed at the end.
336 ///
337 /// See [Section 5.2.3.15 of RFC 9580] for details.
338 ///
339 /// [Section 5.2.3.15 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites
340 PreferredAEADCiphersuites,
341
342 /// Reserved subpacket tag.
343 Reserved(u8),
344 /// Private subpacket tag.
345 Private(u8),
346 /// Unknown subpacket tag.
347 Unknown(u8),
348
349 // If you add a new variant, make sure to add it to the
350 // conversions and to SUBPACKET_TAG_VARIANTS.
351}
352assert_send_and_sync!(SubpacketTag);
353
354impl fmt::Display for SubpacketTag {
355 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356 write!(f, "{:?}", self)
357 }
358}
359
360impl From<u8> for SubpacketTag {
361 fn from(u: u8) -> Self {
362 #[allow(deprecated)]
363 match u {
364 2 => SubpacketTag::SignatureCreationTime,
365 3 => SubpacketTag::SignatureExpirationTime,
366 4 => SubpacketTag::ExportableCertification,
367 5 => SubpacketTag::TrustSignature,
368 6 => SubpacketTag::RegularExpression,
369 7 => SubpacketTag::Revocable,
370 9 => SubpacketTag::KeyExpirationTime,
371 10 => SubpacketTag::PlaceholderForBackwardCompatibility,
372 11 => SubpacketTag::PreferredSymmetricAlgorithms,
373 12 => SubpacketTag::RevocationKey,
374 16 => SubpacketTag::Issuer,
375 20 => SubpacketTag::NotationData,
376 21 => SubpacketTag::PreferredHashAlgorithms,
377 22 => SubpacketTag::PreferredCompressionAlgorithms,
378 23 => SubpacketTag::KeyServerPreferences,
379 24 => SubpacketTag::PreferredKeyServer,
380 25 => SubpacketTag::PrimaryUserID,
381 26 => SubpacketTag::PolicyURI,
382 27 => SubpacketTag::KeyFlags,
383 28 => SubpacketTag::SignersUserID,
384 29 => SubpacketTag::ReasonForRevocation,
385 30 => SubpacketTag::Features,
386 31 => SubpacketTag::SignatureTarget,
387 32 => SubpacketTag::EmbeddedSignature,
388 33 => SubpacketTag::IssuerFingerprint,
389 34 => SubpacketTag::PreferredAEADAlgorithms,
390 35 => SubpacketTag::IntendedRecipient,
391 37 => SubpacketTag::ApprovedCertifications,
392 39 => SubpacketTag::PreferredAEADCiphersuites,
393 0| 1| 8| 13| 14| 15| 17| 18| 19 | 38 => SubpacketTag::Reserved(u),
394 100..=110 => SubpacketTag::Private(u),
395 _ => SubpacketTag::Unknown(u),
396 }
397 }
398}
399
400impl From<SubpacketTag> for u8 {
401 fn from(t: SubpacketTag) -> Self {
402 #[allow(deprecated)]
403 match t {
404 SubpacketTag::SignatureCreationTime => 2,
405 SubpacketTag::SignatureExpirationTime => 3,
406 SubpacketTag::ExportableCertification => 4,
407 SubpacketTag::TrustSignature => 5,
408 SubpacketTag::RegularExpression => 6,
409 SubpacketTag::Revocable => 7,
410 SubpacketTag::KeyExpirationTime => 9,
411 SubpacketTag::PlaceholderForBackwardCompatibility => 10,
412 SubpacketTag::PreferredSymmetricAlgorithms => 11,
413 SubpacketTag::RevocationKey => 12,
414 SubpacketTag::Issuer => 16,
415 SubpacketTag::NotationData => 20,
416 SubpacketTag::PreferredHashAlgorithms => 21,
417 SubpacketTag::PreferredCompressionAlgorithms => 22,
418 SubpacketTag::KeyServerPreferences => 23,
419 SubpacketTag::PreferredKeyServer => 24,
420 SubpacketTag::PrimaryUserID => 25,
421 SubpacketTag::PolicyURI => 26,
422 SubpacketTag::KeyFlags => 27,
423 SubpacketTag::SignersUserID => 28,
424 SubpacketTag::ReasonForRevocation => 29,
425 SubpacketTag::Features => 30,
426 SubpacketTag::SignatureTarget => 31,
427 SubpacketTag::EmbeddedSignature => 32,
428 SubpacketTag::IssuerFingerprint => 33,
429 SubpacketTag::PreferredAEADAlgorithms => 34,
430 SubpacketTag::IntendedRecipient => 35,
431 SubpacketTag::ApprovedCertifications => 37,
432 SubpacketTag::PreferredAEADCiphersuites => 39,
433 SubpacketTag::Reserved(u) => u,
434 SubpacketTag::Private(u) => u,
435 SubpacketTag::Unknown(u) => u,
436 }
437 }
438}
439
440#[allow(deprecated)]
441const SUBPACKET_TAG_VARIANTS: [SubpacketTag; 29] = [
442 SubpacketTag::SignatureCreationTime,
443 SubpacketTag::SignatureExpirationTime,
444 SubpacketTag::ExportableCertification,
445 SubpacketTag::TrustSignature,
446 SubpacketTag::RegularExpression,
447 SubpacketTag::Revocable,
448 SubpacketTag::KeyExpirationTime,
449 SubpacketTag::PlaceholderForBackwardCompatibility,
450 SubpacketTag::PreferredSymmetricAlgorithms,
451 SubpacketTag::RevocationKey,
452 SubpacketTag::Issuer,
453 SubpacketTag::NotationData,
454 SubpacketTag::PreferredHashAlgorithms,
455 SubpacketTag::PreferredCompressionAlgorithms,
456 SubpacketTag::KeyServerPreferences,
457 SubpacketTag::PreferredKeyServer,
458 SubpacketTag::PrimaryUserID,
459 SubpacketTag::PolicyURI,
460 SubpacketTag::KeyFlags,
461 SubpacketTag::SignersUserID,
462 SubpacketTag::ReasonForRevocation,
463 SubpacketTag::Features,
464 SubpacketTag::SignatureTarget,
465 SubpacketTag::EmbeddedSignature,
466 SubpacketTag::IssuerFingerprint,
467 SubpacketTag::PreferredAEADAlgorithms,
468 SubpacketTag::IntendedRecipient,
469 SubpacketTag::ApprovedCertifications,
470 SubpacketTag::PreferredAEADCiphersuites,
471];
472
473impl SubpacketTag {
474 /// Returns an iterator over all valid variants.
475 ///
476 /// Returns an iterator over all known variants. This does not
477 /// include the [`SubpacketTag::Reserved`],
478 /// [`SubpacketTag::Private`], or [`SubpacketTag::Unknown`]
479 /// variants.
480 pub fn variants() -> impl Iterator<Item=Self> {
481 SUBPACKET_TAG_VARIANTS.iter().cloned()
482 }
483}
484
485#[cfg(test)]
486impl Arbitrary for SubpacketTag {
487 fn arbitrary(g: &mut Gen) -> Self {
488 u8::arbitrary(g).into()
489 }
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495 quickcheck! {
496 fn roundtrip(tag: SubpacketTag) -> bool {
497 let val: u8 = tag.into();
498 tag == SubpacketTag::from(val)
499 }
500 }
501
502 quickcheck! {
503 fn parse(tag: SubpacketTag) -> bool {
504 match tag {
505 SubpacketTag::Reserved(u) =>
506 (u == 0 || u == 1 || u == 8
507 || u == 13 || u == 14 || u == 15
508 || u == 17 || u == 18 || u == 19
509 || u == 38),
510 SubpacketTag::Private(u) => (100..=110).contains(&u),
511 SubpacketTag::Unknown(u) => (u > 33 && u < 100) || u > 110,
512 _ => true
513 }
514 }
515 }
516
517 #[test]
518 fn subpacket_tag_variants() {
519 use std::collections::HashSet;
520 use std::iter::FromIterator;
521
522 // SUBPACKET_TAG_VARIANTS is a list. Derive it in a different way
523 // to double-check that nothing is missing.
524 let derived_variants = (0..=u8::MAX)
525 .map(SubpacketTag::from)
526 .filter(|t| {
527 match t {
528 SubpacketTag::Reserved(_) => false,
529 SubpacketTag::Private(_) => false,
530 SubpacketTag::Unknown(_) => false,
531 _ => true,
532 }
533 })
534 .collect::<HashSet<_>>();
535
536 let known_variants
537 = HashSet::from_iter(SUBPACKET_TAG_VARIANTS.iter().cloned());
538
539 let missing = known_variants
540 .symmetric_difference(&derived_variants)
541 .collect::<Vec<_>>();
542
543 assert!(missing.is_empty(), "{:?}", missing);
544 }
545}
546
547/// Subpacket area.
548///
549/// A version 4 Signature contains two areas that can stored
550/// [signature subpackets]: a so-called hashed subpacket area, and a
551/// so-called unhashed subpacket area. The hashed subpacket area is
552/// protected by the signature; the unhashed area is not. This makes
553/// the unhashed subpacket area only appropriate for
554/// self-authenticating data, like the [`Issuer`] subpacket. The
555/// [`SubpacketAreas`] data structure understands these nuances and
556/// routes lookups appropriately. As such, it is usually better to
557/// work with subpackets using that interface.
558///
559/// [signature subpackets]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.7
560/// [`Issuer`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
561///
562/// # Examples
563///
564/// ```
565/// # use sequoia_openpgp as openpgp;
566/// # use openpgp::cert::prelude::*;
567/// # use openpgp::packet::prelude::*;
568/// # use openpgp::policy::StandardPolicy;
569/// # use openpgp::types::SignatureType;
570/// #
571/// # fn main() -> openpgp::Result<()> {
572/// # let p = &StandardPolicy::new();
573/// #
574/// # let (cert, _) = CertBuilder::new().generate()?;
575/// #
576/// # let key : &Key<_, _> = cert.primary_key().key();
577/// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
578/// #
579/// # let msg = b"Hello, world!";
580/// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
581/// # .sign_message(&mut signer, msg)?;
582/// #
583/// # // Verify it.
584/// # sig.verify_message(signer.public(), msg)?;
585/// fn sig_stats(sig: &Signature) {
586/// eprintln!("Hashed subpacket area has {} subpackets",
587/// sig.hashed_area().iter().count());
588/// eprintln!("Unhashed subpacket area has {} subpackets",
589/// sig.unhashed_area().iter().count());
590/// }
591/// # sig_stats(&sig);
592/// # Ok(())
593/// # }
594/// ```
595#[derive(Clone)]
596pub struct SubpacketArea {
597 /// The subpackets.
598 packets: Vec<Subpacket>,
599
600 // The subpacket area, but parsed so that the vector is indexed by
601 // the subpacket tag, and the value is the index of the *last*
602 // occurrence of that subpacket in the subpacket area.
603 //
604 // Since self-referential structs are a no-no, we use an index
605 // to reference the content in the area.
606 //
607 // Note: A subpacket area is at most 2**16-1 bytes large. A
608 // subpacket is at least two bytes long (one for the length, and
609 // one for the subpacket type). Thus, a subpacket area can't have
610 // more than 2**15 subpackets. This means that we need at most 15
611 // bits. Thus, instead of using an `Option<u16>`, which requires
612 // 32 bits, we use an unused value to mean not present.
613 parsed: std::sync::OnceLock<Vec<u16>>,
614}
615assert_send_and_sync!(SubpacketArea);
616
617// The value for an entry of `SubpacketArea::parsed` when the
618// subpacket is not present.
619//
620// We don't use an `Option<u16>`, as that would require 32 bits, and
621// this value is not used. See the comment for
622// `SubpacketArea::parsed`.
623const SUBPACKET_NOT_PRESENT: u16 = u16::MAX;
624
625#[cfg(test)]
626impl ArbitraryBounded for SubpacketArea {
627 fn arbitrary_bounded(g: &mut Gen, depth: usize) -> Self {
628 use crate::arbitrary_helper::gen_arbitrary_from_range;
629
630 let mut a = Self::default();
631 for _ in 0..gen_arbitrary_from_range(0..32, g) {
632 let _ = a.add(ArbitraryBounded::arbitrary_bounded(g, depth));
633 }
634
635 a
636 }
637}
638
639#[cfg(test)]
640impl_arbitrary_with_bound!(SubpacketArea);
641
642impl Default for SubpacketArea {
643 fn default() -> Self {
644 Self::new(Default::default()).unwrap()
645 }
646}
647
648impl PartialEq for SubpacketArea {
649 fn eq(&self, other: &SubpacketArea) -> bool {
650 self.cmp(other) == Ordering::Equal
651 }
652}
653
654impl Eq for SubpacketArea {}
655
656impl PartialOrd for SubpacketArea {
657 fn partial_cmp(&self, other: &SubpacketArea) -> Option<Ordering> {
658 Some(self.cmp(other))
659 }
660}
661
662impl Ord for SubpacketArea {
663 fn cmp(&self, other: &SubpacketArea) -> Ordering {
664 self.packets.cmp(&other.packets)
665 }
666}
667
668impl Hash for SubpacketArea {
669 fn hash<H: Hasher>(&self, state: &mut H) {
670 // We hash only the data, the cache is a hashmap and does not
671 // implement hash.
672 self.packets.hash(state);
673 }
674}
675
676impl fmt::Debug for SubpacketArea {
677 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
678 f.debug_list()
679 .entries(self.iter())
680 .finish()
681 }
682}
683
684impl<'a> IntoIterator for &'a SubpacketArea {
685 type Item = &'a Subpacket;
686 type IntoIter = std::slice::Iter<'a, Subpacket>;
687
688 fn into_iter(self) -> Self::IntoIter {
689 self.packets.iter()
690 }
691}
692
693impl SubpacketArea {
694 /// The maximum size of a subpacket area.
695 pub const MAX_SIZE: usize = (1 << 16) - 1;
696
697 /// Returns a new subpacket area containing the given `packets`.
698 pub fn new(packets: Vec<Subpacket>) -> Result<SubpacketArea> {
699 let area = SubpacketArea {
700 packets,
701 parsed: std::sync::OnceLock::new(),
702 };
703 Ok(area)
704 }
705
706 /// Initialize the cache mapping subpacket tags to positions in
707 /// the subpacket area.
708 ///
709 /// If the cache is already initialized, this is a NOP.
710 ///
711 /// Returns the locked cache.
712 fn cache_init(&self) -> &Vec<u16>
713 {
714 self.parsed.get_or_init(|| {
715 // The largest defined subpacket in the crypto refresh is
716 // 39.
717 if let Some(max)
718 = self.packets.iter().map(|sp| u8::from(sp.tag())).max()
719 {
720 let max = max as usize;
721
722 let mut index = vec![ SUBPACKET_NOT_PRESENT; max + 1 ];
723 for (i, sp) in self.packets.iter().enumerate() {
724 index[u8::from(sp.tag()) as usize] = i as u16;
725 }
726 index
727 } else {
728 Vec::new()
729 }
730 })
731 }
732
733 /// Invalidates the cache.
734 fn cache_invalidate(&mut self) {
735 self.parsed = std::sync::OnceLock::new();
736 }
737
738 /// Iterates over the subpackets.
739 ///
740 /// # Examples
741 ///
742 /// Print the number of different types of subpackets in a
743 /// Signature's hashed subpacket area:
744 ///
745 /// ```
746 /// # use sequoia_openpgp as openpgp;
747 /// # use openpgp::cert::prelude::*;
748 /// # use openpgp::packet::prelude::*;
749 /// # use openpgp::types::SignatureType;
750 /// #
751 /// # fn main() -> openpgp::Result<()> {
752 /// # let (cert, _) = CertBuilder::new().generate()?;
753 /// #
754 /// # let key : &Key<_, _> = cert.primary_key().key();
755 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
756 /// #
757 /// # let msg = b"Hello, world!";
758 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
759 /// # .sign_message(&mut signer, msg)?;
760 /// #
761 /// # // Verify it.
762 /// # sig.verify_message(signer.public(), msg)?;
763 /// #
764 /// let mut tags: Vec<_> = sig.hashed_area().iter().map(|sb| {
765 /// sb.tag()
766 /// }).collect();
767 /// tags.sort();
768 /// tags.dedup();
769 ///
770 /// eprintln!("The hashed area contains {} types of subpackets",
771 /// tags.len());
772 /// # Ok(())
773 /// # }
774 /// ```
775 pub fn iter(&self) -> impl Iterator<Item = &Subpacket> + Send + Sync {
776 self.packets.iter()
777 }
778
779 pub(crate) fn iter_mut(&mut self)
780 -> impl Iterator<Item = &mut Subpacket> + Send + Sync
781 {
782 self.packets.iter_mut()
783 }
784
785 /// Returns a reference to the *last* instance of the specified
786 /// subpacket, if any.
787 ///
788 /// A given subpacket may occur multiple times. For some, like
789 /// the [`Notation Data`] subpacket, this is reasonable. For
790 /// others, like the [`Signature Creation Time`] subpacket, this
791 /// results in an ambiguity. [Section 5.2.3.9 of RFC 9580] says:
792 ///
793 /// > a signature may contain multiple copies of a preference or
794 /// > multiple expiration times. In most cases, an implementation
795 /// > SHOULD use the last subpacket in the signature, but MAY use
796 /// > any conflict resolution scheme that makes more sense.
797 ///
798 /// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
799 /// [`Signature Creation Time`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
800 /// [Section 5.2.3.9 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.9
801 ///
802 /// This function implements the recommended strategy of returning
803 /// the last subpacket.
804 ///
805 /// # Examples
806 ///
807 /// All signatures must have a `Signature Creation Time` subpacket
808 /// in the hashed subpacket area:
809 ///
810 /// ```
811 /// use sequoia_openpgp as openpgp;
812 /// # use openpgp::cert::prelude::*;
813 /// # use openpgp::packet::prelude::*;
814 /// use openpgp::packet::signature::subpacket::SubpacketTag;
815 /// # use openpgp::types::SignatureType;
816 ///
817 /// # fn main() -> openpgp::Result<()> {
818 /// # let (cert, _) = CertBuilder::new().generate()?;
819 /// #
820 /// # let key : &Key<_, _> = cert.primary_key().key();
821 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
822 /// #
823 /// # let msg = b"Hello, world!";
824 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
825 /// # .sign_message(&mut signer, msg)?;
826 /// #
827 /// # // Verify it.
828 /// # sig.verify_message(signer.public(), msg)?;
829 /// #
830 /// if sig.hashed_area().subpacket(SubpacketTag::SignatureCreationTime).is_none() {
831 /// eprintln!("Invalid signature.");
832 /// }
833 /// # Ok(())
834 /// # }
835 /// ```
836 pub fn subpacket(&self, tag: SubpacketTag) -> Option<&Subpacket> {
837 match self.cache_init().get(u8::from(tag) as usize) {
838 Some(&SUBPACKET_NOT_PRESENT) => None,
839 Some(&n) => Some(&self.packets[n as usize]),
840 _ => None,
841 }
842 }
843
844 /// Returns a mutable reference to the *last* instance of the
845 /// specified subpacket, if any.
846 ///
847 /// A given subpacket may occur multiple times. For some, like
848 /// the [`Notation Data`] subpacket, this is reasonable. For
849 /// others, like the [`Signature Creation Time`] subpacket, this
850 /// results in an ambiguity. [Section 5.2.3.9 of RFC 9580] says:
851 ///
852 /// > a signature may contain multiple copies of a preference or
853 /// > multiple expiration times. In most cases, an implementation
854 /// > SHOULD use the last subpacket in the signature, but MAY use
855 /// > any conflict resolution scheme that makes more sense.
856 ///
857 /// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
858 /// [`Signature Creation Time`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
859 /// [Section 5.2.3.9 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.9
860 ///
861 /// This function implements the recommended strategy of returning
862 /// the last subpacket.
863 ///
864 /// # Examples
865 ///
866 /// All signatures must have a `Signature Creation Time` subpacket
867 /// in the hashed subpacket area:
868 ///
869 /// ```
870 /// use sequoia_openpgp as openpgp;
871 /// # use openpgp::cert::prelude::*;
872 /// # use openpgp::packet::prelude::*;
873 /// use openpgp::packet::signature::subpacket::SubpacketTag;
874 /// # use openpgp::types::SignatureType;
875 ///
876 /// # fn main() -> openpgp::Result<()> {
877 /// # let (cert, _) = CertBuilder::new().generate()?;
878 /// #
879 /// # let key : &Key<_, _> = cert.primary_key().key();
880 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
881 /// #
882 /// # let msg = b"Hello, world!";
883 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
884 /// # .sign_message(&mut signer, msg)?;
885 /// #
886 /// # // Verify it.
887 /// # sig.verify_message(signer.public(), msg)?;
888 /// #
889 /// if sig.hashed_area().subpacket(SubpacketTag::SignatureCreationTime).is_none() {
890 /// eprintln!("Invalid signature.");
891 /// }
892 /// # Ok(())
893 /// # }
894 /// ```
895 pub fn subpacket_mut(&mut self, tag: SubpacketTag)
896 -> Option<&mut Subpacket> {
897 match self.cache_init().get(u8::from(tag) as usize) {
898 Some(&SUBPACKET_NOT_PRESENT) => None,
899 Some(&n) => Some(&mut self.packets[n as usize]),
900 _ => None,
901 }
902 }
903
904 /// Returns all instances of the specified subpacket.
905 ///
906 /// For most subpackets, only a single instance of the subpacket
907 /// makes sense. [`SubpacketArea::subpacket`] resolves this
908 /// ambiguity by returning the last instance of the request
909 /// subpacket type. But, for some subpackets, like the [`Notation
910 /// Data`] subpacket, multiple instances of the subpacket are
911 /// reasonable.
912 ///
913 /// [`SubpacketArea::subpacket`]: Self::subpacket()
914 /// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
915 ///
916 /// # Examples
917 ///
918 /// Count the number of `Notation Data` subpackets in the hashed
919 /// subpacket area:
920 ///
921 /// ```
922 /// use sequoia_openpgp as openpgp;
923 /// # use openpgp::cert::prelude::*;
924 /// # use openpgp::packet::prelude::*;
925 /// use openpgp::packet::signature::subpacket::SubpacketTag;
926 /// # use openpgp::types::SignatureType;
927 ///
928 /// # fn main() -> openpgp::Result<()> {
929 /// # let (cert, _) = CertBuilder::new().generate()?;
930 /// #
931 /// # let key : &Key<_, _> = cert.primary_key().key();
932 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
933 /// #
934 /// # let msg = b"Hello, world!";
935 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
936 /// # .sign_message(&mut signer, msg)?;
937 /// #
938 /// # // Verify it.
939 /// # sig.verify_message(signer.public(), msg)?;
940 /// #
941 /// eprintln!("Signature has {} notations.",
942 /// sig.hashed_area().subpackets(SubpacketTag::NotationData).count());
943 /// # Ok(())
944 /// # }
945 /// ```
946 pub fn subpackets(&self, target: SubpacketTag)
947 -> impl Iterator<Item = &Subpacket> + Send + Sync
948 {
949 self.iter().filter(move |sp| sp.tag() == target)
950 }
951
952 pub(crate) fn subpackets_mut(&mut self, target: SubpacketTag)
953 -> impl Iterator<Item = &mut Subpacket> + Send + Sync
954 {
955 self.iter_mut().filter(move |sp| sp.tag() == target)
956 }
957
958 /// Adds the given subpacket.
959 ///
960 /// Adds the given subpacket to the subpacket area. If the
961 /// subpacket area already contains subpackets with the same tag,
962 /// they are left in place. If you want to replace them, you
963 /// should instead use the [`SubpacketArea::replace`] method.
964 ///
965 /// [`SubpacketArea::replace`]: Self::replace()
966 ///
967 /// # Errors
968 ///
969 /// Returns `Error::MalformedPacket` if adding the packet makes
970 /// the subpacket area exceed the size limit.
971 ///
972 /// # Examples
973 ///
974 /// Adds an additional `Issuer` subpacket to the unhashed
975 /// subpacket area. (This is useful if the key material is
976 /// associated with multiple certificates, e.g., a v4 and a v5
977 /// certificate.) Because the subpacket is added to the unhashed
978 /// area, the signature remains valid.
979 ///
980 /// ```
981 /// use sequoia_openpgp as openpgp;
982 /// # use openpgp::cert::prelude::*;
983 /// use openpgp::KeyID;
984 /// # use openpgp::packet::prelude::*;
985 /// use openpgp::packet::signature::subpacket::{
986 /// Subpacket,
987 /// SubpacketTag,
988 /// SubpacketValue,
989 /// };
990 /// # use openpgp::types::SignatureType;
991 ///
992 /// # fn main() -> openpgp::Result<()> {
993 /// # let (cert, _) = CertBuilder::new().generate()?;
994 /// #
995 /// # let key : &Key<_, _> = cert.primary_key().key();
996 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
997 /// #
998 /// # let msg = b"Hello, world!";
999 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
1000 /// # .sign_message(&mut signer, msg)?;
1001 /// #
1002 /// # // Verify it.
1003 /// # sig.verify_message(signer.public(), msg)?;
1004 /// #
1005 /// # assert_eq!(sig
1006 /// # .hashed_area()
1007 /// # .iter()
1008 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
1009 /// # .count(),
1010 /// # 1);
1011 /// let mut sig: Signature = sig;
1012 /// sig.unhashed_area_mut().add(
1013 /// Subpacket::new(
1014 /// SubpacketValue::Issuer(KeyID::from_hex("AAAA BBBB CCCC DDDD")?),
1015 /// false)?);
1016 ///
1017 /// sig.verify_message(signer.public(), msg)?;
1018 /// # assert_eq!(sig
1019 /// # .unhashed_area()
1020 /// # .iter()
1021 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
1022 /// # .count(),
1023 /// # 1);
1024 /// # Ok(())
1025 /// # }
1026 /// ```
1027 pub fn add(&mut self, packet: Subpacket) -> Result<()> {
1028 self.add_internal(packet, false)
1029 }
1030
1031 /// Adds `packet`, setting its authenticated flag to `authenticated`.
1032 pub(super) fn add_internal(&mut self, packet: Subpacket,
1033 authenticated: bool)
1034 -> Result<()>
1035 {
1036 if self.serialized_len() + packet.serialized_len()
1037 > ::std::u16::MAX as usize
1038 {
1039 return Err(Error::MalformedPacket(
1040 "Subpacket area exceeds maximum size".into()).into());
1041 }
1042
1043 self.cache_invalidate();
1044 packet.set_authenticated(authenticated);
1045 self.packets.push(packet);
1046 Ok(())
1047 }
1048
1049 /// Adds the given subpacket, replacing all other subpackets with
1050 /// the same tag.
1051 ///
1052 /// Adds the given subpacket to the subpacket area. If the
1053 /// subpacket area already contains subpackets with the same tag,
1054 /// they are first removed. If you want to preserve them, you
1055 /// should instead use the [`SubpacketArea::add`] method.
1056 ///
1057 /// [`SubpacketArea::add`]: Self::add()
1058 ///
1059 /// # Errors
1060 ///
1061 /// Returns `Error::MalformedPacket` if adding the packet makes
1062 /// the subpacket area exceed the size limit.
1063 ///
1064 /// # Examples
1065 ///
1066 /// Assuming we have a signature with an additional `Issuer`
1067 /// subpacket in the unhashed area (see the example for
1068 /// [`SubpacketArea::add`]), this replaces the `Issuer` subpacket
1069 /// in the unhashed area. Because the unhashed area is not
1070 /// protected by the signature, the signature remains valid:
1071 ///
1072 /// ```
1073 /// use sequoia_openpgp as openpgp;
1074 /// # use openpgp::cert::prelude::*;
1075 /// use openpgp::KeyID;
1076 /// # use openpgp::packet::prelude::*;
1077 /// use openpgp::packet::signature::subpacket::{
1078 /// Subpacket,
1079 /// SubpacketTag,
1080 /// SubpacketValue,
1081 /// };
1082 /// # use openpgp::types::SignatureType;
1083 ///
1084 /// # fn main() -> openpgp::Result<()> {
1085 /// # let (cert, _) = CertBuilder::new().generate()?;
1086 /// #
1087 /// # let key : &Key<_, _> = cert.primary_key().key();
1088 /// # let mut signer = key.clone().parts_into_secret()?.into_keypair()?;
1089 /// #
1090 /// # let msg = b"Hello, world!";
1091 /// # let mut sig = SignatureBuilder::new(SignatureType::Binary)
1092 /// # .sign_message(&mut signer, msg)?;
1093 /// #
1094 /// # // Verify it.
1095 /// # sig.verify_message(signer.public(), msg)?;
1096 /// #
1097 /// # assert_eq!(sig
1098 /// # .hashed_area()
1099 /// # .iter()
1100 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
1101 /// # .count(),
1102 /// # 1);
1103 /// // First, add a subpacket to the unhashed area.
1104 /// let mut sig: Signature = sig;
1105 /// sig.unhashed_area_mut().add(
1106 /// Subpacket::new(
1107 /// SubpacketValue::Issuer(KeyID::from_hex("DDDD CCCC BBBB AAAA")?),
1108 /// false)?);
1109 ///
1110 /// // Now, replace it.
1111 /// sig.unhashed_area_mut().replace(
1112 /// Subpacket::new(
1113 /// SubpacketValue::Issuer(KeyID::from_hex("AAAA BBBB CCCC DDDD")?),
1114 /// false)?);
1115 ///
1116 /// sig.verify_message(signer.public(), msg)?;
1117 /// # assert_eq!(sig
1118 /// # .unhashed_area()
1119 /// # .iter()
1120 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
1121 /// # .count(),
1122 /// # 1);
1123 /// # Ok(())
1124 /// # }
1125 /// ```
1126 pub fn replace(&mut self, packet: Subpacket) -> Result<()> {
1127 if self.iter().filter_map(|sp| if sp.tag() != packet.tag() {
1128 Some(sp.serialized_len())
1129 } else {
1130 None
1131 }).sum::<usize>() + packet.serialized_len() > std::u16::MAX as usize {
1132 return Err(Error::MalformedPacket(
1133 "Subpacket area exceeds maximum size".into()).into());
1134 }
1135 self.remove_all(packet.tag());
1136 packet.set_authenticated(false);
1137 self.packets.push(packet);
1138 Ok(())
1139 }
1140
1141 /// Removes all subpackets with the given tag.
1142 pub fn remove_all(&mut self, tag: SubpacketTag) {
1143 self.cache_invalidate();
1144 self.packets.retain(|sp| sp.tag() != tag);
1145 }
1146
1147 /// Removes all subpackets.
1148 pub fn clear(&mut self) {
1149 self.cache_invalidate();
1150 self.packets.clear();
1151 }
1152
1153 /// Sorts the subpackets by subpacket tag.
1154 ///
1155 /// This normalizes the subpacket area, and accelerates lookups in
1156 /// implementations that sort the in-core representation and use
1157 /// binary search for lookups.
1158 ///
1159 /// The subpackets are sorted by the numeric value of their tag.
1160 /// The sort is stable. So, if there are multiple [`Notation Data`]
1161 /// subpackets, for instance, they will remain in the same order.
1162 ///
1163 /// The [`SignatureBuilder`] sorts the subpacket areas just before
1164 /// creating the signature.
1165 ///
1166 /// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
1167 /// [`SignatureBuilder`]: super::SignatureBuilder
1168 pub fn sort(&mut self) {
1169 self.cache_invalidate();
1170 // slice::sort_by is stable.
1171 self.packets.sort_by(|a, b| u8::from(a.tag()).cmp(&b.tag().into()));
1172 }
1173}
1174
1175/// Payload of a Notation Data subpacket.
1176///
1177/// The [`Notation Data`] subpacket provides a mechanism for a
1178/// message's signer to insert nearly arbitrary data into the
1179/// signature. Because notations can be marked as critical, it is
1180/// possible to add security relevant notations, which the receiving
1181/// OpenPGP implementation will respect (in the sense that an
1182/// implementation will reject signatures that include unknown,
1183/// critical notations), even if they don't understand the notations
1184/// themselves.
1185///
1186/// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
1187///
1188/// It is possible to control how Sequoia's higher-level functionality
1189/// handles unknown, critical notations using a [`Policy`] object.
1190/// Depending on the degree of control required, it may be sufficient
1191/// to customize a [`StandardPolicy`] object using, for instance, the
1192/// [`StandardPolicy::good_critical_notations`] method.
1193///
1194/// [`Policy`]: crate::policy::Policy
1195/// [`StandardPolicy`]: crate::policy::StandardPolicy
1196/// [`StandardPolicy::good_critical_notations`]: crate::policy::StandardPolicy::good_critical_notations()
1197///
1198/// Notation names are human-readable UTF-8 strings. There are two
1199/// namespaces: The user namespace and the IETF namespace. Names in
1200/// the user namespace have the form `name@example.org` and are
1201/// managed by the owner of the domain. Names in the IETF namespace
1202/// may not contain an `@` and are managed by IANA. See [Section
1203/// 5.2.3.24 of RFC 9580] for details.
1204///
1205/// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
1206#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1207pub struct NotationData {
1208 flags: NotationDataFlags,
1209 name: String,
1210 value: Vec<u8>,
1211}
1212assert_send_and_sync!(NotationData);
1213
1214impl fmt::Display for NotationData {
1215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1216 write!(f, "{}", self.name)?;
1217
1218 let flags = format!("{:?}", self.flags);
1219 if ! flags.is_empty() {
1220 write!(f, " ({})", flags)?;
1221 }
1222
1223 if self.flags.human_readable() {
1224 write!(f, ": {}", String::from_utf8_lossy(&self.value))?;
1225 } else {
1226 let hex = crate::fmt::hex::encode(&self.value);
1227 write!(f, ": {}", hex)?;
1228 }
1229
1230 Ok(())
1231 }
1232}
1233
1234impl fmt::Debug for NotationData {
1235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1236 let mut dbg = f.debug_struct("NotationData");
1237 dbg.field("name", &self.name);
1238
1239 let flags = format!("{:?}", self.flags);
1240 if ! flags.is_empty() {
1241 dbg.field("flags", &flags);
1242 }
1243
1244 if self.flags.human_readable() {
1245 match std::str::from_utf8(&self.value) {
1246 Ok(s) => {
1247 dbg.field("value", &s);
1248 },
1249 Err(e) => {
1250 let s = format!("({}): {}", e,
1251 crate::fmt::hex::encode(&self.value));
1252 dbg.field("value", &s);
1253 },
1254 }
1255 } else {
1256 let hex = crate::fmt::hex::encode(&self.value);
1257 dbg.field("value", &hex);
1258 }
1259
1260 dbg.finish()
1261 }
1262}
1263
1264#[cfg(test)]
1265impl Arbitrary for NotationData {
1266 fn arbitrary(g: &mut Gen) -> Self {
1267 NotationData {
1268 flags: Arbitrary::arbitrary(g),
1269 name: Arbitrary::arbitrary(g),
1270 value: Arbitrary::arbitrary(g),
1271 }
1272 }
1273}
1274
1275impl NotationData {
1276 /// Creates a new Notation Data subpacket payload.
1277 pub fn new<N, V, F>(name: N, value: V, flags: F) -> Self
1278 where N: AsRef<str>,
1279 V: AsRef<[u8]>,
1280 F: Into<Option<NotationDataFlags>>,
1281 {
1282 Self {
1283 flags: flags.into().unwrap_or_else(NotationDataFlags::empty),
1284 name: name.as_ref().into(),
1285 value: value.as_ref().into(),
1286 }
1287 }
1288
1289 /// Returns the flags.
1290 pub fn flags(&self) -> &NotationDataFlags {
1291 &self.flags
1292 }
1293
1294 /// Returns the name.
1295 pub fn name(&self) -> &str {
1296 &self.name
1297 }
1298
1299 /// Returns the value.
1300 pub fn value(&self) -> &[u8] {
1301 &self.value
1302 }
1303}
1304
1305/// Flags for the Notation Data subpacket.
1306#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1307pub struct NotationDataFlags(crate::types::Bitfield);
1308assert_send_and_sync!(NotationDataFlags);
1309
1310#[cfg(test)]
1311impl Arbitrary for NotationDataFlags {
1312 fn arbitrary(g: &mut Gen) -> Self {
1313 NotationDataFlags(vec![u8::arbitrary(g), u8::arbitrary(g),
1314 u8::arbitrary(g), u8::arbitrary(g)].into())
1315 }
1316}
1317
1318impl fmt::Debug for NotationDataFlags {
1319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1320 let mut need_comma = false;
1321 if self.human_readable() {
1322 f.write_str("human readable")?;
1323 need_comma = true;
1324 }
1325
1326 for i in self.0.iter_set() {
1327 match i {
1328 NOTATION_DATA_FLAG_HUMAN_READABLE => (),
1329 i => {
1330 if need_comma { f.write_str(", ")?; }
1331 write!(f, "#{}", i)?;
1332 need_comma = true;
1333 },
1334 }
1335 }
1336
1337 // Don't mention padding, the bit field always has the same
1338 // size.
1339
1340 Ok(())
1341 }
1342}
1343
1344const NOTATION_DATA_FLAG_HUMAN_READABLE: usize = 7;
1345
1346impl NotationDataFlags {
1347 /// Creates a new instance from `bits`.
1348 pub fn new<B: AsRef<[u8]>>(bits: B) -> Result<Self> {
1349 if bits.as_ref().len() == 4 {
1350 Ok(Self(bits.as_ref().to_vec().into()))
1351 } else {
1352 Err(Error::InvalidArgument(
1353 format!("Need four bytes of flags, got: {:?}", bits.as_ref()))
1354 .into())
1355 }
1356 }
1357
1358 /// Returns an empty key server preference set.
1359 pub fn empty() -> Self {
1360 Self::new(&[0, 0, 0, 0]).unwrap()
1361 }
1362
1363 /// Returns a reference to the underlying
1364 /// [`Bitfield`](crate::types::Bitfield).
1365 pub fn as_bitfield(&self) -> &crate::types::Bitfield {
1366 &self.0
1367 }
1368
1369 /// Returns whether the specified notation data flag is set.
1370 ///
1371 /// # Examples
1372 ///
1373 /// ```
1374 /// use sequoia_openpgp as openpgp;
1375 /// use openpgp::packet::signature::subpacket::NotationDataFlags;
1376 ///
1377 /// # fn main() -> openpgp::Result<()> {
1378 /// // Notation Data flags 0 and 2.
1379 /// let ndf = NotationDataFlags::new(&[5, 0, 0, 0])?;
1380 ///
1381 /// assert!(ndf.get(0));
1382 /// assert!(! ndf.get(1));
1383 /// assert!(ndf.get(2));
1384 /// assert!(! ndf.get(3));
1385 /// assert!(! ndf.get(8));
1386 /// assert!(! ndf.get(80));
1387 /// # assert!(! ndf.human_readable());
1388 /// # Ok(()) }
1389 /// ```
1390 pub fn get(&self, bit: usize) -> bool {
1391 self.0.get(bit)
1392 }
1393
1394 /// Sets the specified notation data flag.
1395 ///
1396 /// # Examples
1397 ///
1398 /// ```
1399 /// use sequoia_openpgp as openpgp;
1400 /// use openpgp::packet::signature::subpacket::NotationDataFlags;
1401 ///
1402 /// # fn main() -> openpgp::Result<()> {
1403 /// let ndf = NotationDataFlags::empty().set(0)?.set(2)?;
1404 ///
1405 /// assert!(ndf.get(0));
1406 /// assert!(! ndf.get(1));
1407 /// assert!(ndf.get(2));
1408 /// assert!(! ndf.get(3));
1409 /// # assert!(! ndf.human_readable());
1410 /// # Ok(()) }
1411 /// ```
1412 pub fn set(mut self, bit: usize) -> Result<Self> {
1413 assert_eq!(self.0.as_bytes().len(), 4);
1414 let byte = bit / 8;
1415 if byte < 4 {
1416 self.0.set(bit);
1417 Ok(self)
1418 } else {
1419 Err(Error::InvalidArgument(
1420 format!("flag index out of bounds: {}", bit)).into())
1421 }
1422 }
1423
1424 /// Clears the specified notation data flag.
1425 ///
1426 /// # Examples
1427 ///
1428 /// ```
1429 /// use sequoia_openpgp as openpgp;
1430 /// use openpgp::packet::signature::subpacket::NotationDataFlags;
1431 ///
1432 /// # fn main() -> openpgp::Result<()> {
1433 /// let ndf = NotationDataFlags::empty().set(0)?.set(2)?.clear(2)?;
1434 ///
1435 /// assert!(ndf.get(0));
1436 /// assert!(! ndf.get(1));
1437 /// assert!(! ndf.get(2));
1438 /// assert!(! ndf.get(3));
1439 /// # assert!(! ndf.human_readable());
1440 /// # Ok(()) }
1441 /// ```
1442 pub fn clear(mut self, bit: usize) -> Result<Self> {
1443 assert_eq!(self.0.as_bytes().len(), 4);
1444 let byte = bit / 8;
1445 if byte < 4 {
1446 self.0.clear(bit);
1447 Ok(self)
1448 } else {
1449 Err(Error::InvalidArgument(
1450 format!("flag index out of bounds: {}", bit)).into())
1451 }
1452 }
1453
1454 /// Returns whether the value is human-readable.
1455 pub fn human_readable(&self) -> bool {
1456 self.get(NOTATION_DATA_FLAG_HUMAN_READABLE)
1457 }
1458
1459 /// Asserts that the value is human-readable.
1460 pub fn set_human_readable(self) -> Self {
1461 self.set(NOTATION_DATA_FLAG_HUMAN_READABLE).unwrap()
1462 }
1463
1464 /// Clear the assertion that the value is human-readable.
1465 pub fn clear_human_readable(self) -> Self {
1466 self.clear(NOTATION_DATA_FLAG_HUMAN_READABLE).unwrap()
1467 }
1468}
1469
1470/// Holds an arbitrary, well-structured subpacket.
1471///
1472/// The `SubpacketValue` enum holds a [`Subpacket`]'s value. The
1473/// values are well-structured in the sense that they have been parsed
1474/// into Sequoia's native data types rather than just holding the raw
1475/// byte vector. For instance, the [`Issuer`] variant holds a
1476/// [`KeyID`].
1477///
1478/// [`Issuer`]: SubpacketValue::Issuer
1479/// [`KeyID`]: super::super::super::KeyID
1480#[non_exhaustive]
1481#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
1482pub enum SubpacketValue {
1483 /// An unknown subpacket.
1484 Unknown {
1485 /// The unknown subpacket's tag.
1486 tag: SubpacketTag,
1487 /// The unknown subpacket's uninterpreted body.
1488 body: Vec<u8>
1489 },
1490
1491 /// The time the signature was made.
1492 ///
1493 /// See [Section 5.2.3.11 of RFC 9580] for details.
1494 ///
1495 /// [Section 5.2.3.11 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
1496 SignatureCreationTime(Timestamp),
1497 /// The validity period of the signature.
1498 ///
1499 /// The validity is relative to the time stored in the signature's
1500 /// Signature Creation Time subpacket.
1501 ///
1502 /// See [Section 5.2.3.18 of RFC 9580] for details.
1503 ///
1504 /// [Section 5.2.3.18 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
1505 SignatureExpirationTime(Duration),
1506 /// Whether a signature should be published.
1507 ///
1508 /// See [Section 5.2.3.19 of RFC 9580] for details.
1509 ///
1510 /// [Section 5.2.3.19 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.19
1511 ExportableCertification(bool),
1512 /// Signer asserts that the key is not only valid but also trustworthy at
1513 /// the specified level.
1514 ///
1515 /// See [Section 5.2.3.21 of RFC 9580] for details.
1516 ///
1517 /// [Section 5.2.3.21 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
1518 TrustSignature {
1519 /// Trust level, or depth.
1520 ///
1521 /// Level 0 has the same meaning as an ordinary validity
1522 /// signature. Level 1 means that the signed key is asserted
1523 /// to be a valid trusted introducer, with the 2nd octet of
1524 /// the body specifying the degree of trust. Level 2 means
1525 /// that the signed key is asserted to be trusted to issue
1526 /// level 1 trust signatures, i.e., that it is a "meta
1527 /// introducer".
1528 level: u8,
1529
1530 /// Trust amount.
1531 ///
1532 /// This is interpreted such that values less than 120
1533 /// indicate partial trust and values of 120 or greater
1534 /// indicate complete trust. Implementations SHOULD emit
1535 /// values of 60 for partial trust and 120 for complete trust.
1536 trust: u8,
1537 },
1538 /// Used in conjunction with Trust Signature packets (of level > 0) to
1539 /// limit the scope of trust that is extended.
1540 ///
1541 /// See [Section 5.2.3.22 of RFC 9580] for details.
1542 ///
1543 /// [Section 5.2.3.22 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.22
1544 ///
1545 /// Note: The RFC requires that the serialized form includes a
1546 /// trailing NUL byte. When Sequoia parses the regular expression
1547 /// subpacket, it strips the trailing NUL. (If it doesn't include
1548 /// a NUL, then parsing fails.) Likewise, when it serializes a
1549 /// regular expression subpacket, it unconditionally adds a NUL.
1550 RegularExpression(Vec<u8>),
1551 /// Whether a signature can later be revoked.
1552 ///
1553 /// See [Section 5.2.3.20 of RFC 9580] for details.
1554 ///
1555 /// [Section 5.2.3.20 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.20
1556 Revocable(bool),
1557 /// The validity period of the key.
1558 ///
1559 /// The validity period is relative to the key's (not the signature's) creation time.
1560 ///
1561 /// See [Section 5.2.3.13 of RFC 9580] for details.
1562 ///
1563 /// [Section 5.2.3.13 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
1564 KeyExpirationTime(Duration),
1565 /// The Symmetric algorithms that the certificate holder prefers.
1566 ///
1567 /// See [Section 5.2.3.14 of RFC 9580] for details.
1568 ///
1569 /// [Section 5.2.3.14 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.14
1570 PreferredSymmetricAlgorithms(Vec<SymmetricAlgorithm>),
1571 /// Authorizes the specified key to issue revocation signatures for this
1572 /// certificate.
1573 ///
1574 /// See [Section 5.2.3.23 of RFC 9580] for details.
1575 ///
1576 /// [Section 5.2.3.23 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
1577 RevocationKey(RevocationKey),
1578 /// The OpenPGP Key ID of the key issuing the signature.
1579 ///
1580 /// See [Section 5.2.3.12 of RFC 9580] for details.
1581 ///
1582 /// [Section 5.2.3.12 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
1583 Issuer(KeyID),
1584 /// A "notation" on the signature.
1585 ///
1586 /// See [Section 5.2.3.24 of RFC 9580] for details.
1587 ///
1588 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
1589 NotationData(NotationData),
1590 /// The Hash algorithms that the certificate holder prefers.
1591 ///
1592 /// See [Section 5.2.3.16 of RFC 9580] for details.
1593 ///
1594 /// [Section 5.2.3.16 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.16
1595 PreferredHashAlgorithms(Vec<HashAlgorithm>),
1596 /// The compression algorithms that the certificate holder prefers.
1597 ///
1598 /// See [Section 5.2.3.17 of RFC 9580] for details.
1599 ///
1600 /// [Section 5.2.3.17 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.17
1601 PreferredCompressionAlgorithms(Vec<CompressionAlgorithm>),
1602 /// A list of flags that indicate preferences that the certificate
1603 /// holder has about how the key is handled by a key server.
1604 ///
1605 /// See [Section 5.2.3.25 of RFC 9580] for details.
1606 ///
1607 /// [Section 5.2.3.25 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.25
1608 KeyServerPreferences(KeyServerPreferences),
1609 /// The URI of a key server where the certificate holder keeps
1610 /// their certificate up to date.
1611 ///
1612 /// See [Section 5.2.3.26 of RFC 9580] for details.
1613 ///
1614 /// [Section 5.2.3.26 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.26
1615 PreferredKeyServer(Vec<u8>),
1616 /// A flag in a User ID's self-signature that states whether this
1617 /// User ID is the primary User ID for this certificate.
1618 ///
1619 /// See [Section 5.2.3.27 of RFC 9580] for details.
1620 ///
1621 /// [Section 5.2.3.27 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
1622 PrimaryUserID(bool),
1623 /// The URI of a document that describes the policy under which
1624 /// the signature was issued.
1625 ///
1626 /// See [Section 5.2.3.28 of RFC 9580] for details.
1627 ///
1628 /// [Section 5.2.3.28 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.28
1629 PolicyURI(Vec<u8>),
1630 /// A list of flags that hold information about a key.
1631 ///
1632 /// See [Section 5.2.3.29 of RFC 9580] for details.
1633 ///
1634 /// [Section 5.2.3.29 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
1635 KeyFlags(KeyFlags),
1636 /// The User ID that is responsible for the signature.
1637 ///
1638 /// See [Section 5.2.3.30 of RFC 9580] for details.
1639 ///
1640 /// [Section 5.2.3.30 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.30
1641 SignersUserID(Vec<u8>),
1642 /// The reason for a revocation, used in key revocations and
1643 /// certification revocation signatures.
1644 ///
1645 /// See [Section 5.2.3.31 of RFC 9580] for details.
1646 ///
1647 /// [Section 5.2.3.31 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.31
1648 ReasonForRevocation {
1649 /// Machine-readable reason for revocation.
1650 code: ReasonForRevocation,
1651
1652 /// Human-readable reason for revocation.
1653 reason: Vec<u8>,
1654 },
1655 /// The OpenPGP features a user's implementation supports.
1656 ///
1657 /// See [Section 5.2.3.32 of RFC 9580] for details.
1658 ///
1659 /// [Section 5.2.3.32 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.32
1660 Features(Features),
1661 /// A signature to which this signature refers.
1662 ///
1663 /// See [Section 5.2.3.33 of RFC 9580] for details.
1664 ///
1665 /// [Section 5.2.3.33 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
1666 SignatureTarget {
1667 /// Public-key algorithm of the target signature.
1668 pk_algo: PublicKeyAlgorithm,
1669 /// Hash algorithm of the target signature.
1670 hash_algo: HashAlgorithm,
1671 /// Hash digest of the target signature.
1672 digest: Vec<u8>,
1673 },
1674 /// A complete Signature packet body.
1675 ///
1676 /// This is used to store a backsig in a subkey binding signature.
1677 ///
1678 /// See [Section 5.2.3.34 of RFC 9580] for details.
1679 ///
1680 /// [Section 5.2.3.34 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.34
1681 EmbeddedSignature(Signature),
1682
1683 /// The Fingerprint of the key that issued the signature.
1684 ///
1685 /// See [Section 5.2.3.35 of RFC 9580]
1686 /// for details.
1687 ///
1688 /// [Section 5.2.3.35 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
1689 IssuerFingerprint(Fingerprint),
1690
1691 /// Who the signed message was intended for.
1692 ///
1693 /// See [Section 5.2.3.36 of RFC 9580] for details.
1694 ///
1695 /// [Section 5.2.3.36 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
1696 IntendedRecipient(Fingerprint),
1697
1698 /// The Approved Certifications subpacket (experimental).
1699 ///
1700 /// Allows the certificate holder to attest to third party
1701 /// certifications, allowing them to be distributed with the
1702 /// certificate. This can be used to address certificate flooding
1703 /// concerns.
1704 ///
1705 /// See [Section 2.2 of draft-dkg-openpgp-1pa3pc-02] for details.
1706 ///
1707 /// [Section 2.2 of draft-dkg-openpgp-1pa3pc-02]: https://www.ietf.org/archive/id/draft-dkg-openpgp-1pa3pc-02.html#approved-certifications-subpacket
1708 ApprovedCertifications(Vec<Box<[u8]>>),
1709
1710 /// The AEAD Ciphersuites that the certificate holder prefers.
1711 ///
1712 /// A series of paired algorithm identifiers indicating how the
1713 /// keyholder prefers to receive version 2 Symmetrically Encrypted
1714 /// Integrity Protected Data. Each pair of octets indicates a
1715 /// combination of a symmetric cipher and an AEAD mode that the
1716 /// key holder prefers to use.
1717 ///
1718 /// It is assumed that only the combinations of algorithms listed
1719 /// are supported by the recipient's software, with the exception
1720 /// of the mandatory-to-implement combination of AES-128 and OCB.
1721 /// If AES-128 and OCB are not found in the subpacket, it is
1722 /// implicitly listed at the end.
1723 ///
1724 /// See [Section 5.2.3.15 of RFC 9580] for details.
1725 ///
1726 /// [Section 5.2.3.15 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites
1727 PreferredAEADCiphersuites(Vec<(SymmetricAlgorithm, AEADAlgorithm)>),
1728}
1729assert_send_and_sync!(SubpacketValue);
1730
1731#[cfg(test)]
1732impl ArbitraryBounded for SubpacketValue {
1733 fn arbitrary_bounded(g: &mut Gen, depth: usize) -> Self {
1734 use self::SubpacketValue::*;
1735 use crate::arbitrary_helper::gen_arbitrary_from_range;
1736
1737 #[allow(deprecated)]
1738 loop {
1739 #[allow(deprecated)]
1740 break match gen_arbitrary_from_range(0..27, g) {
1741 0 => SignatureCreationTime(Arbitrary::arbitrary(g)),
1742 1 => SignatureExpirationTime(Arbitrary::arbitrary(g)),
1743 2 => ExportableCertification(Arbitrary::arbitrary(g)),
1744 3 => TrustSignature {
1745 level: Arbitrary::arbitrary(g),
1746 trust: Arbitrary::arbitrary(g),
1747 },
1748 4 => RegularExpression(Arbitrary::arbitrary(g)),
1749 5 => Revocable(Arbitrary::arbitrary(g)),
1750 6 => KeyExpirationTime(Arbitrary::arbitrary(g)),
1751 7 => PreferredSymmetricAlgorithms(Arbitrary::arbitrary(g)),
1752 8 => RevocationKey(Arbitrary::arbitrary(g)),
1753 9 => Issuer(Arbitrary::arbitrary(g)),
1754 10 => NotationData(Arbitrary::arbitrary(g)),
1755 11 => PreferredHashAlgorithms(Arbitrary::arbitrary(g)),
1756 12 => PreferredCompressionAlgorithms(Arbitrary::arbitrary(g)),
1757 13 => KeyServerPreferences(Arbitrary::arbitrary(g)),
1758 14 => PreferredKeyServer(Arbitrary::arbitrary(g)),
1759 15 => PrimaryUserID(Arbitrary::arbitrary(g)),
1760 16 => PolicyURI(Arbitrary::arbitrary(g)),
1761 17 => KeyFlags(Arbitrary::arbitrary(g)),
1762 18 => SignersUserID(Arbitrary::arbitrary(g)),
1763 19 => ReasonForRevocation {
1764 code: Arbitrary::arbitrary(g),
1765 reason: Arbitrary::arbitrary(g),
1766 },
1767 20 => Features(Arbitrary::arbitrary(g)),
1768 21 => SignatureTarget {
1769 pk_algo: Arbitrary::arbitrary(g),
1770 hash_algo: Arbitrary::arbitrary(g),
1771 digest: Arbitrary::arbitrary(g),
1772 },
1773 22 if depth == 0 => continue, // Don't recurse, try again.
1774 22 => EmbeddedSignature(
1775 ArbitraryBounded::arbitrary_bounded(g, depth - 1)),
1776 23 => IssuerFingerprint(Arbitrary::arbitrary(g)),
1777 24 => Unknown {
1778 tag: SubpacketTag::PreferredAEADAlgorithms,
1779 body: Arbitrary::arbitrary(g),
1780 },
1781 25 => IntendedRecipient(Arbitrary::arbitrary(g)),
1782 26 => PreferredAEADCiphersuites(Arbitrary::arbitrary(g)),
1783 _ => unreachable!(),
1784 }
1785 }
1786 }
1787}
1788
1789#[cfg(test)]
1790impl_arbitrary_with_bound!(SubpacketValue);
1791
1792impl SubpacketValue {
1793 /// Returns the subpacket tag for this value.
1794 pub fn tag(&self) -> SubpacketTag {
1795 use self::SubpacketValue::*;
1796 #[allow(deprecated)]
1797 match &self {
1798 SignatureCreationTime(_) => SubpacketTag::SignatureCreationTime,
1799 SignatureExpirationTime(_) =>
1800 SubpacketTag::SignatureExpirationTime,
1801 ExportableCertification(_) =>
1802 SubpacketTag::ExportableCertification,
1803 TrustSignature { .. } => SubpacketTag::TrustSignature,
1804 RegularExpression(_) => SubpacketTag::RegularExpression,
1805 Revocable(_) => SubpacketTag::Revocable,
1806 KeyExpirationTime(_) => SubpacketTag::KeyExpirationTime,
1807 PreferredSymmetricAlgorithms(_) =>
1808 SubpacketTag::PreferredSymmetricAlgorithms,
1809 RevocationKey { .. } => SubpacketTag::RevocationKey,
1810 Issuer(_) => SubpacketTag::Issuer,
1811 NotationData(_) => SubpacketTag::NotationData,
1812 PreferredHashAlgorithms(_) =>
1813 SubpacketTag::PreferredHashAlgorithms,
1814 PreferredCompressionAlgorithms(_) =>
1815 SubpacketTag::PreferredCompressionAlgorithms,
1816 KeyServerPreferences(_) => SubpacketTag::KeyServerPreferences,
1817 PreferredKeyServer(_) => SubpacketTag::PreferredKeyServer,
1818 PrimaryUserID(_) => SubpacketTag::PrimaryUserID,
1819 PolicyURI(_) => SubpacketTag::PolicyURI,
1820 KeyFlags(_) => SubpacketTag::KeyFlags,
1821 SignersUserID(_) => SubpacketTag::SignersUserID,
1822 ReasonForRevocation { .. } => SubpacketTag::ReasonForRevocation,
1823 Features(_) => SubpacketTag::Features,
1824 SignatureTarget { .. } => SubpacketTag::SignatureTarget,
1825 EmbeddedSignature(_) => SubpacketTag::EmbeddedSignature,
1826 IssuerFingerprint(_) => SubpacketTag::IssuerFingerprint,
1827 IntendedRecipient(_) => SubpacketTag::IntendedRecipient,
1828 ApprovedCertifications(_) => SubpacketTag::ApprovedCertifications,
1829 PreferredAEADCiphersuites(_) =>
1830 SubpacketTag::PreferredAEADCiphersuites,
1831 Unknown { tag, .. } => *tag,
1832 }
1833 }
1834}
1835
1836/// Signature subpackets.
1837///
1838/// Most of a signature's attributes are not stored in fixed fields,
1839/// but in so-called subpackets. These subpackets are stored in a
1840/// [`Signature`]'s so-called subpacket areas, which are effectively
1841/// small key-value stores. The keys are subpacket tags
1842/// ([`SubpacketTag`]). The values are well-structured
1843/// ([`SubpacketValue`]).
1844///
1845/// [`Signature`]: super::super::Signature
1846///
1847/// In addition to their key and value, subpackets also include a
1848/// critical flag. When set, this flag indicates to the OpenPGP
1849/// implementation that if it doesn't understand the subpacket, it
1850/// must consider the signature to be invalid. (Likewise, if it isn't
1851/// set, then it means that it is safe for the implementation to
1852/// ignore the subpacket.) This enables forward compatibility with
1853/// security-relevant extensions.
1854///
1855/// It is possible to control how Sequoia's higher-level functionality
1856/// handles unknown, critical subpackets using a [`Policy`] object.
1857/// Depending on the degree of control required, it may be sufficient
1858/// to customize a [`StandardPolicy`] object using, for instance, the
1859/// [`StandardPolicy::accept_critical_subpacket`] method.
1860///
1861/// [`Policy`]: crate::policy::Policy
1862/// [`StandardPolicy`]: crate::policy::StandardPolicy
1863/// [`StandardPolicy::accept_critical_subpacket`]: crate::policy::StandardPolicy::accept_critical_subpacket()
1864///
1865/// The subpacket system is extensible in two ways. First, although
1866/// limited, the subpacket name space is not exhausted. So, it is
1867/// possible to introduce new packets. Second, one of the subpackets,
1868/// the [`Notation Data`] subpacket ([`NotationData`]), is explicitly
1869/// designed for adding arbitrary data to signatures.
1870///
1871/// [`Notation Data`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
1872///
1873/// Subpackets are described in [Section 5.2.3.7 of RFC 9580].
1874///
1875/// [Section 5.2.3.7 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.7
1876pub struct Subpacket {
1877 /// The length.
1878 ///
1879 /// In order not to break signatures, we need to be able to
1880 /// roundtrip the subpackets, perfectly reproducing all the bits.
1881 /// To allow for suboptimal encoding of lengths, we store the
1882 /// length when we parse subpackets.
1883 pub(crate) // For serialize/mod.rs, parse/parse.rs.
1884 length: SubpacketLength,
1885 /// Critical flag.
1886 critical: bool,
1887 /// Packet value, must match packet type.
1888 value: SubpacketValue,
1889 /// Whether the information in this subpacket are
1890 /// authenticated in the context of its signature.
1891 authenticated: atomic::AtomicBool,
1892}
1893assert_send_and_sync!(Subpacket);
1894
1895impl Clone for Subpacket {
1896 fn clone(&self) -> Self {
1897 Subpacket {
1898 length: self.length.clone(),
1899 critical: self.critical,
1900 value: self.value.clone(),
1901 authenticated: self.authenticated().into(),
1902 }
1903 }
1904}
1905
1906impl PartialEq for Subpacket {
1907 fn eq(&self, other: &Subpacket) -> bool {
1908 self.cmp(other) == Ordering::Equal
1909 }
1910}
1911
1912impl Eq for Subpacket {}
1913
1914impl PartialOrd for Subpacket {
1915 fn partial_cmp(&self, other: &Subpacket) -> Option<Ordering> {
1916 Some(self.cmp(other))
1917 }
1918}
1919
1920impl Ord for Subpacket {
1921 fn cmp(&self, other: &Subpacket) -> Ordering {
1922 self.length.cmp(&other.length)
1923 .then_with(|| self.critical.cmp(&other.critical))
1924 .then_with(|| self.value.cmp(&other.value))
1925 }
1926}
1927
1928impl Hash for Subpacket {
1929 fn hash<H: Hasher>(&self, state: &mut H) {
1930 self.length.hash(state);
1931 self.critical.hash(state);
1932 self.value.hash(state);
1933 }
1934}
1935
1936#[cfg(test)]
1937impl ArbitraryBounded for Subpacket {
1938 fn arbitrary_bounded(g: &mut Gen, depth: usize) -> Self {
1939 use crate::arbitrary_helper::gen_arbitrary_from_range;
1940
1941 fn encode_non_optimal(length: usize) -> SubpacketLength {
1942 // Calculate length the same way as Subpacket::new.
1943 let length = 1 /* Tag */ + length as u32;
1944
1945 let mut len_vec = Vec::<u8>::with_capacity(5);
1946 len_vec.push(0xFF);
1947 len_vec.extend_from_slice(&length.to_be_bytes());
1948 SubpacketLength::new(length, Some(len_vec))
1949 }
1950
1951 let critical = <bool>::arbitrary(g);
1952 let use_nonoptimal_encoding = <bool>::arbitrary(g);
1953 // We don't want to overrepresent large subpackets.
1954 let create_large_subpacket =
1955 gen_arbitrary_from_range(0..25, g) == 0;
1956
1957 let value = if create_large_subpacket {
1958 // Choose a size which makes sure the subpacket length must be
1959 // encoded with 2 or 5 octets.
1960 let value_size = gen_arbitrary_from_range(7000..9000, g);
1961 let nd = NotationData {
1962 flags: Arbitrary::arbitrary(g),
1963 name: Arbitrary::arbitrary(g),
1964 value: (0..value_size)
1965 .map(|_| <u8>::arbitrary(g))
1966 .collect::<Vec<u8>>(),
1967 };
1968 SubpacketValue::NotationData(nd)
1969 } else {
1970 SubpacketValue::arbitrary_bounded(g, depth)
1971 };
1972
1973 if use_nonoptimal_encoding {
1974 let length = encode_non_optimal(value.serialized_len());
1975 Subpacket::with_length(length, value, critical)
1976 } else {
1977 Subpacket::new(value, critical).unwrap()
1978 }
1979 }
1980}
1981
1982#[cfg(test)]
1983impl_arbitrary_with_bound!(Subpacket);
1984
1985impl fmt::Debug for Subpacket {
1986 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1987 let mut s = f.debug_struct("Subpacket");
1988 if self.length.raw.is_some() {
1989 s.field("length", &self.length);
1990 }
1991 if self.critical {
1992 s.field("critical", &self.critical);
1993 }
1994 s.field("value", &self.value);
1995 s.field("authenticated", &self.authenticated());
1996 s.finish()
1997 }
1998}
1999
2000impl Subpacket {
2001 /// Creates a new Subpacket.
2002 pub fn new(value: SubpacketValue, critical: bool)
2003 -> Result<Subpacket> {
2004 Ok(Self::with_length(
2005 SubpacketLength::from(1 /* Tag */ + value.serialized_len() as u32),
2006 value, critical))
2007 }
2008
2009 /// Creates a new subpacket with the given length and tag.
2010 pub(crate) fn with_length(length: SubpacketLength,
2011 value: SubpacketValue,
2012 critical: bool)
2013 -> Subpacket {
2014 Subpacket {
2015 length,
2016 critical,
2017 value,
2018 authenticated: false.into(),
2019 }
2020 }
2021
2022 /// Returns whether the critical bit is set.
2023 pub fn critical(&self) -> bool {
2024 self.critical
2025 }
2026
2027 /// Returns the Subpacket's tag.
2028 pub fn tag(&self) -> SubpacketTag {
2029 self.value.tag()
2030 }
2031
2032 /// Returns the Subpacket's value.
2033 pub fn value(&self) -> &SubpacketValue {
2034 &self.value
2035 }
2036
2037 /// Returns whether the information in this subpacket has been
2038 /// authenticated.
2039 ///
2040 /// There are three ways a subpacket can be authenticated:
2041 ///
2042 /// - It is in the hashed subpacket area and the signature has
2043 /// been verified.
2044 /// - It is in the unhashed subpacket area and the information
2045 /// is self-authenticating and has been authenticated by
2046 /// Sequoia. This can be done for issuer information and
2047 /// embedded Signatures.
2048 /// - The subpacket has been authenticated by the user and
2049 /// marked as such using [`Subpacket::set_authenticated`].
2050 ///
2051 /// Note: The authentication is only valid in the context of the
2052 /// signature the subpacket is in. If the authenticated
2053 /// `Subpacket` is added to a [`SubpacketArea`], the flag is
2054 /// cleared.
2055 pub fn authenticated(&self) -> bool {
2056 self.authenticated.load(atomic::Ordering::Relaxed)
2057 }
2058
2059 /// Marks the information in this subpacket as authenticated or
2060 /// not.
2061 ///
2062 /// See [`Subpacket::authenticated`] for more information.
2063 ///
2064 /// [`Subpacket::authenticated`]: Self::authenticated()
2065 pub fn set_authenticated(&self, authenticated: bool) -> bool {
2066 self.authenticated.swap(authenticated, atomic::Ordering::Relaxed)
2067 }
2068}
2069
2070#[derive(Clone, Debug)]
2071pub(crate) struct SubpacketLength {
2072 /// The length.
2073 pub(crate) len: u32,
2074 /// The length encoding used in the serialized form.
2075 /// If this is `None`, optimal encoding will be used.
2076 pub(crate) raw: Option<Vec<u8>>,
2077}
2078
2079impl From<u32> for SubpacketLength {
2080 fn from(len: u32) -> Self {
2081 SubpacketLength {
2082 len, raw: None,
2083 }
2084 }
2085}
2086
2087impl PartialEq for SubpacketLength {
2088 fn eq(&self, other: &Self) -> bool {
2089 self.cmp(other) == Ordering::Equal
2090 }
2091}
2092
2093impl Eq for SubpacketLength {}
2094
2095impl Hash for SubpacketLength {
2096 fn hash<H: Hasher>(&self, state: &mut H) {
2097 match &self.raw {
2098 Some(raw) => raw.hash(state),
2099 None => {
2100 let l = self.serialized_len();
2101 let mut raw = [0; 5];
2102 self.serialize_into(&mut raw[..l]).unwrap();
2103 raw[..l].hash(state);
2104 },
2105 }
2106 }
2107}
2108
2109impl PartialOrd for SubpacketLength {
2110 fn partial_cmp(&self, other: &SubpacketLength) -> Option<Ordering> {
2111 Some(self.cmp(other))
2112 }
2113}
2114
2115impl Ord for SubpacketLength {
2116 fn cmp(&self, other: &SubpacketLength) -> Ordering {
2117 match (&self.raw, &other.raw) {
2118 (None, None) => {
2119 self.len.cmp(&other.len)
2120 },
2121 // Compare serialized representations if at least one is given
2122 (Some(self_raw), Some(other_raw)) => {
2123 self_raw.cmp(other_raw)
2124 },
2125 (Some(self_raw), None) => {
2126 let mut other_raw = [0; 5];
2127 other.serialize_into(&mut other_raw[..self.serialized_len()])
2128 .unwrap();
2129 self_raw[..].cmp(&other_raw[..self.serialized_len()])
2130 },
2131 (None, Some(other_raw)) => {
2132 let mut self_raw = [0; 5];
2133 self.serialize_into(&mut self_raw[..self.serialized_len()])
2134 .unwrap();
2135 self_raw[..self.serialized_len()].cmp(&other_raw[..])
2136 },
2137 }
2138 }
2139}
2140
2141impl SubpacketLength {
2142 pub(crate) fn new(len: u32, raw: Option<Vec<u8>>) -> Self {
2143 Self { len, raw }
2144 }
2145
2146 /// Returns the length.
2147 pub(crate) fn len(&self) -> usize {
2148 self.len as usize
2149 }
2150
2151 /// Returns the length of the optimal encoding of `len`.
2152 pub(crate) fn len_optimal_encoding(len: u32) -> usize {
2153 BodyLength::serialized_len(&BodyLength::Full(len))
2154 }
2155}
2156
2157/// Subpacket storage.
2158///
2159/// Subpackets are stored either in a so-called hashed area or a
2160/// so-called unhashed area. Packets stored in the hashed area are
2161/// protected by the signature's hash whereas packets stored in the
2162/// unhashed area are not. Generally, two types of information are
2163/// stored in the unhashed area: self-authenticating data (the
2164/// `Issuer` subpacket, the `Issuer Fingerprint` subpacket, and the
2165/// `Embedded Signature` subpacket), and hints, like the features
2166/// subpacket.
2167///
2168/// When accessing subpackets directly via `SubpacketArea`s, the
2169/// subpackets are only looked up in the hashed area unless the
2170/// packets are self-authenticating in which case subpackets from the
2171/// hash area are preferred. To return packets from a specific area,
2172/// use the `hashed_area` and `unhashed_area` methods to get the
2173/// specific methods and then use their accessors.
2174#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
2175pub struct SubpacketAreas {
2176 /// Subpackets that are part of the signature.
2177 hashed_area: SubpacketArea,
2178 /// Subpackets that are _not_ part of the signature.
2179 unhashed_area: SubpacketArea,
2180}
2181assert_send_and_sync!(SubpacketAreas);
2182
2183#[cfg(test)]
2184impl ArbitraryBounded for SubpacketAreas {
2185 fn arbitrary_bounded(g: &mut Gen, depth: usize) -> Self {
2186 SubpacketAreas::new(ArbitraryBounded::arbitrary_bounded(g, depth),
2187 ArbitraryBounded::arbitrary_bounded(g, depth))
2188 }
2189}
2190
2191#[cfg(test)]
2192impl_arbitrary_with_bound!(SubpacketAreas);
2193
2194impl SubpacketAreas {
2195 /// Returns a new `SubpacketAreas` object.
2196 pub fn new(hashed_area: SubpacketArea,
2197 unhashed_area: SubpacketArea) -> Self {
2198 Self {
2199 hashed_area,
2200 unhashed_area,
2201 }
2202 }
2203
2204 /// Gets a reference to the hashed area.
2205 pub fn hashed_area(&self) -> &SubpacketArea {
2206 &self.hashed_area
2207 }
2208
2209 /// Gets a mutable reference to the hashed area.
2210 ///
2211 /// Note: if you modify the hashed area of a [`Signature4`], this
2212 /// will invalidate the signature. Instead, you should normally
2213 /// convert the [`Signature4`] into a [`signature::SignatureBuilder`],
2214 /// modify that, and then create a new signature.
2215 pub fn hashed_area_mut(&mut self) -> &mut SubpacketArea {
2216 &mut self.hashed_area
2217 }
2218
2219 /// Gets a reference to the unhashed area.
2220 pub fn unhashed_area(&self) -> &SubpacketArea {
2221 &self.unhashed_area
2222 }
2223
2224 /// Gets a mutable reference to the unhashed area.
2225 pub fn unhashed_area_mut(&mut self) -> &mut SubpacketArea {
2226 &mut self.unhashed_area
2227 }
2228
2229 /// Sorts the subpacket areas.
2230 ///
2231 /// See [`SubpacketArea::sort()`].
2232 ///
2233 pub fn sort(&mut self) {
2234 self.hashed_area.sort();
2235 self.unhashed_area.sort();
2236 }
2237
2238 /// Returns a reference to the *last* instance of the specified
2239 /// subpacket, if any.
2240 ///
2241 /// This function returns the last instance of the specified
2242 /// subpacket in the subpacket areas in which it can occur. Thus,
2243 /// when looking for the `Signature Creation Time` subpacket, this
2244 /// function only considers the hashed subpacket area. But, when
2245 /// looking for the `Embedded Signature` subpacket, this function
2246 /// considers both subpacket areas.
2247 ///
2248 /// Unknown subpackets are assumed to only safely occur in the
2249 /// hashed subpacket area. Thus, any instances of them in the
2250 /// unhashed area are ignored.
2251 ///
2252 /// For subpackets that can safely occur in both subpacket areas,
2253 /// this function prefers instances in the hashed subpacket area.
2254 pub fn subpacket(&self, tag: SubpacketTag) -> Option<&Subpacket> {
2255 if let Some(sb) = self.hashed_area().subpacket(tag) {
2256 return Some(sb);
2257 }
2258
2259 // There are a couple of subpackets that we are willing to
2260 // take from the unhashed area. The others we ignore
2261 // completely.
2262 if !(tag == SubpacketTag::Issuer
2263 || tag == SubpacketTag::IssuerFingerprint
2264 || tag == SubpacketTag::EmbeddedSignature) {
2265 return None;
2266 }
2267
2268 self.unhashed_area().subpacket(tag)
2269 }
2270
2271 /// Returns a mutable reference to the *last* instance of the
2272 /// specified subpacket, if any.
2273 ///
2274 /// This function returns the last instance of the specified
2275 /// subpacket in the subpacket areas in which it can occur. Thus,
2276 /// when looking for the `Signature Creation Time` subpacket, this
2277 /// function only considers the hashed subpacket area. But, when
2278 /// looking for the `Embedded Signature` subpacket, this function
2279 /// considers both subpacket areas.
2280 ///
2281 /// Unknown subpackets are assumed to only safely occur in the
2282 /// hashed subpacket area. Thus, any instances of them in the
2283 /// unhashed area are ignored.
2284 ///
2285 /// For subpackets that can safely occur in both subpacket areas,
2286 /// this function prefers instances in the hashed subpacket area.
2287 pub fn subpacket_mut(&mut self, tag: SubpacketTag)
2288 -> Option<&mut Subpacket> {
2289 if let Some(_) = self.hashed_area().subpacket(tag) {
2290 return self.hashed_area_mut().subpacket_mut(tag);
2291 }
2292
2293 // There are a couple of subpackets that we are willing to
2294 // take from the unhashed area. The others we ignore
2295 // completely.
2296 if !(tag == SubpacketTag::Issuer
2297 || tag == SubpacketTag::IssuerFingerprint
2298 || tag == SubpacketTag::EmbeddedSignature) {
2299 return None;
2300 }
2301
2302 self.unhashed_area_mut().subpacket_mut(tag)
2303 }
2304
2305 /// Returns an iterator over all instances of the specified
2306 /// subpacket.
2307 ///
2308 /// This function returns an iterator over all instances of the
2309 /// specified subpacket in the subpacket areas in which it can
2310 /// occur. Thus, when looking for the `Issuer` subpacket, the
2311 /// iterator includes instances of the subpacket from both the
2312 /// hashed subpacket area and the unhashed subpacket area, but
2313 /// when looking for the `Signature Creation Time` subpacket, the
2314 /// iterator only includes instances of the subpacket from the
2315 /// hashed subpacket area; any instances of the subpacket in the
2316 /// unhashed subpacket area are ignored.
2317 ///
2318 /// Unknown subpackets are assumed to only safely occur in the
2319 /// hashed subpacket area. Thus, any instances of them in the
2320 /// unhashed area are ignored.
2321 pub fn subpackets(&self, tag: SubpacketTag)
2322 -> impl Iterator<Item = &Subpacket> + Send + Sync
2323 {
2324 // It would be nice to do:
2325 //
2326 // let iter = self.hashed_area().subpackets(tag);
2327 // if (subpacket allowed in unhashed area) {
2328 // iter.chain(self.unhashed_area().subpackets(tag))
2329 // } else {
2330 // iter
2331 // }
2332 //
2333 // but then we have different types. Instead, we need to
2334 // inline SubpacketArea::subpackets, add the additional
2335 // constraint in the closure, and hope that the optimizer is
2336 // smart enough to not unnecessarily iterate over the unhashed
2337 // area.
2338 self.hashed_area().subpackets(tag).chain(
2339 self.unhashed_area()
2340 .iter()
2341 .filter(move |sp| {
2342 (tag == SubpacketTag::Issuer
2343 || tag == SubpacketTag::IssuerFingerprint
2344 || tag == SubpacketTag::EmbeddedSignature)
2345 && sp.tag() == tag
2346 }))
2347 }
2348
2349 pub(crate) fn subpackets_mut(&mut self, tag: SubpacketTag)
2350 -> impl Iterator<Item = &mut Subpacket> + Send + Sync
2351 {
2352 self.hashed_area.subpackets_mut(tag).chain(
2353 self.unhashed_area
2354 .iter_mut()
2355 .filter(move |sp| {
2356 (tag == SubpacketTag::Issuer
2357 || tag == SubpacketTag::IssuerFingerprint
2358 || tag == SubpacketTag::EmbeddedSignature)
2359 && sp.tag() == tag
2360 }))
2361 }
2362
2363 /// Returns the value of the Signature Creation Time subpacket.
2364 ///
2365 /// The [Signature Creation Time subpacket] specifies when the
2366 /// signature was created. According to the standard, all
2367 /// signatures must include a Signature Creation Time subpacket in
2368 /// the signature's hashed area. This doesn't mean that the time
2369 /// stamp is correct: the issuer can always forge it.
2370 ///
2371 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
2372 ///
2373 /// If the subpacket is not present in the hashed subpacket area,
2374 /// this returns `None`.
2375 ///
2376 /// Note: if the signature contains multiple instances of this
2377 /// subpacket in the hashed subpacket area, the last one is
2378 /// returned.
2379 pub fn signature_creation_time(&self) -> Option<time::SystemTime> {
2380 // 4-octet time field
2381 if let Some(sb)
2382 = self.subpacket(SubpacketTag::SignatureCreationTime) {
2383 if let SubpacketValue::SignatureCreationTime(v) = sb.value {
2384 Some(v.into())
2385 } else {
2386 None
2387 }
2388 } else {
2389 None
2390 }
2391 }
2392
2393 /// Returns the value of the Signature Expiration Time subpacket.
2394 ///
2395 /// This function is called `signature_validity_period` and not
2396 /// `signature_expiration_time`, which would be more consistent
2397 /// with the subpacket's name, because the latter suggests an
2398 /// absolute time, but the time is actually relative to the
2399 /// signature's creation time, which is stored in the signature's
2400 /// [Signature Creation Time subpacket].
2401 ///
2402 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
2403 ///
2404 /// A [Signature Expiration Time subpacket] specifies when the
2405 /// signature expires. This is different from the [Key Expiration
2406 /// Time subpacket], which is accessed using
2407 /// [`SubpacketAreas::key_validity_period`], and used to
2408 /// specify when an associated key expires. The difference is
2409 /// that in the former case, the signature itself expires, but in
2410 /// the latter case, only the associated key expires. This
2411 /// difference is critical: if a binding signature expires, then
2412 /// an OpenPGP implementation will still consider the associated
2413 /// key to be valid if there is another valid binding signature,
2414 /// even if it is older than the expired signature; if the active
2415 /// binding signature indicates that the key has expired, then
2416 /// OpenPGP implementations will not fall back to an older binding
2417 /// signature.
2418 ///
2419 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
2420 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2421 /// [`SubpacketAreas::key_validity_period`]: SubpacketAreas::key_validity_period()
2422 ///
2423 /// There are several cases where having a signature expire is
2424 /// useful. Say Alice certifies Bob's certificate for
2425 /// `bob@example.org`. She can limit the lifetime of the
2426 /// certification to force her to reevaluate the certification
2427 /// shortly before it expires. For instance, is Bob still
2428 /// associated with `example.org`? Does she have reason to
2429 /// believe that his key has been compromised? Using an
2430 /// expiration is common in the X.509 ecosystem. For instance,
2431 /// [Let's Encrypt] issues certificates with 90-day lifetimes.
2432 ///
2433 /// [Let's Encrypt]: https://letsencrypt.org/2015/11/09/why-90-days.html
2434 ///
2435 /// Having signatures expire can also be useful when deploying
2436 /// software. For instance, you might have a service that
2437 /// installs an update if it has been signed by a trusted
2438 /// certificate. To prevent an adversary from coercing the
2439 /// service to install an older version, you could limit the
2440 /// signature's lifetime to just a few minutes.
2441 ///
2442 /// If the subpacket is not present in the hashed subpacket area,
2443 /// this returns `None`. If this function returns `None`, or the
2444 /// returned period is `0`, the signature does not expire.
2445 ///
2446 /// Note: if the signature contains multiple instances of this
2447 /// subpacket in the hashed subpacket area, the last one is
2448 /// returned.
2449 pub fn signature_validity_period(&self) -> Option<time::Duration> {
2450 // 4-octet time field
2451 if let Some(sb)
2452 = self.subpacket(SubpacketTag::SignatureExpirationTime) {
2453 if let SubpacketValue::SignatureExpirationTime(v) = sb.value {
2454 Some(v.into())
2455 } else {
2456 None
2457 }
2458 } else {
2459 None
2460 }
2461 }
2462
2463 /// Returns the value of the Signature Expiration Time subpacket
2464 /// as an absolute time.
2465 ///
2466 /// A [Signature Expiration Time subpacket] specifies when the
2467 /// signature expires. The value stored is not an absolute time,
2468 /// but a duration, which is relative to the Signature's creation
2469 /// time. To better reflect the subpacket's name, this method
2470 /// returns the absolute expiry time, and the
2471 /// [`SubpacketAreas::signature_validity_period`] method returns
2472 /// the subpacket's raw value.
2473 ///
2474 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
2475 /// [`SubpacketAreas::signature_validity_period`]: SubpacketAreas::signature_validity_period()
2476 ///
2477 /// The Signature Expiration Time subpacket is different from the
2478 /// [Key Expiration Time subpacket], which is accessed using
2479 /// [`SubpacketAreas::key_validity_period`], and used specifies
2480 /// when an associated key expires. The difference is that in the
2481 /// former case, the signature itself expires, but in the latter
2482 /// case, only the associated key expires. This difference is
2483 /// critical: if a binding signature expires, then an OpenPGP
2484 /// implementation will still consider the associated key to be
2485 /// valid if there is another valid binding signature, even if it
2486 /// is older than the expired signature; if the active binding
2487 /// signature indicates that the key has expired, then OpenPGP
2488 /// implementations will not fall back to an older binding
2489 /// signature.
2490 ///
2491 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2492 /// [`SubpacketAreas::key_validity_period`]: SubpacketAreas::key_validity_period()
2493 ///
2494 /// There are several cases where having a signature expire is
2495 /// useful. Say Alice certifies Bob's certificate for
2496 /// `bob@example.org`. She can limit the lifetime of the
2497 /// certification to force her to reevaluate the certification
2498 /// shortly before it expires. For instance, is Bob still
2499 /// associated with `example.org`? Does she have reason to
2500 /// believe that his key has been compromised? Using an
2501 /// expiration is common in the X.509 ecosystem. For instance,
2502 /// [Let's Encrypt] issues certificates with 90-day lifetimes.
2503 ///
2504 /// [Let's Encrypt]: https://letsencrypt.org/2015/11/09/why-90-days.html
2505 ///
2506 /// Having signatures expire can also be useful when deploying
2507 /// software. For instance, you might have a service that
2508 /// installs an update if it has been signed by a trusted
2509 /// certificate. To prevent an adversary from coercing the
2510 /// service to install an older version, you could limit the
2511 /// signature's lifetime to just a few minutes.
2512 ///
2513 /// If the subpacket is not present in the hashed subpacket area,
2514 /// this returns `None`. If this function returns `None`, the
2515 /// signature does not expire.
2516 ///
2517 /// Note: if the signature contains multiple instances of this
2518 /// subpacket in the hashed subpacket area, the last one is
2519 /// returned.
2520 // Note: If you update this function, also update
2521 // SignatureBuilder::signature_expiration_time.
2522 pub fn signature_expiration_time(&self) -> Option<time::SystemTime> {
2523 match (self.signature_creation_time(), self.signature_validity_period())
2524 {
2525 (Some(ct), Some(vp)) if vp.as_secs() > 0 => Some(ct + vp),
2526 _ => None,
2527 }
2528 }
2529
2530 /// Returns whether the signature is alive at the specified
2531 /// time.
2532 ///
2533 /// A signature is considered to be alive if `creation time -
2534 /// tolerance <= time` and `time < expiration time`.
2535 ///
2536 /// This function does not check whether the key is revoked.
2537 ///
2538 /// If `time` is `None`, then this function uses the current time
2539 /// for `time`.
2540 ///
2541 /// If `time` is `None`, and `clock_skew_tolerance` is `None`,
2542 /// then this function uses [`CLOCK_SKEW_TOLERANCE`] for the
2543 /// tolerance. If `time` is not `None `and `clock_skew_tolerance`
2544 /// is `None`, it uses no tolerance. The intuition here is that
2545 /// we only need a tolerance when checking if a signature is alive
2546 /// right now; if we are checking at a specific time, we don't
2547 /// want to use a tolerance.
2548 ///
2549 ///
2550 /// A small amount of tolerance for clock skew is necessary,
2551 /// because although most computers synchronize their clocks with
2552 /// a time server, up to a few seconds of clock skew are not
2553 /// unusual in practice. And, even worse, several minutes of
2554 /// clock skew appear to be not uncommon on virtual machines.
2555 ///
2556 /// Not accounting for clock skew can result in signatures being
2557 /// unexpectedly considered invalid. Consider: computer A sends a
2558 /// message to computer B at 9:00, but computer B, whose clock
2559 /// says the current time is 8:59, rejects it, because the
2560 /// signature appears to have been made in the future. This is
2561 /// particularly problematic for low-latency protocols built on
2562 /// top of OpenPGP, e.g., when two MUAs synchronize their state
2563 /// via a shared IMAP folder.
2564 ///
2565 /// Being tolerant to potential clock skew is not always
2566 /// appropriate. For instance, when determining a User ID's
2567 /// current self signature at time `t`, we don't ever want to
2568 /// consider a self-signature made after `t` to be valid, even if
2569 /// it was made just a few moments after `t`. This goes doubly so
2570 /// for soft revocation certificates: the user might send a
2571 /// message that she is retiring, and then immediately create a
2572 /// soft revocation. The soft revocation should not invalidate
2573 /// the message.
2574 ///
2575 /// Unfortunately, in many cases, whether we should account for
2576 /// clock skew or not depends on application-specific context. As
2577 /// a rule of thumb, if the time and the timestamp come from
2578 /// different clocks, you probably want to account for clock skew.
2579 ///
2580 /// # Errors
2581 ///
2582 /// [Section 5.2.3.11 of RFC 9580] states that a Signature Creation
2583 /// Time subpacket "MUST be present in the hashed area."
2584 /// Consequently, if such a packet does not exist, this function
2585 /// returns [`Error::MalformedPacket`].
2586 ///
2587 /// [Section 5.2.3.11 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
2588 /// [`Error::MalformedPacket`]: super::super::super::Error::MalformedPacket
2589 ///
2590 /// # Examples
2591 ///
2592 /// Alice's desktop computer and laptop exchange messages in real
2593 /// time via a shared IMAP folder. Unfortunately, the clocks are
2594 /// not perfectly synchronized: the desktop computer's clock is a
2595 /// few seconds ahead of the laptop's clock. When there is little
2596 /// or no propagation delay, this means that the laptop will
2597 /// consider the signatures to be invalid, because they appear to
2598 /// have been created in the future. Using a tolerance prevents
2599 /// this from happening.
2600 ///
2601 /// ```
2602 /// use std::time::{SystemTime, Duration};
2603 /// use sequoia_openpgp as openpgp;
2604 /// use openpgp::cert::prelude::*;
2605 /// use openpgp::packet::signature::SignatureBuilder;
2606 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
2607 /// use openpgp::types::SignatureType;
2608 ///
2609 /// # fn main() -> openpgp::Result<()> {
2610 /// #
2611 /// let (alice, _) =
2612 /// CertBuilder::general_purpose(Some("alice@example.org"))
2613 /// .generate()?;
2614 ///
2615 /// // Alice's Desktop computer signs a message. Its clock is a
2616 /// // few seconds fast.
2617 /// let now = SystemTime::now() + Duration::new(5, 0);
2618 ///
2619 /// let mut alices_signer = alice.primary_key().key().clone()
2620 /// .parts_into_secret()?.into_keypair()?;
2621 /// let msg = "START PROTOCOL";
2622 /// let mut sig = SignatureBuilder::new(SignatureType::Binary)
2623 /// .set_signature_creation_time(now)?
2624 /// .sign_message(&mut alices_signer, msg)?;
2625 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
2626 ///
2627 /// // The desktop computer transfers the message to the laptop
2628 /// // via the shared IMAP folder. Because the laptop receives a
2629 /// // push notification, it immediately processes it.
2630 /// // Unfortunately, it is considered to be invalid: the message
2631 /// // appears to be from the future!
2632 /// assert!(sig.signature_alive(None, Duration::new(0, 0)).is_err());
2633 ///
2634 /// // But, using the small default tolerance causes the laptop
2635 /// // to consider the signature to be alive.
2636 /// assert!(sig.signature_alive(None, None).is_ok());
2637 /// # Ok(()) }
2638 /// ```
2639 pub fn signature_alive<T, U>(&self, time: T, clock_skew_tolerance: U)
2640 -> Result<()>
2641 where T: Into<Option<time::SystemTime>>,
2642 U: Into<Option<time::Duration>>
2643 {
2644 let (time, tolerance)
2645 = match (time.into(), clock_skew_tolerance.into()) {
2646 (None, None) =>
2647 (crate::now(),
2648 CLOCK_SKEW_TOLERANCE),
2649 (None, Some(tolerance)) =>
2650 (crate::now(),
2651 tolerance),
2652 (Some(time), None) =>
2653 (time, time::Duration::new(0, 0)),
2654 (Some(time), Some(tolerance)) =>
2655 (time, tolerance)
2656 };
2657
2658 match (self.signature_creation_time(), self.signature_validity_period())
2659 {
2660 (None, _) =>
2661 Err(Error::MalformedPacket("no signature creation time".into())
2662 .into()),
2663 (Some(c), Some(e)) if e.as_secs() > 0 && (c + e) <= time =>
2664 Err(Error::Expired(c + e).into()),
2665 // Be careful to avoid underflow.
2666 (Some(c), _) if cmp::max(c, time::UNIX_EPOCH + tolerance)
2667 - tolerance > time =>
2668 Err(Error::NotYetLive(cmp::max(c, time::UNIX_EPOCH + tolerance)
2669 - tolerance).into()),
2670 _ => Ok(()),
2671 }
2672 }
2673
2674 /// Returns the value of the Key Expiration Time subpacket.
2675 ///
2676 /// This function is called `key_validity_period` and not
2677 /// `key_expiration_time`, which would be more consistent with
2678 /// the subpacket's name, because the latter suggests an absolute
2679 /// time, but the time is actually relative to the associated
2680 /// key's (*not* the signature's) creation time, which is stored
2681 /// in the [Key].
2682 ///
2683 /// [Key]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
2684 ///
2685 /// A [Key Expiration Time subpacket] specifies when the
2686 /// associated key expires. This is different from the [Signature
2687 /// Expiration Time subpacket] (accessed using
2688 /// [`SubpacketAreas::signature_validity_period`]), which is
2689 /// used to specify when the signature expires. That is, in the
2690 /// former case, the associated key expires, but in the latter
2691 /// case, the signature itself expires. This difference is
2692 /// critical: if a binding signature expires, then an OpenPGP
2693 /// implementation will still consider the associated key to be
2694 /// valid if there is another valid binding signature, even if it
2695 /// is older than the expired signature; if the active binding
2696 /// signature indicates that the key has expired, then OpenPGP
2697 /// implementations will not fall back to an older binding
2698 /// signature.
2699 ///
2700 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2701 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2702 /// [`SubpacketAreas::signature_validity_period`]: Self::signature_validity_period()
2703 ///
2704 /// If the subpacket is not present in the hashed subpacket area,
2705 /// this returns `None`. If this function returns `None`, or the
2706 /// returned period is `0`, the key does not expire.
2707 ///
2708 /// Note: if the signature contains multiple instances of this
2709 /// subpacket in the hashed subpacket area, the last one is
2710 /// returned.
2711 pub fn key_validity_period(&self) -> Option<time::Duration> {
2712 // 4-octet time field
2713 if let Some(sb)
2714 = self.subpacket(SubpacketTag::KeyExpirationTime) {
2715 if let SubpacketValue::KeyExpirationTime(v) = sb.value {
2716 Some(v.into())
2717 } else {
2718 None
2719 }
2720 } else {
2721 None
2722 }
2723 }
2724
2725 /// Returns the value of the Key Expiration Time subpacket
2726 /// as an absolute time.
2727 ///
2728 /// A [Key Expiration Time subpacket] specifies when a key
2729 /// expires. The value stored is not an absolute time, but a
2730 /// duration, which is relative to the associated [Key]'s creation
2731 /// time, which is stored in the Key packet, not the binding
2732 /// signature. As such, the Key Expiration Time subpacket is only
2733 /// meaningful on a key's binding signature. To better reflect
2734 /// the subpacket's name, this method returns the absolute expiry
2735 /// time, and the [`SubpacketAreas::key_validity_period`] method
2736 /// returns the subpacket's raw value.
2737 ///
2738 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2739 /// [Key]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
2740 /// [`SubpacketAreas::key_validity_period`]: Self::key_validity_period()
2741 ///
2742 /// The Key Expiration Time subpacket is different from the
2743 /// [Signature Expiration Time subpacket], which is accessed using
2744 /// [`SubpacketAreas::signature_validity_period`], and specifies
2745 /// when a signature expires. The difference is that in the
2746 /// former case, only the associated key expires, but in the
2747 /// latter case, the signature itself expires. This difference is
2748 /// critical: if a binding signature expires, then an OpenPGP
2749 /// implementation will still consider the associated key to be
2750 /// valid if there is another valid binding signature, even if it
2751 /// is older than the expired signature; if the active binding
2752 /// signature indicates that the key has expired, then OpenPGP
2753 /// implementations will not fall back to an older binding
2754 /// signature.
2755 ///
2756 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
2757 /// [`SubpacketAreas::signature_validity_period`]: Self::signature_validity_period()
2758 ///
2759 /// Because the absolute time is relative to the key's creation
2760 /// time, which is stored in the key itself, this function needs
2761 /// the associated key. Since there is no way to get the
2762 /// associated key from a signature, the key must be passed to
2763 /// this function. This function does not check that the key is
2764 /// in fact associated with this signature.
2765 ///
2766 /// If the subpacket is not present in the hashed subpacket area,
2767 /// this returns `None`. If this function returns `None`, the
2768 /// signature does not expire.
2769 ///
2770 /// Note: if the signature contains multiple instances of this
2771 /// subpacket in the hashed subpacket area, the last one is
2772 /// returned.
2773 pub fn key_expiration_time<P, R>(&self, key: &Key<P, R>)
2774 -> Option<time::SystemTime>
2775 where P: key::KeyParts,
2776 R: key::KeyRole,
2777 {
2778 match self.key_validity_period() {
2779 Some(vp) if vp.as_secs() > 0 => Some(key.creation_time() + vp),
2780 _ => None,
2781 }
2782 }
2783
2784 /// Returns whether a key is alive at the specified
2785 /// time.
2786 ///
2787 /// A [Key] is considered to be alive if `creation time -
2788 /// tolerance <= time` and `time < expiration time`.
2789 ///
2790 /// [Key]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
2791 ///
2792 /// This function does not check whether the signature is alive
2793 /// (cf. [`SubpacketAreas::signature_alive`]), or whether the key
2794 /// is revoked (cf. [`ValidKeyAmalgamation::revoked`]).
2795 ///
2796 /// [`SubpacketAreas::signature_alive`]: Self::signature_alive()
2797 /// [`ValidKeyAmalgamation::revoked`]: crate::cert::amalgamation::key::ValidKeyAmalgamationIter::revoked()
2798 ///
2799 /// If `time` is `None`, then this function uses the current time
2800 /// for `time`.
2801 ///
2802 /// Whereas a Key's expiration time is stored in the Key's active
2803 /// binding signature in the [Key Expiration Time
2804 /// subpacket], its creation time is stored in the Key packet. As
2805 /// such, the associated Key must be passed to this function.
2806 /// This function, however, has no way to check that the signature
2807 /// is actually a binding signature for the specified Key.
2808 ///
2809 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
2810 ///
2811 /// # Examples
2812 ///
2813 /// Even keys that don't expire may not be considered alive. This
2814 /// is the case if they were created after the specified time.
2815 ///
2816 /// ```
2817 /// use std::time::{SystemTime, Duration};
2818 /// use sequoia_openpgp as openpgp;
2819 /// use openpgp::cert::prelude::*;
2820 /// use openpgp::policy::StandardPolicy;
2821 ///
2822 /// # fn main() -> openpgp::Result<()> {
2823 /// #
2824 /// let p = &StandardPolicy::new();
2825 ///
2826 /// let (cert, _) = CertBuilder::new().generate()?;
2827 ///
2828 /// let mut pk = cert.primary_key().key();
2829 /// let sig = cert.primary_key().with_policy(p, None)?.binding_signature();
2830 ///
2831 /// assert!(sig.key_alive(pk, None).is_ok());
2832 /// // A key is not considered alive prior to its creation time.
2833 /// let the_past = SystemTime::now() - Duration::new(300, 0);
2834 /// assert!(sig.key_alive(pk, the_past).is_err());
2835 /// # Ok(()) }
2836 /// ```
2837 pub fn key_alive<P, R, T>(&self, key: &Key<P, R>, t: T) -> Result<()>
2838 where P: key::KeyParts,
2839 R: key::KeyRole,
2840 T: Into<Option<time::SystemTime>>
2841 {
2842 let t = t.into().unwrap_or_else(crate::now);
2843
2844 match self.key_validity_period() {
2845 Some(e) if e.as_secs() > 0 && key.creation_time() + e <= t =>
2846 Err(Error::Expired(key.creation_time() + e).into()),
2847 _ if key.creation_time() > t =>
2848 Err(Error::NotYetLive(key.creation_time()).into()),
2849 _ => Ok(()),
2850 }
2851 }
2852
2853 /// Returns the value of the Exportable Certification subpacket.
2854 ///
2855 /// The [Exportable Certification subpacket] indicates whether the
2856 /// signature should be exported (e.g., published on a public key
2857 /// server) or not. When using [`Serialize::export`] to export a
2858 /// certificate, signatures that have this subpacket present and
2859 /// set to false are not serialized.
2860 ///
2861 /// [Exportable Certification subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.19
2862 /// [`Serialize::export`]: https://docs.sequoia-pgp.org/sequoia_openpgp/serialize/trait.Serialize.html#method.export
2863 ///
2864 /// Normally, you'll want to use [`Signature4::exportable`] to
2865 /// check if a signature should be exported. That function also
2866 /// checks whether the signature includes any sensitive
2867 /// [Revocation Key subpackets], which also shouldn't be exported.
2868 ///
2869 /// [`Signature4::exportable`]: super::Signature4::exportable()
2870 /// [Revocation Key subpackets]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
2871 ///
2872 /// If the subpacket is not present in the hashed subpacket area,
2873 /// this returns `None`.
2874 ///
2875 /// Note: if the signature contains multiple instances of this
2876 /// subpacket in the hashed subpacket area, the last one is
2877 /// returned.
2878 pub fn exportable_certification(&self) -> Option<bool> {
2879 // 1 octet of exportability, 0 for not, 1 for exportable
2880 if let Some(sb)
2881 = self.subpacket(SubpacketTag::ExportableCertification) {
2882 if let SubpacketValue::ExportableCertification(v) = sb.value {
2883 Some(v)
2884 } else {
2885 None
2886 }
2887 } else {
2888 None
2889 }
2890 }
2891
2892 /// Returns the value of the Trust Signature subpacket.
2893 ///
2894 /// The [Trust Signature subpacket] indicates the degree to which
2895 /// a certificate holder is trusted to certify other keys.
2896 ///
2897 /// [Trust Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
2898 ///
2899 /// A level of 0 means that the certificate holder is not trusted
2900 /// to certificate other keys, a level of 1 means that the
2901 /// certificate holder is a trusted introducer (a [certificate
2902 /// authority]) and any certifications that they make should be
2903 /// considered valid. A level of 2 means the certificate holder
2904 /// can designate level 1 trusted introducers, etc.
2905 ///
2906 /// [certificate authority]: https://en.wikipedia.org/wiki/Certificate_authority
2907 ///
2908 /// The trust indicates the degree of confidence. A value of 120
2909 /// means that a certification should be considered valid. A
2910 /// value of 60 means that a certification should only be
2911 /// considered partially valid. In the latter case, typically
2912 /// three such certifications are required for a binding to be
2913 /// considered authenticated.
2914 ///
2915 /// If the subpacket is not present in the hashed subpacket area,
2916 /// this returns `None`.
2917 ///
2918 /// Note: if the signature contains multiple instances of this
2919 /// subpacket in the hashed subpacket area, the last one is
2920 /// returned.
2921 pub fn trust_signature(&self) -> Option<(u8, u8)> {
2922 // 1 octet "level" (depth), 1 octet of trust amount
2923 if let Some(sb) = self.subpacket(SubpacketTag::TrustSignature) {
2924 if let SubpacketValue::TrustSignature{ level, trust } = sb.value {
2925 Some((level, trust))
2926 } else {
2927 None
2928 }
2929 } else {
2930 None
2931 }
2932 }
2933
2934 /// Returns the values of all Regular Expression subpackets.
2935 ///
2936 /// The [Regular Expression subpacket] is used in conjunction with
2937 /// a [Trust Signature subpacket], which is accessed using
2938 /// [`SubpacketAreas::trust_signature`], to limit the scope
2939 /// of a trusted introducer. This is useful, for instance, when a
2940 /// company has a CA and you only want to trust them to certify
2941 /// their own employees.
2942 ///
2943 /// [Trust Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
2944 /// [Regular Expression subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.22
2945 /// [`SubpacketAreas::trust_signature`]: Self::trust_signature()
2946 ///
2947 /// Note: The serialized form includes a trailing `NUL` byte.
2948 /// Sequoia strips the `NUL` when parsing the subpacket.
2949 ///
2950 /// This returns all instances of the Regular Expression subpacket
2951 /// in the hashed subpacket area.
2952 pub fn regular_expressions(&self) -> impl Iterator<Item=&[u8]> + Send + Sync
2953 {
2954 self.subpackets(SubpacketTag::RegularExpression).map(|sb| {
2955 match sb.value {
2956 SubpacketValue::RegularExpression(ref v) => &v[..],
2957 _ => unreachable!(),
2958 }
2959 })
2960 }
2961
2962 /// Returns the value of the Revocable subpacket.
2963 ///
2964 ///
2965 /// The [Revocable subpacket] indicates whether a certification
2966 /// may be later revoked by creating a [Certification revocation
2967 /// signature] (0x30) that targets the signature using the
2968 /// [Signature Target subpacket] (accessed using the
2969 /// [`SubpacketAreas::signature_target`] method).
2970 ///
2971 /// [Revocable subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.20
2972 /// [Certification revocation signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
2973 /// [Signature Target subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
2974 /// [`SubpacketAreas::signature_target`]: Self::signature_target()
2975 ///
2976 /// If the subpacket is not present in the hashed subpacket area,
2977 /// this returns `None`.
2978 ///
2979 /// Note: if the signature contains multiple instances of this
2980 /// subpacket in the hashed subpacket area, the last one is
2981 /// returned.
2982 pub fn revocable(&self) -> Option<bool> {
2983 // 1 octet of revocability, 0 for not, 1 for revocable
2984 if let Some(sb)
2985 = self.subpacket(SubpacketTag::Revocable) {
2986 if let SubpacketValue::Revocable(v) = sb.value {
2987 Some(v)
2988 } else {
2989 None
2990 }
2991 } else {
2992 None
2993 }
2994 }
2995
2996 /// Returns the values of all Revocation Key subpackets.
2997 ///
2998 /// A [Revocation Key subpacket] indicates certificates (so-called
2999 /// designated revokers) that are allowed to revoke the signer's
3000 /// certificate. For instance, if Alice trusts Bob, she can set
3001 /// him as a designated revoker. This is useful if Alice loses
3002 /// access to her key, and therefore is unable to generate a
3003 /// revocation certificate on her own. In this case, she can
3004 /// still Bob to generate one on her behalf.
3005 ///
3006 /// When getting a certificate's revocation keys, all valid
3007 /// self-signatures should be checked, not only the active
3008 /// self-signature. This prevents an attacker who has gained
3009 /// access to the private key material from invalidating a
3010 /// third-party revocation by publishing a new self signature that
3011 /// doesn't include any revocation keys.
3012 ///
3013 /// Due to the complexity of verifying such signatures, many
3014 /// OpenPGP implementations do not support this feature.
3015 ///
3016 /// [Revocation Key subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
3017 ///
3018 /// This returns all instance of the Revocation Key subpacket in
3019 /// the hashed subpacket area.
3020 pub fn revocation_keys(&self)
3021 -> impl Iterator<Item=&RevocationKey> + Send + Sync
3022 {
3023 self.subpackets(SubpacketTag::RevocationKey)
3024 .map(|sb| {
3025 match sb.value {
3026 SubpacketValue::RevocationKey(ref rk) => rk,
3027 _ => unreachable!(),
3028 }
3029 })
3030 }
3031
3032 /// Returns the values of all Issuer subpackets.
3033 ///
3034 /// The [Issuer subpacket] is used when processing a signature to
3035 /// identify which certificate created the signature. Since this
3036 /// information is self-authenticating (the act of validating the
3037 /// signature authenticates the subpacket), it may be stored in the
3038 /// unhashed subpacket area.
3039 ///
3040 /// [Issuer subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
3041 ///
3042 /// This returns all instances of the Issuer subpacket in both the
3043 /// hashed subpacket area and the unhashed subpacket area.
3044 pub fn issuers(&self) -> impl Iterator<Item=&KeyID> + Send + Sync {
3045 // 8-octet Key ID
3046 self.subpackets(SubpacketTag::Issuer)
3047 .map(|sb| {
3048 match sb.value {
3049 SubpacketValue::Issuer(ref keyid) => keyid,
3050 _ => unreachable!(),
3051 }
3052 })
3053 }
3054
3055 /// Returns the values of all Issuer Fingerprint subpackets.
3056 ///
3057 /// The [Issuer Fingerprint subpacket] is used when processing a
3058 /// signature to identify which certificate created the signature.
3059 /// Since this information is self-authenticating (the act of
3060 /// validating the signature authenticates the subpacket), it is
3061 /// normally stored in the unhashed subpacket area.
3062 ///
3063 /// [Issuer Fingerprint subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
3064 ///
3065 /// This returns all instances of the Issuer Fingerprint subpacket
3066 /// in both the hashed subpacket area and the unhashed subpacket
3067 /// area.
3068 pub fn issuer_fingerprints(&self)
3069 -> impl Iterator<Item=&Fingerprint> + Send + Sync
3070 {
3071 // 1 octet key version number, N octets of fingerprint
3072 self.subpackets(SubpacketTag::IssuerFingerprint)
3073 .map(|sb| {
3074 match sb.value {
3075 SubpacketValue::IssuerFingerprint(ref fpr) => fpr,
3076 _ => unreachable!(),
3077 }
3078 })
3079 }
3080
3081 /// Returns all Notation Data subpackets.
3082 ///
3083 /// [Notation Data subpackets] are key-value pairs. They can be
3084 /// used by applications to annotate signatures in a structured
3085 /// way. For instance, they can define additional,
3086 /// application-specific security requirements. Because they are
3087 /// functionally equivalent to subpackets, they can also be used
3088 /// for OpenPGP extensions. This is how the [Intended Recipient
3089 /// subpacket] started life.
3090 ///
3091 /// [Notation Data subpackets]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
3092 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
3093 ///
3094 /// Notation names are structured, and are divided into two
3095 /// namespaces: the user namespace and the IETF namespace. Names
3096 /// in the user namespace have the form `name@example.org` and
3097 /// their meaning is defined by the owner of the domain. The
3098 /// meaning of the notation `name@example.org`, for instance, is
3099 /// defined by whoever controls `example.org`. Names in the IETF
3100 /// namespace do not contain an `@` and are managed by IANA. See
3101 /// [Section 5.2.3.24 of RFC 9580] for details.
3102 ///
3103 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
3104 ///
3105 /// This returns all instances of the Notation Data subpacket in
3106 /// the hashed subpacket area.
3107 pub fn notation_data(&self)
3108 -> impl Iterator<Item=&NotationData> + Send + Sync
3109 {
3110 self.subpackets(SubpacketTag::NotationData)
3111 .map(|sb| {
3112 match sb.value {
3113 SubpacketValue::NotationData(ref v) => v,
3114 _ => unreachable!(),
3115 }
3116 })
3117 }
3118
3119 /// Returns the values of all Notation Data subpackets with the
3120 /// given name.
3121 ///
3122 /// [Notation Data subpackets] are key-value pairs. They can be
3123 /// used by applications to annotate signatures in a structured
3124 /// way. For instance, they can define additional,
3125 /// application-specific security requirements. Because they are
3126 /// functionally equivalent to subpackets, they can also be used
3127 /// for OpenPGP extensions. This is how the [Intended Recipient
3128 /// subpacket] started life.
3129 ///
3130 /// [Notation Data subpackets]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
3131 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
3132 ///
3133 /// Notation names are structured, and are divided into two
3134 /// namespaces: the user namespace and the IETF namespace. Names
3135 /// in the user namespace have the form `name@example.org` and
3136 /// their meaning is defined by the owner of the domain. The
3137 /// meaning of the notation `name@example.org`, for instance, is
3138 /// defined by whoever controls `example.org`. Names in the IETF
3139 /// namespace do not contain an `@` and are managed by IANA. See
3140 /// [Section 5.2.3.24 of RFC 9580] for details.
3141 ///
3142 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
3143 ///
3144 /// This returns the values of all instances of the Notation Data
3145 /// subpacket with the specified name in the hashed subpacket area.
3146 // name needs 'a, because the closure outlives the function call.
3147 pub fn notation<'a, N>(&'a self, name: N)
3148 -> impl Iterator<Item=&'a [u8]> + Send + Sync
3149 where N: 'a + AsRef<str> + Send + Sync
3150 {
3151 self.notation_data()
3152 .filter_map(move |n| {
3153 if n.name == name.as_ref() {
3154 Some(&n.value[..])
3155 } else {
3156 None
3157 }
3158 })
3159 }
3160
3161 /// Returns the value of the Preferred Symmetric Algorithms
3162 /// subpacket.
3163 ///
3164 /// A [Preferred Symmetric Algorithms subpacket] lists what
3165 /// symmetric algorithms the user prefers. When encrypting a
3166 /// message for a recipient, the OpenPGP implementation should not
3167 /// use an algorithm that is not on this list.
3168 ///
3169 /// [Preferred Symmetric Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.14
3170 ///
3171 /// This subpacket is a type of preference. When looking up a
3172 /// preference, an OpenPGP implementation should first look for
3173 /// the subpacket on the binding signature of the User ID or the
3174 /// User Attribute used to locate the certificate (or the primary
3175 /// User ID, if it was addressed by Key ID or fingerprint). If
3176 /// the binding signature doesn't contain the subpacket, then the
3177 /// direct key signature should be checked. See the
3178 /// [`Preferences`] trait for details.
3179 ///
3180 /// Unless addressing different User IDs really should result in
3181 /// different behavior, it is best to only set this preference on
3182 /// the direct key signature. This guarantees that even if some
3183 /// or all User IDs are stripped, the behavior remains consistent.
3184 ///
3185 /// [`Preferences`]: crate::cert::Preferences
3186 ///
3187 /// If the subpacket is not present in the hashed subpacket area,
3188 /// this returns `None`.
3189 ///
3190 /// Note: if the signature contains multiple instances of this
3191 /// subpacket in the hashed subpacket area, the last one is
3192 /// returned.
3193 pub fn preferred_symmetric_algorithms(&self)
3194 -> Option<&[SymmetricAlgorithm]> {
3195 // array of one-octet values
3196 if let Some(sb)
3197 = self.subpacket(
3198 SubpacketTag::PreferredSymmetricAlgorithms) {
3199 if let SubpacketValue::PreferredSymmetricAlgorithms(v)
3200 = &sb.value {
3201 Some(v)
3202 } else {
3203 None
3204 }
3205 } else {
3206 None
3207 }
3208 }
3209
3210 /// Returns the value of the Preferred Hash Algorithms subpacket.
3211 ///
3212 /// A [Preferred Hash Algorithms subpacket] lists what hash
3213 /// algorithms the user prefers. When signing a message that
3214 /// should be verified by a particular recipient, the OpenPGP
3215 /// implementation should not use an algorithm that is not on this
3216 /// list.
3217 ///
3218 /// [Preferred Hash Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.16
3219 ///
3220 /// This subpacket is a type of preference. When looking up a
3221 /// preference, an OpenPGP implementation should first look for
3222 /// the subpacket on the binding signature of the User ID or the
3223 /// User Attribute used to locate the certificate (or the primary
3224 /// User ID, if it was addressed by Key ID or fingerprint). If
3225 /// the binding signature doesn't contain the subpacket, then the
3226 /// direct key signature should be checked. See the
3227 /// [`Preferences`] trait for details.
3228 ///
3229 /// Unless addressing different User IDs really should result in
3230 /// different behavior, it is best to only set this preference on
3231 /// the direct key signature. This guarantees that even if some
3232 /// or all User IDs are stripped, the behavior remains consistent.
3233 ///
3234 /// [`Preferences`]: crate::cert::Preferences
3235 ///
3236 /// If the subpacket is not present in the hashed subpacket area,
3237 /// this returns `None`.
3238 ///
3239 /// Note: if the signature contains multiple instances of this
3240 /// subpacket in the hashed subpacket area, the last one is
3241 /// returned.
3242 pub fn preferred_hash_algorithms(&self) -> Option<&[HashAlgorithm]> {
3243 // array of one-octet values
3244 if let Some(sb)
3245 = self.subpacket(
3246 SubpacketTag::PreferredHashAlgorithms) {
3247 if let SubpacketValue::PreferredHashAlgorithms(v) = &sb.value {
3248 Some(v)
3249 } else {
3250 None
3251 }
3252 } else {
3253 None
3254 }
3255 }
3256
3257 /// Returns the value of the Preferred Compression Algorithms
3258 /// subpacket.
3259 ///
3260 /// A [Preferred Compression Algorithms subpacket] lists what
3261 /// compression algorithms the user prefers. When compressing a
3262 /// message for a recipient, the OpenPGP implementation should not
3263 /// use an algorithm that is not on the list.
3264 ///
3265 /// [Preferred Compression Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.17
3266 ///
3267 /// This subpacket is a type of preference. When looking up a
3268 /// preference, an OpenPGP implementation should first for the
3269 /// subpacket on the binding signature of the User ID or the User
3270 /// Attribute used to locate the certificate (or the primary User
3271 /// ID, if it was addressed by Key ID or fingerprint). If the
3272 /// binding signature doesn't contain the subpacket, then the
3273 /// direct key signature should be checked. See the
3274 /// [`Preferences`] trait for details.
3275 ///
3276 /// Unless addressing different User IDs really should result in
3277 /// different behavior, it is best to only set this preference on
3278 /// the direct key signature. This guarantees that even if some
3279 /// or all User IDs are stripped, the behavior remains consistent.
3280 ///
3281 /// [`Preferences`]: crate::cert::Preferences
3282 ///
3283 /// If the subpacket is not present in the hashed subpacket area,
3284 /// this returns `None`.
3285 ///
3286 /// Note: if the signature contains multiple instances of this
3287 /// subpacket in the hashed subpacket area, the last one is
3288 /// returned.
3289 pub fn preferred_compression_algorithms(&self)
3290 -> Option<&[CompressionAlgorithm]>
3291 {
3292 // array of one-octet values
3293 if let Some(sb)
3294 = self.subpacket(
3295 SubpacketTag::PreferredCompressionAlgorithms) {
3296 if let SubpacketValue::PreferredCompressionAlgorithms(v)
3297 = &sb.value {
3298 Some(v)
3299 } else {
3300 None
3301 }
3302 } else {
3303 None
3304 }
3305 }
3306
3307 /// Returns the value of the Preferred AEAD Ciphersuites subpacket.
3308 ///
3309 /// The [Preferred AEAD Ciphersuites subpacket] indicates what
3310 /// AEAD ciphersuites (i.e. pairs of symmetric algorithm and AEAD
3311 /// algorithm) the key holder prefers ordered by preference. If
3312 /// this is set, then the SEIPDv2 feature flag should in the
3313 /// [Features subpacket] should also be set.
3314 ///
3315 /// [Preferred AEAD Ciphersuites subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites
3316 /// [Features subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#features-subpacket
3317 ///
3318 /// This subpacket is a type of preference. When looking up a
3319 /// preference, an OpenPGP implementation should first look for
3320 /// the subpacket on the binding signature of the User ID or the
3321 /// User Attribute used to locate the certificate (or the primary
3322 /// User ID, if it was addressed by Key ID or fingerprint). If
3323 /// the binding signature doesn't contain the subpacket, then the
3324 /// direct key signature should be checked. See the
3325 /// [`Preferences`] trait for details.
3326 ///
3327 /// Unless addressing different User IDs really should result in
3328 /// different behavior, it is best to only set this preference on
3329 /// the direct key signature. This guarantees that even if some
3330 /// or all User IDs are stripped, the behavior remains consistent.
3331 ///
3332 /// [`Preferences`]: crate::cert::Preferences
3333 ///
3334 /// If the subpacket is not present in the hashed subpacket area,
3335 /// this returns `None`.
3336 ///
3337 /// Note: if the signature contains multiple instances of this
3338 /// subpacket in the hashed subpacket area, the last one is
3339 /// returned.
3340 pub fn preferred_aead_ciphersuites(&self)
3341 -> Option<&[(SymmetricAlgorithm, AEADAlgorithm)]>
3342 {
3343 if let Some(sb) = self.subpacket(
3344 SubpacketTag::PreferredAEADCiphersuites)
3345 {
3346 if let SubpacketValue::PreferredAEADCiphersuites(v)
3347 = &sb.value
3348 {
3349 Some(v)
3350 } else {
3351 None
3352 }
3353 } else {
3354 None
3355 }
3356 }
3357
3358 /// Returns the value of the Key Server Preferences subpacket.
3359 ///
3360 /// The [Key Server Preferences subpacket] indicates to key
3361 /// servers how they should handle the certificate.
3362 ///
3363 /// [Key Server Preferences subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.25
3364 ///
3365 /// This subpacket is a type of preference. When looking up a
3366 /// preference, an OpenPGP implementation should first for the
3367 /// subpacket on the binding signature of the User ID or the User
3368 /// Attribute used to locate the certificate (or the primary User
3369 /// ID, if it was addressed by Key ID or fingerprint). If the
3370 /// binding signature doesn't contain the subpacket, then the
3371 /// direct key signature should be checked. See the
3372 /// [`Preferences`] trait for details.
3373 ///
3374 /// Unless addressing different User IDs really should result in
3375 /// different behavior, it is best to only set this preference on
3376 /// the direct key signature. This guarantees that even if some
3377 /// or all User IDs are stripped, the behavior remains consistent.
3378 ///
3379 /// [`Preferences`]: crate::cert::Preferences
3380 ///
3381 /// If the subpacket is not present in the hashed subpacket area,
3382 /// this returns `None`.
3383 ///
3384 /// Note: if the signature contains multiple instances of this
3385 /// subpacket in the hashed subpacket area, the last one is
3386 /// returned.
3387 pub fn key_server_preferences(&self) -> Option<KeyServerPreferences> {
3388 // N octets of flags
3389 if let Some(sb) = self.subpacket(SubpacketTag::KeyServerPreferences) {
3390 if let SubpacketValue::KeyServerPreferences(v) = &sb.value {
3391 Some(v.clone())
3392 } else {
3393 None
3394 }
3395 } else {
3396 None
3397 }
3398 }
3399
3400 /// Returns the value of the Preferred Key Server subpacket.
3401 ///
3402 /// The [Preferred Key Server subpacket] contains a link to a key
3403 /// server where the certificate holder plans to publish updates
3404 /// to their certificate (e.g., extensions to the expiration time,
3405 /// new subkeys, revocation certificates).
3406 ///
3407 /// The Preferred Key Server subpacket should be handled
3408 /// cautiously, because it can be used by a certificate holder to
3409 /// track communication partners.
3410 ///
3411 /// [Preferred Key Server subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.26
3412 ///
3413 /// This subpacket is a type of preference. When looking up a
3414 /// preference, an OpenPGP implementation should first look for
3415 /// the subpacket on the binding signature of the User ID or the
3416 /// User Attribute used to locate the certificate (or the primary
3417 /// User ID, if it was addressed by Key ID or fingerprint). If
3418 /// the binding signature doesn't contain the subpacket, then the
3419 /// direct key signature should be checked. See the
3420 /// [`Preferences`] trait for details.
3421 ///
3422 /// Unless addressing different User IDs really should result in
3423 /// different behavior, it is best to only set this preference on
3424 /// the direct key signature. This guarantees that even if some
3425 /// or all User IDs are stripped, the behavior remains consistent.
3426 ///
3427 /// [`Preferences`]: crate::cert::Preferences
3428 ///
3429 /// If the subpacket is not present in the hashed subpacket area,
3430 /// this returns `None`.
3431 ///
3432 /// Note: if the signature contains multiple instances of this
3433 /// subpacket in the hashed subpacket area, the last one is
3434 /// returned.
3435 pub fn preferred_key_server(&self) -> Option<&[u8]> {
3436 // String
3437 if let Some(sb)
3438 = self.subpacket(SubpacketTag::PreferredKeyServer) {
3439 if let SubpacketValue::PreferredKeyServer(v) = &sb.value {
3440 Some(v)
3441 } else {
3442 None
3443 }
3444 } else {
3445 None
3446 }
3447 }
3448
3449 /// Returns the value of the Policy URI subpacket.
3450 ///
3451 /// The [Policy URI subpacket] contains a link to a policy document,
3452 /// which contains information about the conditions under which
3453 /// the signature was made.
3454 ///
3455 /// [Policy URI subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.28
3456 ///
3457 /// This subpacket is a type of preference. When looking up a
3458 /// preference, an OpenPGP implementation should first look for
3459 /// the subpacket on the binding signature of the User ID or the
3460 /// User Attribute used to locate the certificate (or the primary
3461 /// User ID, if it was addressed by Key ID or fingerprint). If
3462 /// the binding signature doesn't contain the subpacket, then the
3463 /// direct key signature should be checked. See the
3464 /// [`Preferences`] trait for details.
3465 ///
3466 /// Unless addressing different User IDs really should result in
3467 /// different behavior, it is best to only set this preference on
3468 /// the direct key signature. This guarantees that even if some
3469 /// or all User IDs are stripped, the behavior remains consistent.
3470 ///
3471 /// [`Preferences`]: crate::cert::Preferences
3472 ///
3473 /// If the subpacket is not present in the hashed subpacket area,
3474 /// this returns `None`.
3475 ///
3476 /// Note: if the signature contains multiple instances of this
3477 /// subpacket in the hashed subpacket area, the last one is
3478 /// returned.
3479 pub fn policy_uri(&self) -> Option<&[u8]> {
3480 // String
3481 if let Some(sb)
3482 = self.subpacket(SubpacketTag::PolicyURI) {
3483 if let SubpacketValue::PolicyURI(v) = &sb.value {
3484 Some(v)
3485 } else {
3486 None
3487 }
3488 } else {
3489 None
3490 }
3491 }
3492
3493 /// Returns the value of the Primary UserID subpacket.
3494 ///
3495 /// The [Primary User ID subpacket] indicates whether the
3496 /// associated User ID or User Attribute should be considered the
3497 /// primary User ID. It is possible that this is set on multiple
3498 /// User IDs. See the documentation for
3499 /// [`ValidCert::primary_userid`] for an explanation of how
3500 /// Sequoia resolves this ambiguity.
3501 ///
3502 /// [Primary User ID subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
3503 /// [`ValidCert::primary_userid`]: crate::cert::ValidCert::primary_userid()
3504 ///
3505 /// If the subpacket is not present in the hashed subpacket area,
3506 /// this returns `None`.
3507 ///
3508 /// Note: if the signature contains multiple instances of this
3509 /// subpacket in the hashed subpacket area, the last one is
3510 /// returned.
3511 pub fn primary_userid(&self) -> Option<bool> {
3512 // 1 octet, Boolean
3513 if let Some(sb)
3514 = self.subpacket(SubpacketTag::PrimaryUserID) {
3515 if let SubpacketValue::PrimaryUserID(v) = sb.value {
3516 Some(v)
3517 } else {
3518 None
3519 }
3520 } else {
3521 None
3522 }
3523 }
3524
3525 /// Returns the value of the Key Flags subpacket.
3526 ///
3527 /// The [Key Flags subpacket] describes a key's capabilities
3528 /// (certification capable, signing capable, etc.). In the case
3529 /// of subkeys, the Key Flags are located on the subkey's binding
3530 /// signature. For primary keys, locating the correct Key Flags
3531 /// subpacket is more complex: First, the primary User ID is
3532 /// consulted. If the primary User ID contains a Key Flags
3533 /// subpacket, that is used. Otherwise, any direct key signature
3534 /// is considered. If that still doesn't contain a Key Flags
3535 /// packet, then the primary key should be assumed to be
3536 /// certification capable.
3537 ///
3538 /// [Key Flags subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
3539 ///
3540 /// If the subpacket is not present in the hashed subpacket area,
3541 /// this returns `None`.
3542 ///
3543 /// Note: if the signature contains multiple instances of this
3544 /// subpacket in the hashed subpacket area, the last one is
3545 /// returned.
3546 pub fn key_flags(&self) -> Option<KeyFlags> {
3547 // N octets of flags
3548 if let Some(sb) = self.subpacket(SubpacketTag::KeyFlags) {
3549 if let SubpacketValue::KeyFlags(v) = &sb.value {
3550 Some(v.clone())
3551 } else {
3552 None
3553 }
3554 } else {
3555 None
3556 }
3557 }
3558
3559 /// Returns the value of the Signer's UserID subpacket.
3560 ///
3561 /// The [Signer's User ID subpacket] indicates, which User ID made
3562 /// the signature. This is useful when a key has multiple User
3563 /// IDs, which correspond to different roles. For instance, it is
3564 /// not uncommon to use the same certificate in private as well as
3565 /// for a club.
3566 ///
3567 /// [Signer's User ID subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.30
3568 ///
3569 /// If the subpacket is not present in the hashed subpacket area,
3570 /// this returns `None`.
3571 ///
3572 /// Note: if the signature contains multiple instances of this
3573 /// subpacket in the hashed subpacket area, the last one is
3574 /// returned.
3575 pub fn signers_user_id(&self) -> Option<&[u8]> {
3576 // String
3577 if let Some(sb)
3578 = self.subpacket(SubpacketTag::SignersUserID) {
3579 if let SubpacketValue::SignersUserID(v) = &sb.value {
3580 Some(v)
3581 } else {
3582 None
3583 }
3584 } else {
3585 None
3586 }
3587 }
3588
3589 /// Returns the value of the Reason for Revocation subpacket.
3590 ///
3591 /// The [Reason For Revocation subpacket] indicates why a key,
3592 /// User ID, or User Attribute is being revoked. It includes both
3593 /// a machine-readable code, and a human-readable string. The
3594 /// code is essential as it indicates to the OpenPGP
3595 /// implementation that reads the certificate whether the key was
3596 /// compromised (a hard revocation), or is no longer used (a soft
3597 /// revocation). In the former case, the OpenPGP implementation
3598 /// must conservatively consider all past signatures as suspect
3599 /// whereas in the latter case, past signatures can still be
3600 /// considered valid.
3601 ///
3602 /// [Reason For Revocation subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.31
3603 ///
3604 /// If the subpacket is not present in the hashed subpacket area,
3605 /// this returns `None`.
3606 ///
3607 /// Note: if the signature contains multiple instances of this
3608 /// subpacket in the hashed subpacket area, the last one is
3609 /// returned.
3610 pub fn reason_for_revocation(&self)
3611 -> Option<(ReasonForRevocation, &[u8])> {
3612 // 1 octet of revocation code, N octets of reason string
3613 if let Some(sb) = self.subpacket(SubpacketTag::ReasonForRevocation) {
3614 if let SubpacketValue::ReasonForRevocation {
3615 code, reason,
3616 } = &sb.value {
3617 Some((*code, reason))
3618 } else {
3619 None
3620 }
3621 } else {
3622 None
3623 }
3624 }
3625
3626 /// Returns the value of the Features subpacket.
3627 ///
3628 /// A [Features subpacket] lists what OpenPGP features the user
3629 /// wants to use. When creating a message, features that the
3630 /// intended recipients do not support should not be used.
3631 /// However, because this information is rarely held up to date in
3632 /// practice, this information is only advisory, and
3633 /// implementations are allowed to infer what features the
3634 /// recipients support from contextual clues, e.g., their past
3635 /// behavior.
3636 ///
3637 /// [Features subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.32
3638 /// [features]: crate::types::Features
3639 ///
3640 /// This subpacket is a type of preference. When looking up a
3641 /// preference, an OpenPGP implementation should first look for
3642 /// the subpacket on the binding signature of the User ID or the
3643 /// User Attribute used to locate the certificate (or the primary
3644 /// User ID, if it was addressed by Key ID or fingerprint). If
3645 /// the binding signature doesn't contain the subpacket, then the
3646 /// direct key signature should be checked. See the
3647 /// [`Preferences`] trait for details.
3648 ///
3649 /// Unless addressing different User IDs really should result in
3650 /// different behavior, it is best to only set this preference on
3651 /// the direct key signature. This guarantees that even if some
3652 /// or all User IDs are stripped, the behavior remains consistent.
3653 ///
3654 /// [`Preferences`]: crate::cert::Preferences
3655 ///
3656 /// If the subpacket is not present in the hashed subpacket area,
3657 /// this returns `None`.
3658 ///
3659 /// Note: if the signature contains multiple instances of this
3660 /// subpacket in the hashed subpacket area, the last one is
3661 /// returned.
3662 pub fn features(&self) -> Option<Features> {
3663 // N octets of flags
3664 if let Some(sb) = self.subpacket(SubpacketTag::Features) {
3665 if let SubpacketValue::Features(v) = &sb.value {
3666 Some(v.clone())
3667 } else {
3668 None
3669 }
3670 } else {
3671 None
3672 }
3673 }
3674
3675 /// Returns the value of the Signature Target subpacket.
3676 ///
3677 /// The [Signature Target subpacket] is used to identify the target
3678 /// of a signature. This is used when revoking a signature, and
3679 /// by timestamp signatures. It contains a hash of the target
3680 /// signature.
3681 ///
3682 /// [Signature Target subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
3683 ///
3684 /// If the subpacket is not present in the hashed subpacket area,
3685 /// this returns `None`.
3686 ///
3687 /// Note: if the signature contains multiple instances of this
3688 /// subpacket in the hashed subpacket area, the last one is
3689 /// returned.
3690 pub fn signature_target(&self) -> Option<(PublicKeyAlgorithm,
3691 HashAlgorithm,
3692 &[u8])> {
3693 // 1 octet public-key algorithm, 1 octet hash algorithm, N
3694 // octets hash
3695 if let Some(sb) = self.subpacket(SubpacketTag::SignatureTarget) {
3696 if let SubpacketValue::SignatureTarget {
3697 pk_algo, hash_algo, digest,
3698 } = &sb.value {
3699 Some((*pk_algo, *hash_algo, digest))
3700 } else {
3701 None
3702 }
3703 } else {
3704 None
3705 }
3706 }
3707
3708 /// Returns references to all Embedded Signature subpackets.
3709 ///
3710 /// The [Embedded Signature subpacket] is normally used to hold a
3711 /// [Primary Key Binding signature], which binds a
3712 /// signing-capable, authentication-capable, or
3713 /// certification-capable subkey to the primary key. Since this
3714 /// information is self-authenticating, it is usually stored in
3715 /// the unhashed subpacket area.
3716 ///
3717 /// [Embedded Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.34
3718 /// [Primary Key Binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
3719 ///
3720 /// If the subpacket is not present in the hashed subpacket area
3721 /// or in the unhashed subpacket area, this returns `None`.
3722 ///
3723 /// Note: if the signature contains multiple instances of this
3724 /// subpacket in the hashed subpacket area, the last one is
3725 /// returned. Otherwise, the last one is returned from the
3726 /// unhashed subpacket area.
3727 pub fn embedded_signatures(&self)
3728 -> impl Iterator<Item = &Signature> + Send + Sync
3729 {
3730 self.subpackets(SubpacketTag::EmbeddedSignature).map(|sb| {
3731 if let SubpacketValue::EmbeddedSignature(v) = &sb.value {
3732 v
3733 } else {
3734 unreachable!(
3735 "subpackets(EmbeddedSignature) returns EmbeddedSignatures"
3736 );
3737 }
3738 })
3739 }
3740
3741 /// Returns mutable references to all Embedded Signature subpackets.
3742 ///
3743 /// The [Embedded Signature subpacket] is normally used to hold a
3744 /// [Primary Key Binding signature], which binds a
3745 /// signing-capable, authentication-capable, or
3746 /// certification-capable subkey to the primary key. Since this
3747 /// information is self-authenticating, it is usually stored in
3748 /// the unhashed subpacket area.
3749 ///
3750 /// [Embedded Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.34
3751 /// [Primary Key Binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
3752 ///
3753 /// If the subpacket is not present in the hashed subpacket area
3754 /// or in the unhashed subpacket area, this returns `None`.
3755 ///
3756 /// Note: if the signature contains multiple instances of this
3757 /// subpacket in the hashed subpacket area, the last one is
3758 /// returned. Otherwise, the last one is returned from the
3759 /// unhashed subpacket area.
3760 pub fn embedded_signatures_mut(&mut self)
3761 -> impl Iterator<Item = &mut Signature> + Send + Sync
3762 {
3763 self.subpackets_mut(SubpacketTag::EmbeddedSignature).map(|sb| {
3764 if let SubpacketValue::EmbeddedSignature(v) = &mut sb.value {
3765 v
3766 } else {
3767 unreachable!(
3768 "subpackets_mut(EmbeddedSignature) returns EmbeddedSignatures"
3769 );
3770 }
3771 })
3772 }
3773
3774 /// Returns the intended recipients.
3775 ///
3776 /// The [Intended Recipient subpacket] holds the fingerprint of a
3777 /// certificate.
3778 ///
3779 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
3780 ///
3781 /// When signing a message, the message should include one such
3782 /// subpacket for each intended recipient. Note: not all messages
3783 /// have intended recipients. For instance, when signing an open
3784 /// letter, or a software release, the message is intended for
3785 /// anyone.
3786 ///
3787 /// When processing a signature, the application should ensure
3788 /// that if there are any such subpackets, then one of the
3789 /// subpackets identifies the recipient's certificate (or user
3790 /// signed the message). If this is not the case, then an
3791 /// attacker may have taken the message out of its original
3792 /// context. For instance, if Alice sends a signed email to Bob,
3793 /// with the content: "I agree to the contract", and Bob forwards
3794 /// that message to Carol, then Carol may think that Alice agreed
3795 /// to a contract with her if the signature appears to be valid!
3796 /// By adding an intended recipient, it is possible for Carol's
3797 /// mail client to warn her that although Alice signed the
3798 /// message, the content was intended for Bob and not for her.
3799 ///
3800 /// This returns all instances of the Intended Recipient subpacket
3801 /// in the hashed subpacket area.
3802 pub fn intended_recipients(&self)
3803 -> impl Iterator<Item=&Fingerprint> + Send + Sync
3804 {
3805 self.subpackets(SubpacketTag::IntendedRecipient)
3806 .map(|sb| {
3807 match sb.value() {
3808 SubpacketValue::IntendedRecipient(ref fp) => fp,
3809 _ => unreachable!(),
3810 }
3811 })
3812 }
3813
3814 /// Returns the digests of approved certifications.
3815 ///
3816 /// This feature is [experimental](crate#experimental-features).
3817 ///
3818 /// Allows the certificate holder to attest to third party
3819 /// certifications, allowing them to be distributed with the
3820 /// certificate. This can be used to address certificate flooding
3821 /// concerns.
3822 ///
3823 /// Note: The maximum size of the hashed signature subpacket area
3824 /// constrains the number of attestations that can be stored in a
3825 /// signature. If the certificate holder approved of more
3826 /// certifications, the digests are split across multiple approved
3827 /// certification key signatures with the same creation time.
3828 ///
3829 /// The standard strongly suggests that the digests should be
3830 /// sorted. However, this function returns the digests in the
3831 /// order they are stored in the subpacket, which may not be
3832 /// sorted.
3833 ///
3834 /// To address both issues, collect all digests from all approved
3835 /// key signatures with the most recent creation time into a data
3836 /// structure that allows efficient lookups, such as [`HashSet`]
3837 /// or [`BTreeSet`].
3838 ///
3839 /// See [Section 2.2 of draft-dkg-openpgp-1pa3pc-02] for details.
3840 ///
3841 /// [`HashSet`]: std::collections::HashSet
3842 /// [`BTreeSet`]: std::collections::BTreeSet
3843 /// [Section 2.2 of draft-dkg-openpgp-1pa3pc-02]: https://www.ietf.org/archive/id/draft-dkg-openpgp-1pa3pc-02.html#approved-certifications-subpacket
3844 pub fn approved_certifications(&self)
3845 -> Result<impl Iterator<Item=&[u8]> + Send + Sync>
3846 {
3847 if self.hashed_area()
3848 .subpackets(SubpacketTag::ApprovedCertifications).count() > 1
3849 || self.unhashed_area()
3850 .subpackets(SubpacketTag::ApprovedCertifications).count() != 0
3851 {
3852 return Err(Error::BadSignature(
3853 "Wrong number of approved certifications subpackets".into())
3854 .into());
3855 }
3856
3857 Ok(self.subpackets(SubpacketTag::ApprovedCertifications)
3858 .flat_map(|sb| {
3859 match sb.value() {
3860 SubpacketValue::ApprovedCertifications(digests) =>
3861 digests.iter().map(|d| d.as_ref()),
3862 _ => unreachable!(),
3863 }
3864 }))
3865 }
3866}
3867
3868impl TryFrom<Signature> for Signature4 {
3869 type Error = anyhow::Error;
3870
3871 fn try_from(sig: Signature) -> Result<Self> {
3872 match sig {
3873 Signature::V4(sig) => Ok(sig),
3874 sig => Err(
3875 Error::InvalidArgument(
3876 format!(
3877 "Got a v{}, require a v4 signature",
3878 sig.version()))
3879 .into()),
3880 }
3881 }
3882}
3883
3884impl Deref for Signature4 {
3885 type Target = signature::SignatureFields;
3886
3887 fn deref(&self) -> &Self::Target {
3888 &self.fields
3889 }
3890}
3891
3892impl DerefMut for Signature4 {
3893 fn deref_mut(&mut self) -> &mut Self::Target {
3894 &mut self.fields
3895 }
3896}
3897
3898impl signature::SignatureBuilder {
3899 /// Modifies the unhashed subpacket area.
3900 ///
3901 /// This method provides a builder-style interface for modifying
3902 /// the unhashed subpacket area.
3903 ///
3904 /// Normally, to modify a subpacket area in a non-standard way
3905 /// (that is, when there are no subpacket-specific function like
3906 /// [`SignatureBuilder::set_signature_validity_period`] that
3907 /// implement the required functionality), you need to do
3908 /// something like the following:
3909 ///
3910 /// [`SignatureBuilder::set_signature_validity_period`]: super::SignatureBuilder::set_signature_validity_period()
3911 ///
3912 /// ```
3913 /// # use sequoia_openpgp as openpgp;
3914 /// # use openpgp::types::Curve;
3915 /// # use openpgp::cert::prelude::*;
3916 /// # use openpgp::packet::prelude::*;
3917 /// # use openpgp::packet::signature::subpacket::{
3918 /// # Subpacket,
3919 /// # SubpacketTag,
3920 /// # SubpacketValue,
3921 /// # };
3922 /// # use openpgp::types::SignatureType;
3923 /// #
3924 /// # fn main() -> openpgp::Result<()> {
3925 /// #
3926 /// # let key: Key<key::SecretParts, key::PrimaryRole>
3927 /// # = Key6::generate_ecc(true, Curve::Ed25519)?.into();
3928 /// # let mut signer = key.into_keypair()?;
3929 /// # let msg = b"Hello, World";
3930 /// #
3931 /// let mut builder = SignatureBuilder::new(SignatureType::Binary)
3932 /// // Build up the signature.
3933 /// ;
3934 /// builder.unhashed_area_mut().add(Subpacket::new(
3935 /// SubpacketValue::Unknown {
3936 /// tag: SubpacketTag::Private(61),
3937 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
3938 /// },
3939 /// true)?)?;
3940 /// let sig = builder.sign_message(&mut signer, msg)?;
3941 /// # let mut sig = sig;
3942 /// # sig.verify_message(signer.public(), msg)?;
3943 /// # Ok(()) }
3944 /// ```
3945 ///
3946 /// This is necessary, because modifying the subpacket area
3947 /// doesn't follow the builder pattern like the surrounding code.
3948 /// Using this function, you can instead do:
3949 ///
3950 /// ```
3951 /// # use sequoia_openpgp as openpgp;
3952 /// # use openpgp::cert::prelude::*;
3953 /// # use openpgp::packet::prelude::*;
3954 /// # use openpgp::packet::signature::subpacket::{
3955 /// # Subpacket,
3956 /// # SubpacketTag,
3957 /// # SubpacketValue,
3958 /// # };
3959 /// # use openpgp::types::Curve;
3960 /// # use openpgp::types::SignatureType;
3961 /// #
3962 /// # fn main() -> openpgp::Result<()> {
3963 /// #
3964 /// # let key: Key<key::SecretParts, key::PrimaryRole>
3965 /// # = Key6::generate_ecc(true, Curve::Ed25519)?.into();
3966 /// # let mut signer = key.into_keypair()?;
3967 /// # let msg = b"Hello, World";
3968 /// #
3969 /// let sig = SignatureBuilder::new(SignatureType::Binary)
3970 /// // Call some setters.
3971 /// .modify_unhashed_area(|mut a| {
3972 /// a.add(Subpacket::new(
3973 /// SubpacketValue::Unknown {
3974 /// tag: SubpacketTag::Private(61),
3975 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
3976 /// },
3977 /// true)?);
3978 /// Ok(a)
3979 /// })?
3980 /// .sign_message(&mut signer, msg)?;
3981 /// # let mut sig = sig;
3982 /// # sig.verify_message(signer.public(), msg)?;
3983 /// # Ok(()) }
3984 /// ```
3985 ///
3986 /// If you are only interested in modifying an existing
3987 /// signature's unhashed area, it may be better to simply modify
3988 /// the signature in place using
3989 /// [`SignatureBuilder::modify_unhashed_area`] rather than to create a
3990 /// new signature, because modifying the unhashed area doesn't
3991 /// invalidate any existing signature.
3992 ///
3993 /// [`SignatureBuilder::modify_unhashed_area`]: super::SignatureBuilder::modify_unhashed_area
3994 ///
3995 /// # Examples
3996 ///
3997 /// Create a signature with a custom, non-critical subpacket in
3998 /// the unhashed area:
3999 ///
4000 /// ```
4001 /// use sequoia_openpgp as openpgp;
4002 /// use openpgp::cert::prelude::*;
4003 /// use openpgp::packet::prelude::*;
4004 /// use openpgp::packet::signature::subpacket::{
4005 /// Subpacket,
4006 /// SubpacketTag,
4007 /// SubpacketValue,
4008 /// };
4009 /// use openpgp::types::SignatureType;
4010 /// #
4011 /// # fn main() -> openpgp::Result<()> {
4012 ///
4013 /// let (cert, _) =
4014 /// CertBuilder::general_purpose(Some("alice@example.org"))
4015 /// .generate()?;
4016 /// let mut signer = cert.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
4017 ///
4018 /// let msg = b"Hello, World";
4019 ///
4020 /// let sig = SignatureBuilder::new(SignatureType::Binary)
4021 /// // Call some setters.
4022 /// .modify_unhashed_area(|mut a| {
4023 /// a.add(Subpacket::new(
4024 /// SubpacketValue::Unknown {
4025 /// tag: SubpacketTag::Private(61),
4026 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
4027 /// },
4028 /// true)?);
4029 /// Ok(a)
4030 /// })?
4031 /// .sign_message(&mut signer, msg)?;
4032 /// # let mut sig = sig;
4033 /// # sig.verify_message(signer.public(), msg)?;
4034 /// # Ok(()) }
4035 /// ```
4036 pub fn modify_unhashed_area<F>(mut self, f: F)
4037 -> Result<Self>
4038 where F: FnOnce(SubpacketArea) -> Result<SubpacketArea>
4039 {
4040 self.fields.subpackets.unhashed_area
4041 = f(self.fields.subpackets.unhashed_area)?;
4042 Ok(self)
4043 }
4044
4045 /// Modifies the hashed subpacket area.
4046 ///
4047 /// This method provides a builder-style interface for modifying
4048 /// the hashed subpacket area.
4049 ///
4050 /// Normally, to modify a subpacket area in a non-standard way
4051 /// (that is, when there are no subpacket-specific function like
4052 /// [`SignatureBuilder::set_signature_validity_period`] that
4053 /// implement the required functionality), you need to do
4054 /// something like the following:
4055 ///
4056 /// [`SignatureBuilder::set_signature_validity_period`]: super::SignatureBuilder::set_signature_validity_period()
4057 ///
4058 /// ```
4059 /// # use sequoia_openpgp as openpgp;
4060 /// # use openpgp::types::Curve;
4061 /// # use openpgp::cert::prelude::*;
4062 /// # use openpgp::packet::prelude::*;
4063 /// # use openpgp::packet::signature::subpacket::{
4064 /// # Subpacket,
4065 /// # SubpacketTag,
4066 /// # SubpacketValue,
4067 /// # };
4068 /// # use openpgp::types::SignatureType;
4069 /// #
4070 /// # fn main() -> openpgp::Result<()> {
4071 /// #
4072 /// # let key: Key<key::SecretParts, key::PrimaryRole>
4073 /// # = Key6::generate_ecc(true, Curve::Ed25519)?.into();
4074 /// # let mut signer = key.into_keypair()?;
4075 /// # let msg = b"Hello, World";
4076 /// #
4077 /// let mut builder = SignatureBuilder::new(SignatureType::Binary)
4078 /// // Build up the signature.
4079 /// ;
4080 /// builder.hashed_area_mut().add(Subpacket::new(
4081 /// SubpacketValue::Unknown {
4082 /// tag: SubpacketTag::Private(61),
4083 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
4084 /// },
4085 /// true)?)?;
4086 /// let sig = builder.sign_message(&mut signer, msg)?;
4087 /// # let mut sig = sig;
4088 /// # sig.verify_message(signer.public(), msg)?;
4089 /// # Ok(()) }
4090 /// ```
4091 ///
4092 /// This is necessary, because modifying the subpacket area
4093 /// doesn't follow the builder pattern like the surrounding code.
4094 /// Using this function, you can instead do:
4095 ///
4096 /// ```
4097 /// # use sequoia_openpgp as openpgp;
4098 /// # use openpgp::cert::prelude::*;
4099 /// # use openpgp::packet::prelude::*;
4100 /// # use openpgp::packet::signature::subpacket::{
4101 /// # Subpacket,
4102 /// # SubpacketTag,
4103 /// # SubpacketValue,
4104 /// # };
4105 /// # use openpgp::types::Curve;
4106 /// # use openpgp::types::SignatureType;
4107 /// #
4108 /// # fn main() -> openpgp::Result<()> {
4109 /// #
4110 /// # let key: Key<key::SecretParts, key::PrimaryRole>
4111 /// # = Key6::generate_ecc(true, Curve::Ed25519)?.into();
4112 /// # let mut signer = key.into_keypair()?;
4113 /// # let msg = b"Hello, World";
4114 /// #
4115 /// let sig = SignatureBuilder::new(SignatureType::Binary)
4116 /// // Call some setters.
4117 /// .modify_hashed_area(|mut a| {
4118 /// a.add(Subpacket::new(
4119 /// SubpacketValue::Unknown {
4120 /// tag: SubpacketTag::Private(61),
4121 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
4122 /// },
4123 /// true)?);
4124 /// Ok(a)
4125 /// })?
4126 /// .sign_message(&mut signer, msg)?;
4127 /// # let mut sig = sig;
4128 /// # sig.verify_message(signer.public(), msg)?;
4129 /// # Ok(()) }
4130 /// ```
4131 ///
4132 /// # Examples
4133 ///
4134 /// Add a critical, custom subpacket to a certificate's direct key
4135 /// signature:
4136 ///
4137 /// ```
4138 /// use sequoia_openpgp as openpgp;
4139 /// use openpgp::cert::prelude::*;
4140 /// use openpgp::packet::prelude::*;
4141 /// use openpgp::packet::signature::subpacket::{
4142 /// Subpacket,
4143 /// SubpacketTag,
4144 /// SubpacketValue,
4145 /// };
4146 /// use openpgp::policy::StandardPolicy;
4147 /// use openpgp::types::Features;
4148 ///
4149 /// # fn main() -> openpgp::Result<()> {
4150 /// let p = &StandardPolicy::new();
4151 ///
4152 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
4153 ///
4154 /// // Derive a signer (the primary key is always certification capable).
4155 /// let pk = cert.primary_key().key();
4156 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
4157 ///
4158 /// let vc = cert.with_policy(p, None)?;
4159 ///
4160 /// let sig = vc.direct_key_signature().expect("direct key signature");
4161 /// let sig = SignatureBuilder::from(sig.clone())
4162 /// .modify_hashed_area(|mut a| {
4163 /// a.add(Subpacket::new(
4164 /// SubpacketValue::Unknown {
4165 /// tag: SubpacketTag::Private(61),
4166 /// body: [0x6D, 0x6F, 0x6F].to_vec(),
4167 /// },
4168 /// true)?)?;
4169 /// Ok(a)
4170 /// })?
4171 /// .sign_direct_key(&mut signer, None)?;
4172 ///
4173 /// // Merge in the new signature.
4174 /// let cert = cert.insert_packets(sig)?.0;
4175 /// # assert_eq!(cert.bad_signatures().count(), 0);
4176 /// # Ok(())
4177 /// # }
4178 /// ```
4179 ///
4180 /// Update a certificate's feature set by updating the `Features`
4181 /// subpacket on any direct key signature, and any User ID binding
4182 /// signatures:
4183 ///
4184 /// ```
4185 /// use sequoia_openpgp as openpgp;
4186 /// use openpgp::cert::prelude::*;
4187 /// use openpgp::packet::prelude::*;
4188 /// use openpgp::packet::signature::subpacket::{Subpacket, SubpacketValue};
4189 /// use openpgp::policy::StandardPolicy;
4190 /// use openpgp::types::Features;
4191 ///
4192 /// # fn main() -> openpgp::Result<()> {
4193 /// let p = &StandardPolicy::new();
4194 ///
4195 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
4196 ///
4197 /// // Derive a signer (the primary key is always certification capable).
4198 /// let pk = cert.primary_key().key();
4199 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
4200 ///
4201 /// let mut sigs = Vec::new();
4202 ///
4203 /// let vc = cert.with_policy(p, None)?;
4204 ///
4205 /// if let Ok(sig) = vc.direct_key_signature() {
4206 /// sigs.push(SignatureBuilder::from(sig.clone())
4207 /// .modify_hashed_area(|mut a| {
4208 /// a.replace(Subpacket::new(
4209 /// SubpacketValue::Features(Features::sequoia().set(10)),
4210 /// false)?)?;
4211 /// Ok(a)
4212 /// })?
4213 /// // Update the direct key signature.
4214 /// .sign_direct_key(&mut signer, Some(pk))?);
4215 /// }
4216 ///
4217 /// for ua in vc.userids() {
4218 /// sigs.push(SignatureBuilder::from(ua.binding_signature().clone())
4219 /// .modify_hashed_area(|mut a| {
4220 /// a.replace(Subpacket::new(
4221 /// SubpacketValue::Features(Features::sequoia().set(10)),
4222 /// false)?)?;
4223 /// Ok(a)
4224 /// })?
4225 /// // Update the binding signature.
4226 /// .sign_userid_binding(&mut signer, pk, ua.userid())?);
4227 /// }
4228 ///
4229 /// // Merge in the new signatures.
4230 /// let cert = cert.insert_packets(sigs)?.0;
4231 /// # assert_eq!(cert.bad_signatures().count(), 0);
4232 /// # Ok(())
4233 /// # }
4234 /// ```
4235 pub fn modify_hashed_area<F>(mut self, f: F)
4236 -> Result<Self>
4237 where F: FnOnce(SubpacketArea) -> Result<SubpacketArea>
4238 {
4239 self.fields.subpackets.hashed_area
4240 = f(self.fields.subpackets.hashed_area)?;
4241 Ok(self)
4242 }
4243
4244 /// Sets the Signature Creation Time subpacket.
4245 ///
4246 /// Adds a [Signature Creation Time subpacket] to the hashed
4247 /// subpacket area. This function first removes any Signature
4248 /// Creation Time subpacket from the hashed subpacket area.
4249 ///
4250 /// The Signature Creation Time subpacket specifies when the
4251 /// signature was created. According to the standard, all
4252 /// signatures must include a Signature Creation Time subpacket in
4253 /// the signature's hashed area. This doesn't mean that the time
4254 /// stamp is correct: the issuer can always forge it.
4255 ///
4256 /// When creating a signature using a SignatureBuilder or the
4257 /// [streaming `Signer`], it is not necessary to explicitly set
4258 /// this subpacket: those functions automatically set the
4259 /// signature creation time, if it has not been set explicitly.
4260 ///
4261 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
4262 /// [streaming `Signer`]: crate::serialize::stream::Signer
4263 ///
4264 /// # Examples
4265 ///
4266 /// Create a backdated signature:
4267 ///
4268 /// ```
4269 /// use sequoia_openpgp as openpgp;
4270 /// use openpgp::cert::prelude::*;
4271 /// use openpgp::packet::signature::SignatureBuilder;
4272 /// use openpgp::types::SignatureType;
4273 ///
4274 /// # fn main() -> openpgp::Result<()> {
4275 /// #
4276 /// # let (cert, _) =
4277 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4278 /// # // We also need to backdate the certificate.
4279 /// # .set_creation_time(
4280 /// # std::time::SystemTime::now()
4281 /// # - std::time::Duration::new(2 * 24 * 60 * 60, 0))
4282 /// # .generate()?;
4283 /// # let mut signer = cert.primary_key().key().clone()
4284 /// # .parts_into_secret()?.into_keypair()?;
4285 /// let msg = "hiermit kündige ich den mit Ihnen bestehenden Vertrag fristgerecht.";
4286 ///
4287 /// let mut sig = SignatureBuilder::new(SignatureType::Binary)
4288 /// .set_signature_creation_time(
4289 /// std::time::SystemTime::now()
4290 /// - std::time::Duration::new(24 * 60 * 60, 0))?
4291 /// .sign_message(&mut signer, msg)?;
4292 ///
4293 /// assert!(sig.verify_message(signer.public(), msg).is_ok());
4294 /// # Ok(()) }
4295 /// ```
4296 pub fn set_signature_creation_time<T>(mut self, creation_time: T)
4297 -> Result<Self>
4298 where T: Into<time::SystemTime>
4299 {
4300 self.hashed_area.replace(Subpacket::new(
4301 SubpacketValue::SignatureCreationTime(
4302 creation_time.into().try_into()?),
4303 true)?)?;
4304
4305 self.overrode_creation_time = true;
4306 Ok(self)
4307 }
4308
4309 /// Causes the builder to use an existing signature creation time
4310 /// subpacket.
4311 ///
4312 /// When converting a [`Signature`] to a `SignatureBuilder`, the
4313 /// [Signature Creation Time subpacket] is removed from the hashed
4314 /// area, and saved internally. When creating the signature, a
4315 /// Signature Creation Time subpacket with the current time is
4316 /// normally added to the hashed area. Calling this function
4317 /// instead causes the signature generation code to use the cached
4318 /// `Signature Creation Time` subpacket.
4319 ///
4320 /// [`Signature`]: super::Signature
4321 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
4322 ///
4323 /// This function returns an error if there is no cached
4324 /// `Signature Creation Time` subpacket.
4325 ///
4326 /// # Examples
4327 ///
4328 /// Alice signs a message. Shortly thereafter, Bob signs the
4329 /// message using a nearly identical Signature packet:
4330 ///
4331 /// ```
4332 /// use sequoia_openpgp as openpgp;
4333 /// # use openpgp::cert::prelude::*;
4334 /// use openpgp::packet::signature::SignatureBuilder;
4335 /// use openpgp::types::SignatureType;
4336 ///
4337 /// # fn main() -> openpgp::Result<()> {
4338 /// #
4339 /// # let (alice, _) =
4340 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4341 /// # .generate()?;
4342 /// # let mut alices_signer = alice.primary_key().key().clone()
4343 /// # .parts_into_secret()?.into_keypair()?;
4344 /// # let (bob, _) =
4345 /// # CertBuilder::general_purpose(Some("bob@example.org"))
4346 /// # .generate()?;
4347 /// # let mut bobs_signer = bob.primary_key().key().clone()
4348 /// # .parts_into_secret()?.into_keypair()?;
4349 /// let msg = "Version 489 of Foo has the SHA256 sum e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
4350 ///
4351 /// let siga = SignatureBuilder::new(SignatureType::Binary)
4352 /// .sign_message(&mut alices_signer, msg)?;
4353 /// let sigb = SignatureBuilder::from(siga.clone())
4354 /// .preserve_signature_creation_time()?
4355 /// .sign_message(&mut bobs_signer, msg)?;
4356 /// #
4357 /// # let mut siga = siga;
4358 /// # let mut sigb = sigb;
4359 /// # assert!(siga.verify_message(alices_signer.public(), msg).is_ok());
4360 /// # assert!(sigb.verify_message(bobs_signer.public(), msg).is_ok());
4361 /// # assert_eq!(siga.signature_creation_time(),
4362 /// # sigb.signature_creation_time());
4363 /// # Ok(()) }
4364 /// ```
4365 pub fn preserve_signature_creation_time(self)
4366 -> Result<Self>
4367 {
4368 if let Some(t) = self.original_creation_time {
4369 self.set_signature_creation_time(t)
4370 } else {
4371 Err(Error::InvalidOperation(
4372 "Signature does not contain a Signature Creation Time subpacket".into())
4373 .into())
4374 }
4375 }
4376
4377 /// Causes the builder to not output a Signature Creation Time
4378 /// subpacket.
4379 ///
4380 /// When creating a signature, a [Signature Creation Time
4381 /// subpacket] is added to the hashed area if one hasn't been
4382 /// added already. This function suppresses that behavior.
4383 ///
4384 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
4385 ///
4386 /// [Section 5.2.3.11 of RFC 9580] says that the `Signature
4387 /// Creation Time` subpacket must be present in the hashed area.
4388 /// This function clears any `Signature Creation Time` subpackets
4389 /// from both the hashed area and the unhashed area, and causes
4390 /// the various `SignatureBuilder` finalizers to not emit a
4391 /// `Signature Creation Time` subpacket. This function should
4392 /// only be used for generating test data.
4393 ///
4394 /// [Section 5.2.3.11 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
4395 ///
4396 /// # Examples
4397 ///
4398 /// Create a signature without a Signature Creation Time
4399 /// subpacket. As per the specification, Sequoia considers such
4400 /// signatures to be invalid:
4401 ///
4402 /// ```
4403 /// use sequoia_openpgp as openpgp;
4404 /// use openpgp::cert::prelude::*;
4405 /// use openpgp::packet::signature::SignatureBuilder;
4406 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4407 /// use openpgp::types::SignatureType;
4408 ///
4409 /// # fn main() -> openpgp::Result<()> {
4410 /// #
4411 /// # let (cert, _) =
4412 /// # CertBuilder::general_purpose(Some("alice@example.org"))
4413 /// # .generate()?;
4414 /// # let mut signer = cert.primary_key().key().clone()
4415 /// # .parts_into_secret()?.into_keypair()?;
4416 /// let msg = "Some things are timeless.";
4417 ///
4418 /// let mut sig = SignatureBuilder::new(SignatureType::Binary)
4419 /// .suppress_signature_creation_time()?
4420 /// .sign_message(&mut signer, msg)?;
4421 ///
4422 /// assert!(sig.verify_message(signer.public(), msg).is_err());
4423 /// # assert_eq!(sig
4424 /// # .hashed_area()
4425 /// # .iter()
4426 /// # .filter(|sp| sp.tag() == SubpacketTag::SignatureCreationTime)
4427 /// # .count(),
4428 /// # 0);
4429 /// # Ok(()) }
4430 /// ```
4431 pub fn suppress_signature_creation_time(mut self)
4432 -> Result<Self>
4433 {
4434 self.hashed_area.remove_all(SubpacketTag::SignatureCreationTime);
4435 self.unhashed_area.remove_all(SubpacketTag::SignatureCreationTime);
4436
4437 self.overrode_creation_time = true;
4438 Ok(self)
4439 }
4440
4441 /// Returns the value of the Signature Expiration Time subpacket
4442 /// as an absolute time.
4443 ///
4444 /// A [Signature Expiration Time subpacket] specifies when the
4445 /// signature expires. The value stored is not an absolute time,
4446 /// but a duration, which is relative to the Signature's creation
4447 /// time. To better reflect the subpacket's name, this method
4448 /// returns the absolute expiry time, and the
4449 /// [`SubpacketAreas::signature_validity_period`] method returns
4450 /// the subpacket's raw value.
4451 ///
4452 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
4453 /// [`SubpacketAreas::signature_validity_period`]: SubpacketAreas::signature_validity_period()
4454 ///
4455 /// The Signature Expiration Time subpacket is different from the
4456 /// [Key Expiration Time subpacket], which is accessed using
4457 /// [`SubpacketAreas::key_validity_period`], and used specifies
4458 /// when an associated key expires. The difference is that in the
4459 /// former case, the signature itself expires, but in the latter
4460 /// case, only the associated key expires. This difference is
4461 /// critical: if a binding signature expires, then an OpenPGP
4462 /// implementation will still consider the associated key to be
4463 /// valid if there is another valid binding signature, even if it
4464 /// is older than the expired signature; if the active binding
4465 /// signature indicates that the key has expired, then OpenPGP
4466 /// implementations will not fall back to an older binding
4467 /// signature.
4468 ///
4469 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
4470 /// [`SubpacketAreas::key_validity_period`]: SubpacketAreas::key_validity_period()
4471 ///
4472 /// There are several cases where having a signature expire is
4473 /// useful. Say Alice certifies Bob's certificate for
4474 /// `bob@example.org`. She can limit the lifetime of the
4475 /// certification to force her to reevaluate the certification
4476 /// shortly before it expires. For instance, is Bob still
4477 /// associated with `example.org`? Does she have reason to
4478 /// believe that his key has been compromised? Using an
4479 /// expiration is common in the X.509 ecosystem. For instance,
4480 /// [Let's Encrypt] issues certificates with 90-day lifetimes.
4481 ///
4482 /// [Let's Encrypt]: https://letsencrypt.org/2015/11/09/why-90-days.html
4483 ///
4484 /// Having signatures expire can also be useful when deploying
4485 /// software. For instance, you might have a service that
4486 /// installs an update if it has been signed by a trusted
4487 /// certificate. To prevent an adversary from coercing the
4488 /// service to install an older version, you could limit the
4489 /// signature's lifetime to just a few minutes.
4490 ///
4491 /// If the subpacket is not present in the hashed subpacket area,
4492 /// this returns `None`. If this function returns `None`, the
4493 /// signature does not expire.
4494 ///
4495 /// Note: if the signature contains multiple instances of this
4496 /// subpacket in the hashed subpacket area, the last one is
4497 /// returned.
4498 // Note: This shadows SubpacketAreas::signature_expiration_time
4499 // (SignatureBuilder derefs to SubpacketAreas), because we need to
4500 // take SignatureBuilder::reference_time into account.
4501 //
4502 // If you update this function, also update
4503 // SubpacketAreas::signature_expiration_time.
4504 pub fn signature_expiration_time(&self) -> Option<time::SystemTime> {
4505 match (self.effective_signature_creation_time(),
4506 // This ^ is the difference to
4507 // SubpacketAreas::signature_expiration_time.
4508 self.signature_validity_period())
4509 {
4510 (Ok(Some(ct)), Some(vp)) if vp.as_secs() > 0 => Some(ct + vp),
4511 _ => None,
4512 }
4513 }
4514
4515 /// Sets the Signature Expiration Time subpacket.
4516 ///
4517 /// Adds a [Signature Expiration Time subpacket] to the hashed
4518 /// subpacket area. This function first removes any Signature
4519 /// Expiration Time subpacket from the hashed subpacket area.
4520 ///
4521 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.18
4522 ///
4523 /// This function is called `set_signature_validity_period` and
4524 /// not `set_signature_expiration_time`, which would be more
4525 /// consistent with the subpacket's name, because the latter
4526 /// suggests an absolute time, but the time is actually relative
4527 /// to the signature's creation time, which is stored in the
4528 /// signature's [Signature Creation Time subpacket] and set using
4529 /// [`SignatureBuilder::set_signature_creation_time`].
4530 ///
4531 /// [Signature Creation Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.11
4532 /// [`SignatureBuilder::set_signature_creation_time`]: super::SignatureBuilder::set_signature_creation_time()
4533 ///
4534 /// A Signature Expiration Time subpacket specifies when the
4535 /// signature expires. This is different from the [Key Expiration
4536 /// Time subpacket], which is set using
4537 /// [`SignatureBuilder::set_key_validity_period`], and used to
4538 /// specify when an associated key expires. The difference is
4539 /// that in the former case, the signature itself expires, but in
4540 /// the latter case, only the associated key expires. This
4541 /// difference is critical: if a binding signature expires, then
4542 /// an OpenPGP implementation will still consider the associated
4543 /// key to be valid if there is another valid binding signature,
4544 /// even if it is older than the expired signature; if the active
4545 /// binding signature indicates that the key has expired, then
4546 /// OpenPGP implementations will not fall back to an older binding
4547 /// signature.
4548 ///
4549 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
4550 /// [`SignatureBuilder::set_key_validity_period`]: super::SignatureBuilder::set_key_validity_period()
4551 ///
4552 /// There are several cases where having a signature expire is
4553 /// useful. Say Alice certifies Bob's certificate for
4554 /// `bob@example.org`. She can limit the lifetime of the
4555 /// certification to force her to reevaluate the certification
4556 /// shortly before it expires. For instance, is Bob still
4557 /// associated with `example.org`? Does she have reason to
4558 /// believe that his key has been compromised? Using an
4559 /// expiration is common in the X.509 ecosystem. For instance,
4560 /// [Let's Encrypt] issues certificates with 90-day lifetimes.
4561 ///
4562 /// [Let's Encrypt]: https://letsencrypt.org/2015/11/09/why-90-days.html
4563 ///
4564 /// Having signatures expire can also be useful when deploying
4565 /// software. For instance, you might have a service that
4566 /// installs an update if it has been signed by a trusted
4567 /// certificate. To prevent an adversary from coercing the
4568 /// service to install an older version, you could limit the
4569 /// signature's lifetime to just a few minutes.
4570 ///
4571 /// # Examples
4572 ///
4573 /// Create a signature that expires in 10 minutes:
4574 ///
4575 /// ```
4576 /// use sequoia_openpgp as openpgp;
4577 /// use openpgp::cert::prelude::*;
4578 /// use openpgp::packet::signature::SignatureBuilder;
4579 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4580 /// use openpgp::types::SignatureType;
4581 ///
4582 /// # fn main() -> openpgp::Result<()> {
4583 /// #
4584 /// let (cert, _) =
4585 /// CertBuilder::general_purpose(Some("alice@example.org"))
4586 /// .generate()?;
4587 /// let mut signer = cert.primary_key().key().clone()
4588 /// .parts_into_secret()?.into_keypair()?;
4589 ///
4590 /// let msg = "install e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
4591 ///
4592 /// let mut sig = SignatureBuilder::new(SignatureType::Binary)
4593 /// .set_signature_validity_period(
4594 /// std::time::Duration::new(10 * 60, 0))?
4595 /// .sign_message(&mut signer, msg)?;
4596 ///
4597 /// assert!(sig.verify_message(signer.public(), msg).is_ok());
4598 /// # assert_eq!(sig
4599 /// # .hashed_area()
4600 /// # .iter()
4601 /// # .filter(|sp| sp.tag() == SubpacketTag::SignatureExpirationTime)
4602 /// # .count(),
4603 /// # 1);
4604 /// # Ok(()) }
4605 /// ```
4606 ///
4607 /// Create a certification that expires at the end of the year
4608 /// (give or take a few seconds) unless the new year is in a
4609 /// month, then have it expire at the end of the following year:
4610 ///
4611 /// ```
4612 /// use std::time::{SystemTime, UNIX_EPOCH, Duration};
4613 /// use sequoia_openpgp as openpgp;
4614 /// use openpgp::cert::prelude::*;
4615 /// use openpgp::packet::signature::SignatureBuilder;
4616 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4617 /// use openpgp::types::SignatureType;
4618 ///
4619 /// # fn main() -> openpgp::Result<()> {
4620 /// let (cert, _) =
4621 /// CertBuilder::general_purpose(Some("alice@example.org"))
4622 /// .generate()?;
4623 /// let mut signer = cert.primary_key().key().clone()
4624 /// .parts_into_secret()?.into_keypair()?;
4625 ///
4626 /// let msg = "message.";
4627 ///
4628 /// // Average number of seconds in a year. See:
4629 /// // https://en.wikipedia.org/wiki/Year .
4630 /// const SECONDS_IN_YEAR: u64 = (365.2425 * 24. * 60. * 60.) as u64;
4631 ///
4632 /// let now = SystemTime::now();
4633 /// let since_epoch = now.duration_since(UNIX_EPOCH)?.as_secs();
4634 /// let next_year
4635 /// = (since_epoch + SECONDS_IN_YEAR) - (since_epoch % SECONDS_IN_YEAR);
4636 /// // Make sure the expiration is at least a month in the future.
4637 /// let next_year = if next_year - since_epoch < SECONDS_IN_YEAR / 12 {
4638 /// next_year + SECONDS_IN_YEAR
4639 /// } else {
4640 /// next_year
4641 /// };
4642 /// let next_year = UNIX_EPOCH + Duration::new(next_year, 0);
4643 /// let next_year = next_year.duration_since(now)?;
4644 ///
4645 /// let sig = SignatureBuilder::new(SignatureType::Binary)
4646 /// .set_signature_creation_time(now)?
4647 /// .set_signature_validity_period(next_year)?
4648 /// .sign_message(&mut signer, msg)?;
4649 /// #
4650 /// # let mut sig = sig;
4651 /// # assert!(sig.verify_message(signer.public(), msg).is_ok());
4652 /// # assert_eq!(sig
4653 /// # .hashed_area()
4654 /// # .iter()
4655 /// # .filter(|sp| sp.tag() == SubpacketTag::SignatureExpirationTime)
4656 /// # .count(),
4657 /// # 1);
4658 /// # Ok(()) }
4659 /// ```
4660 pub fn set_signature_validity_period<D>(mut self, expires_in: D)
4661 -> Result<Self>
4662 where D: Into<time::Duration>
4663 {
4664 self.hashed_area.replace(Subpacket::new(
4665 SubpacketValue::SignatureExpirationTime(
4666 Duration::try_from(expires_in.into())?),
4667 true)?)?;
4668
4669 Ok(self)
4670 }
4671
4672 /// Sets the Exportable Certification subpacket.
4673 ///
4674 /// Adds an [Exportable Certification subpacket] to the hashed
4675 /// subpacket area. This function first removes any Exportable
4676 /// Certification subpacket from the hashed subpacket area.
4677 ///
4678 /// [Exportable Certification subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.19
4679 ///
4680 /// The Exportable Certification subpacket indicates whether the
4681 /// signature should be exported (e.g., published on a public key
4682 /// server) or not. When using [`Serialize::export`] to export a
4683 /// certificate, signatures that have this subpacket present and
4684 /// set to false are not serialized.
4685 ///
4686 /// [`Serialize::export`]: https://docs.sequoia-pgp.org/sequoia_openpgp/serialize/trait.Serialize.html#method.export
4687 ///
4688 /// # Examples
4689 ///
4690 /// Alice certificates Bob's certificate, but because she doesn't
4691 /// want to publish it, she creates a so-called local signature by
4692 /// adding an Exportable Certification subpacket set to `false` to
4693 /// the signature:
4694 ///
4695 /// ```
4696 /// use sequoia_openpgp as openpgp;
4697 /// use openpgp::cert::prelude::*;
4698 /// use openpgp::packet::prelude::*;
4699 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4700 /// use openpgp::policy::StandardPolicy;
4701 /// use openpgp::types::SignatureType;
4702 ///
4703 /// # fn main() -> openpgp::Result<()> {
4704 /// #
4705 /// let p = &StandardPolicy::new();
4706 ///
4707 /// let (alice, _)
4708 /// = CertBuilder::general_purpose(Some("alice@example.org"))
4709 /// .generate()?;
4710 /// let mut alices_signer = alice.primary_key().key().clone()
4711 /// .parts_into_secret()?.into_keypair()?;
4712 ///
4713 /// let (bob, _)
4714 /// = CertBuilder::general_purpose(Some("bob@example.org"))
4715 /// .generate()?;
4716 /// let bobs_userid
4717 /// = bob.with_policy(p, None)?.userids().nth(0).expect("Added a User ID").userid();
4718 ///
4719 /// let certification = SignatureBuilder::new(SignatureType::GenericCertification)
4720 /// .set_exportable_certification(false)?
4721 /// .sign_userid_binding(
4722 /// &mut alices_signer, bob.primary_key().key(), bobs_userid)?;
4723 /// # assert_eq!(certification
4724 /// # .hashed_area()
4725 /// # .iter()
4726 /// # .filter(|sp| sp.tag() == SubpacketTag::ExportableCertification)
4727 /// # .count(),
4728 /// # 1);
4729 ///
4730 /// // Merge in the new signature.
4731 /// let bob = bob.insert_packets(certification)?.0;
4732 /// # assert_eq!(bob.bad_signatures().count(), 0);
4733 /// # assert_eq!(bob.userids().nth(0).unwrap().certifications().count(), 1);
4734 /// # Ok(()) }
4735 /// ```
4736 pub fn set_exportable_certification(mut self, exportable: bool)
4737 -> Result<Self> {
4738 self.hashed_area.replace(Subpacket::new(
4739 SubpacketValue::ExportableCertification(exportable),
4740 true)?)?;
4741
4742 Ok(self)
4743 }
4744
4745 /// Sets the Trust Signature subpacket.
4746 ///
4747 /// Adds a [Trust Signature subpacket] to the hashed subpacket
4748 /// area. This function first removes any Trust Signature
4749 /// subpacket from the hashed subpacket area.
4750 ///
4751 /// [Trust Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
4752 ///
4753 /// The Trust Signature subpacket indicates the degree to which a
4754 /// certificate holder is trusted to certify other keys.
4755 ///
4756 /// A level of 0 means that the certificate holder is not trusted
4757 /// to certificate other keys, a level of 1 means that the
4758 /// certificate holder is a trusted introducer (a [certificate
4759 /// authority]) and any certifications that they make should be
4760 /// considered valid. A level of 2 means the certificate holder
4761 /// can designate level 1 trusted introducers, etc.
4762 ///
4763 /// [certificate authority]: https://en.wikipedia.org/wiki/Certificate_authority
4764 ///
4765 /// The trust indicates the degree of confidence. A value of 120
4766 /// means that a certification should be considered valid. A
4767 /// value of 60 means that a certification should only be
4768 /// considered partially valid. In the latter case, typically
4769 /// three such certifications are required for a binding to be
4770 /// considered authenticated.
4771 ///
4772 /// # Examples
4773 ///
4774 /// Alice designates Bob as a fully trusted, trusted introducer:
4775 ///
4776 /// ```
4777 /// use sequoia_openpgp as openpgp;
4778 /// use openpgp::cert::prelude::*;
4779 /// use openpgp::packet::prelude::*;
4780 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4781 /// use openpgp::policy::StandardPolicy;
4782 /// use openpgp::types::SignatureType;
4783 ///
4784 /// # fn main() -> openpgp::Result<()> {
4785 /// #
4786 /// let p = &StandardPolicy::new();
4787 ///
4788 /// let (alice, _)
4789 /// = CertBuilder::general_purpose(Some("alice@example.org"))
4790 /// .generate()?;
4791 /// let mut alices_signer = alice.primary_key().key().clone()
4792 /// .parts_into_secret()?.into_keypair()?;
4793 ///
4794 /// let (bob, _)
4795 /// = CertBuilder::general_purpose(Some("bob@example.org"))
4796 /// .generate()?;
4797 /// let bobs_userid
4798 /// = bob.with_policy(p, None)?.userids().nth(0).expect("Added a User ID").userid();
4799 ///
4800 /// let certification = SignatureBuilder::new(SignatureType::GenericCertification)
4801 /// .set_trust_signature(1, 120)?
4802 /// .sign_userid_binding(
4803 /// &mut alices_signer, bob.primary_key().component(), bobs_userid)?;
4804 /// # assert_eq!(certification
4805 /// # .hashed_area()
4806 /// # .iter()
4807 /// # .filter(|sp| sp.tag() == SubpacketTag::TrustSignature)
4808 /// # .count(),
4809 /// # 1);
4810 ///
4811 /// // Merge in the new signature.
4812 /// let bob = bob.insert_packets(certification)?.0;
4813 /// # assert_eq!(bob.bad_signatures().count(), 0);
4814 /// # assert_eq!(bob.userids().nth(0).unwrap().certifications().count(), 1);
4815 /// # Ok(()) }
4816 /// ```
4817 pub fn set_trust_signature(mut self, level: u8, trust: u8)
4818 -> Result<Self> {
4819 self.hashed_area.replace(Subpacket::new(
4820 SubpacketValue::TrustSignature {
4821 level,
4822 trust,
4823 },
4824 true)?)?;
4825
4826 Ok(self)
4827 }
4828
4829 /// Sets the Regular Expression subpacket.
4830 ///
4831 /// Adds a [Regular Expression subpacket] to the hashed subpacket
4832 /// area. This function first removes any Regular Expression
4833 /// subpacket from the hashed subpacket area.
4834 ///
4835 /// [Regular Expression subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.22
4836 ///
4837 /// The Regular Expression subpacket is used in conjunction with a
4838 /// [Trust Signature subpacket], which is set using
4839 /// [`SignatureBuilder::set_trust_signature`], to limit the scope
4840 /// of a trusted introducer. This is useful, for instance, when a
4841 /// company has a CA and you only want to trust them to certify
4842 /// their own employees.
4843 ///
4844 /// [Trust Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
4845 /// [`SignatureBuilder::set_trust_signature`]: super::SignatureBuilder::set_trust_signature()
4846 ///
4847 /// GnuPG only supports [a limited form of regular expressions].
4848 ///
4849 /// [a limited form of regular expressions]: https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=g10/trustdb.c;h=c4b996a9685486b2095608f6685727022120505f;hb=refs/heads/master#l1537
4850 ///
4851 /// Note: The serialized form includes a trailing `NUL` byte.
4852 /// Sequoia adds this `NUL` when serializing the signature.
4853 /// Adding it yourself will result in two trailing NUL bytes.
4854 ///
4855 /// # Examples
4856 ///
4857 /// Alice designates ``openpgp-ca@example.com`` as a fully
4858 /// trusted, trusted introducer, but only for users from the
4859 /// ``example.com`` domain:
4860 ///
4861 /// ```
4862 /// use sequoia_openpgp as openpgp;
4863 /// use openpgp::cert::prelude::*;
4864 /// use openpgp::packet::prelude::*;
4865 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4866 /// use openpgp::policy::StandardPolicy;
4867 /// use openpgp::types::SignatureType;
4868 ///
4869 /// # fn main() -> openpgp::Result<()> {
4870 /// #
4871 /// let p = &StandardPolicy::new();
4872 ///
4873 /// let (alice, _)
4874 /// = CertBuilder::general_purpose(Some("Alice <alice@example.org>"))
4875 /// .generate()?;
4876 /// let mut alices_signer = alice.primary_key().key().clone()
4877 /// .parts_into_secret()?.into_keypair()?;
4878 ///
4879 /// let (example_com, _)
4880 /// = CertBuilder::general_purpose(Some("OpenPGP CA <openpgp-ca@example.com>"))
4881 /// .generate()?;
4882 /// let example_com_userid = example_com.with_policy(p, None)?
4883 /// .userids().nth(0).expect("Added a User ID").userid();
4884 ///
4885 /// let certification = SignatureBuilder::new(SignatureType::GenericCertification)
4886 /// .set_trust_signature(1, 120)?
4887 /// .set_regular_expression("<[^>]+[@.]example\\.com>$")?
4888 /// .sign_userid_binding(
4889 /// &mut alices_signer,
4890 /// example_com.primary_key().component(),
4891 /// example_com_userid)?;
4892 /// # assert_eq!(certification
4893 /// # .hashed_area()
4894 /// # .iter()
4895 /// # .filter(|sp| sp.tag() == SubpacketTag::TrustSignature)
4896 /// # .count(),
4897 /// # 1);
4898 /// # assert_eq!(certification
4899 /// # .hashed_area()
4900 /// # .iter()
4901 /// # .filter(|sp| sp.tag() == SubpacketTag::RegularExpression)
4902 /// # .count(),
4903 /// # 1);
4904 ///
4905 /// // Merge in the new signature.
4906 /// let example_com = example_com.insert_packets(certification)?.0;
4907 /// # assert_eq!(example_com.bad_signatures().count(), 0);
4908 /// # assert_eq!(example_com.userids().nth(0).unwrap().certifications().count(), 1);
4909 /// # Ok(()) }
4910 /// ```
4911 pub fn set_regular_expression<R>(mut self, re: R) -> Result<Self>
4912 where R: AsRef<[u8]>
4913 {
4914 self.hashed_area.replace(Subpacket::new(
4915 SubpacketValue::RegularExpression(re.as_ref().to_vec()),
4916 true)?)?;
4917
4918 Ok(self)
4919 }
4920
4921 /// Sets a Regular Expression subpacket.
4922 ///
4923 /// Adds a [Regular Expression subpacket] to the hashed subpacket
4924 /// area. Unlike [`SignatureBuilder::set_regular_expression`],
4925 /// this function does not first remove any Regular Expression
4926 /// subpacket from the hashed subpacket area, but adds an
4927 /// additional Regular Expression subpacket to the hashed
4928 /// subpacket area.
4929 ///
4930 /// [`SignatureBuilder::set_regular_expression`]: super::SignatureBuilder::set_regular_expression()
4931 /// [Regular Expression subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.22
4932 ///
4933 /// The Regular Expression subpacket is used in conjunction with a
4934 /// [Trust Signature subpacket], which is set using
4935 /// [`SignatureBuilder::set_trust_signature`], to limit the scope
4936 /// of a trusted introducer. This is useful, for instance, when a
4937 /// company has a CA and you only want to trust them to certify
4938 /// their own employees.
4939 ///
4940 /// [Trust Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.21
4941 /// [`SignatureBuilder::set_trust_signature`]: super::SignatureBuilder::set_trust_signature()
4942 ///
4943 /// GnuPG only supports [a limited form of regular expressions].
4944 ///
4945 /// [a limited form of regular expressions]: https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=g10/trustdb.c;h=c4b996a9685486b2095608f6685727022120505f;hb=refs/heads/master#l1537
4946 ///
4947 /// Note: The serialized form includes a trailing `NUL` byte.
4948 /// Sequoia adds this `NUL` when serializing the signature.
4949 /// Adding it yourself will result in two trailing NUL bytes.
4950 ///
4951 /// # Examples
4952 ///
4953 /// Alice designates ``openpgp-ca@example.com`` as a fully
4954 /// trusted, trusted introducer, but only for users from the
4955 /// ``example.com`` and ``example.net`` domains:
4956 ///
4957 /// ```
4958 /// use sequoia_openpgp as openpgp;
4959 /// use openpgp::cert::prelude::*;
4960 /// use openpgp::packet::prelude::*;
4961 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
4962 /// use openpgp::policy::StandardPolicy;
4963 /// use openpgp::types::SignatureType;
4964 ///
4965 /// # fn main() -> openpgp::Result<()> {
4966 /// #
4967 /// let p = &StandardPolicy::new();
4968 ///
4969 /// let (alice, _)
4970 /// = CertBuilder::general_purpose(Some("Alice <alice@example.org>"))
4971 /// .generate()?;
4972 /// let mut alices_signer = alice.primary_key().key().clone()
4973 /// .parts_into_secret()?.into_keypair()?;
4974 ///
4975 /// let (example_com, _)
4976 /// = CertBuilder::general_purpose(Some("OpenPGP CA <openpgp-ca@example.com>"))
4977 /// .generate()?;
4978 /// let example_com_userid = example_com.with_policy(p, None)?
4979 /// .userids().nth(0).expect("Added a User ID").userid();
4980 ///
4981 /// let certification = SignatureBuilder::new(SignatureType::GenericCertification)
4982 /// .set_trust_signature(1, 120)?
4983 /// .set_regular_expression("<[^>]+[@.]example\\.com>$")?
4984 /// .add_regular_expression("<[^>]+[@.]example\\.net>$")?
4985 /// .sign_userid_binding(
4986 /// &mut alices_signer,
4987 /// example_com.primary_key().component(),
4988 /// example_com_userid)?;
4989 /// # assert_eq!(certification
4990 /// # .hashed_area()
4991 /// # .iter()
4992 /// # .filter(|sp| sp.tag() == SubpacketTag::TrustSignature)
4993 /// # .count(),
4994 /// # 1);
4995 /// # assert_eq!(certification
4996 /// # .hashed_area()
4997 /// # .iter()
4998 /// # .filter(|sp| sp.tag() == SubpacketTag::RegularExpression)
4999 /// # .count(),
5000 /// # 2);
5001 ///
5002 /// // Merge in the new signature.
5003 /// let example_com = example_com.insert_packets(certification)?.0;
5004 /// # assert_eq!(example_com.bad_signatures().count(), 0);
5005 /// # assert_eq!(example_com.userids().nth(0).unwrap().certifications().count(), 1);
5006 /// # Ok(()) }
5007 /// ```
5008 pub fn add_regular_expression<R>(mut self, re: R) -> Result<Self>
5009 where R: AsRef<[u8]>
5010 {
5011 self.hashed_area.add(Subpacket::new(
5012 SubpacketValue::RegularExpression(re.as_ref().to_vec()),
5013 true)?)?;
5014
5015 Ok(self)
5016 }
5017
5018 /// Sets the Revocable subpacket.
5019 ///
5020 /// Adds a [Revocable subpacket] to the hashed subpacket area.
5021 /// This function first removes any Revocable subpacket from the
5022 /// hashed subpacket area.
5023 ///
5024 /// [Revocable subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.20
5025 ///
5026 /// The Revocable subpacket indicates whether a certification may
5027 /// be later revoked by creating a [Certification revocation
5028 /// signature] (0x30) that targets the signature using the
5029 /// [Signature Target subpacket] (set using the
5030 /// [`SignatureBuilder::set_signature_target`] method).
5031 ///
5032 /// [Certification revocation signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
5033 /// [Signature Target subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
5034 /// [`SignatureBuilder::set_signature_target`]: super::SignatureBuilder::set_signature_target()
5035 ///
5036 /// # Examples
5037 ///
5038 /// Alice certifies Bob's key and marks the certification as
5039 /// irrevocable. Since she can't revoke the signature, she limits
5040 /// the scope of misuse by setting the signature to expire in a
5041 /// year:
5042 ///
5043 /// ```
5044 /// use sequoia_openpgp as openpgp;
5045 /// use openpgp::cert::prelude::*;
5046 /// use openpgp::packet::prelude::*;
5047 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5048 /// use openpgp::policy::StandardPolicy;
5049 /// use openpgp::types::SignatureType;
5050 ///
5051 /// # fn main() -> openpgp::Result<()> {
5052 /// #
5053 /// let p = &StandardPolicy::new();
5054 ///
5055 /// let (alice, _)
5056 /// = CertBuilder::general_purpose(Some("alice@example.org"))
5057 /// .generate()?;
5058 /// let mut alices_signer = alice.primary_key().key().clone()
5059 /// .parts_into_secret()?.into_keypair()?;
5060 ///
5061 /// let (bob, _)
5062 /// = CertBuilder::general_purpose(Some("bob@example.org"))
5063 /// .generate()?;
5064 /// let bobs_userid
5065 /// = bob.with_policy(p, None)?.userids().nth(0).expect("Added a User ID").userid();
5066 ///
5067 /// // Average number of seconds in a year. See:
5068 /// // https://en.wikipedia.org/wiki/Year .
5069 /// const SECONDS_IN_YEAR: u64 = (365.2425 * 24. * 60. * 60.) as u64;
5070 ///
5071 /// let certification = SignatureBuilder::new(SignatureType::GenericCertification)
5072 /// .set_revocable(false)?
5073 /// .set_signature_validity_period(
5074 /// std::time::Duration::new(SECONDS_IN_YEAR, 0))?
5075 /// .sign_userid_binding(
5076 /// &mut alices_signer, bob.primary_key().component(), bobs_userid)?;
5077 /// # assert_eq!(certification
5078 /// # .hashed_area()
5079 /// # .iter()
5080 /// # .filter(|sp| sp.tag() == SubpacketTag::Revocable)
5081 /// # .count(),
5082 /// # 1);
5083 ///
5084 /// // Merge in the new signature.
5085 /// let bob = bob.insert_packets(certification)?.0;
5086 /// # assert_eq!(bob.bad_signatures().count(), 0);
5087 /// # assert_eq!(bob.userids().nth(0).unwrap().certifications().count(), 1);
5088 /// # Ok(()) }
5089 /// ```
5090 pub fn set_revocable(mut self, revocable: bool) -> Result<Self> {
5091 self.hashed_area.replace(Subpacket::new(
5092 SubpacketValue::Revocable(revocable),
5093 true)?)?;
5094
5095 Ok(self)
5096 }
5097
5098 /// Sets the Key Expiration Time subpacket.
5099 ///
5100 /// Adds a [Key Expiration Time subpacket] to the hashed subpacket
5101 /// area. This function first removes any Key Expiration Time
5102 /// subpacket from the hashed subpacket area.
5103 ///
5104 /// If `None` is given, any expiration subpacket is removed.
5105 ///
5106 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
5107 ///
5108 /// This function is called `set_key_validity_period` and not
5109 /// `set_key_expiration_time`, which would be more consistent with
5110 /// the subpacket's name, because the latter suggests an absolute
5111 /// time, but the time is actually relative to the associated
5112 /// key's (*not* the signature's) creation time, which is stored
5113 /// in the [Key].
5114 ///
5115 /// [Key]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
5116 ///
5117 /// There is a more convenient function
5118 /// [`SignatureBuilder::set_key_expiration_time`] that takes an
5119 /// absolute expiration time.
5120 ///
5121 /// [`SignatureBuilder::set_key_expiration_time`]: super::SignatureBuilder::set_key_expiration_time()
5122 ///
5123 /// A Key Expiration Time subpacket specifies when the associated
5124 /// key expires. This is different from the [Signature Expiration
5125 /// Time subpacket] (set using
5126 /// [`SignatureBuilder::set_signature_validity_period`]), which is
5127 /// used to specify when the signature expires. That is, in the
5128 /// former case, the associated key expires, but in the latter
5129 /// case, the signature itself expires. This difference is
5130 /// critical: if a binding signature expires, then an OpenPGP
5131 /// implementation will still consider the associated key to be
5132 /// valid if there is another valid binding signature, even if it
5133 /// is older than the expired signature; if the active binding
5134 /// signature indicates that the key has expired, then OpenPGP
5135 /// implementations will not fall back to an older binding
5136 /// signature.
5137 ///
5138 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
5139 /// [`SignatureBuilder::set_signature_validity_period`]: super::SignatureBuilder::set_signature_validity_period()
5140 ///
5141 /// # Examples
5142 ///
5143 /// Change all subkeys to expire 10 minutes after their (not the
5144 /// new binding signature's) creation time.
5145 ///
5146 /// ```
5147 /// use sequoia_openpgp as openpgp;
5148 /// use openpgp::cert::prelude::*;
5149 /// use openpgp::packet::prelude::*;
5150 /// use openpgp::policy::StandardPolicy;
5151 /// use openpgp::types::SignatureType;
5152 ///
5153 /// # fn main() -> openpgp::Result<()> {
5154 /// #
5155 /// let p = &StandardPolicy::new();
5156 ///
5157 /// let (cert, _) =
5158 /// CertBuilder::general_purpose(Some("alice@example.org"))
5159 /// .generate()?;
5160 /// let pk = cert.primary_key().key();
5161 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
5162 ///
5163 /// // Create the binding signatures.
5164 /// let mut sigs = Vec::new();
5165 ///
5166 /// for ka in cert.with_policy(p, None)?.keys().subkeys() {
5167 /// // This reuses any existing backsignature.
5168 /// let sig = SignatureBuilder::from(ka.binding_signature().clone())
5169 /// .set_key_validity_period(std::time::Duration::new(10 * 60, 0))?
5170 /// .sign_subkey_binding(&mut signer, None, ka.key())?;
5171 /// sigs.push(sig);
5172 /// }
5173 ///
5174 /// let cert = cert.insert_packets(sigs)?.0;
5175 /// # assert_eq!(cert.bad_signatures().count(), 0);
5176 /// #
5177 /// # // "Before"
5178 /// # for key in cert.with_policy(p, None)?.keys().subkeys() {
5179 /// # assert_eq!(key.bundle().self_signatures().count(), 2);
5180 /// # assert!(key.alive().is_ok());
5181 /// # }
5182 /// #
5183 /// # // "After"
5184 /// # for key in cert
5185 /// # .with_policy(p, std::time::SystemTime::now()
5186 /// # + std::time::Duration::new(20 * 60, 0))?
5187 /// # .keys().subkeys()
5188 /// # {
5189 /// # assert!(key.alive().is_err());
5190 /// # }
5191 /// # Ok(()) }
5192 /// ```
5193 pub fn set_key_validity_period<D>(mut self, expires_in: D)
5194 -> Result<Self>
5195 where D: Into<Option<time::Duration>>
5196 {
5197 if let Some(e) = expires_in.into() {
5198 self.hashed_area.replace(Subpacket::new(
5199 SubpacketValue::KeyExpirationTime(e.try_into()?),
5200 true)?)?;
5201 } else {
5202 self.hashed_area.remove_all(SubpacketTag::KeyExpirationTime);
5203 }
5204
5205 Ok(self)
5206 }
5207
5208 /// Sets the Key Expiration Time subpacket.
5209 ///
5210 /// Adds a [Key Expiration Time subpacket] to the hashed subpacket
5211 /// area. This function first removes any Key Expiration Time
5212 /// subpacket from the hashed subpacket area.
5213 ///
5214 /// If `None` is given, any expiration subpacket is removed.
5215 ///
5216 /// [Key Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
5217 ///
5218 /// This function is called `set_key_expiration_time` similar to
5219 /// the subpacket's name, but it takes an absolute time, whereas
5220 /// the subpacket stores a time relative to the associated key's
5221 /// (*not* the signature's) creation time, which is stored in the
5222 /// [Key].
5223 ///
5224 /// [Key]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
5225 ///
5226 /// This is a more convenient function than
5227 /// [`SignatureBuilder::set_key_validity_period`] that takes a
5228 /// relative expiration time.
5229 ///
5230 /// [`SignatureBuilder::set_key_validity_period`]: super::SignatureBuilder::set_key_validity_period()
5231 ///
5232 /// A Key Expiration Time subpacket specifies when the associated
5233 /// key expires. This is different from the [Signature Expiration
5234 /// Time subpacket] (set using
5235 /// [`SignatureBuilder::set_signature_validity_period`]), which is
5236 /// used to specify when the signature expires. That is, in the
5237 /// former case, the associated key expires, but in the latter
5238 /// case, the signature itself expires. This difference is
5239 /// critical: if a binding signature expires, then an OpenPGP
5240 /// implementation will still consider the associated key to be
5241 /// valid if there is another valid binding signature, even if it
5242 /// is older than the expired signature; if the active binding
5243 /// signature indicates that the key has expired, then OpenPGP
5244 /// implementations will not fall back to an older binding
5245 /// signature.
5246 ///
5247 /// [Signature Expiration Time subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.13
5248 /// [`SignatureBuilder::set_signature_validity_period`]: super::SignatureBuilder::set_signature_validity_period()
5249 ///
5250 /// # Examples
5251 ///
5252 /// Change all subkeys to expire 10 minutes after their (not the
5253 /// new binding signature's) creation time.
5254 ///
5255 /// ```
5256 /// use std::time;
5257 /// use sequoia_openpgp as openpgp;
5258 /// use openpgp::cert::prelude::*;
5259 /// use openpgp::packet::prelude::*;
5260 /// use openpgp::policy::StandardPolicy;
5261 /// use openpgp::types::SignatureType;
5262 ///
5263 /// # fn main() -> openpgp::Result<()> {
5264 /// #
5265 /// let p = &StandardPolicy::new();
5266 ///
5267 /// let (cert, _) =
5268 /// CertBuilder::general_purpose(Some("alice@example.org"))
5269 /// .generate()?;
5270 /// let pk = cert.primary_key().key();
5271 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
5272 ///
5273 /// // Create the binding signatures.
5274 /// let mut sigs = Vec::new();
5275 ///
5276 /// for ka in cert.with_policy(p, None)?.keys().subkeys() {
5277 /// // This reuses any existing backsignature.
5278 /// let sig = SignatureBuilder::from(ka.binding_signature().clone())
5279 /// .set_key_expiration_time(ka.key(),
5280 /// time::SystemTime::now()
5281 /// + time::Duration::new(10 * 60, 0))?
5282 /// .sign_subkey_binding(&mut signer, None, ka.key())?;
5283 /// sigs.push(sig);
5284 /// }
5285 ///
5286 /// let cert = cert.insert_packets(sigs)?.0;
5287 /// # assert_eq!(cert.bad_signatures().count(), 0);
5288 /// #
5289 /// # // "Before"
5290 /// # for key in cert.with_policy(p, None)?.keys().subkeys() {
5291 /// # assert_eq!(key.bundle().self_signatures().count(), 2);
5292 /// # assert!(key.alive().is_ok());
5293 /// # }
5294 /// #
5295 /// # // "After"
5296 /// # for key in cert.with_policy(p, time::SystemTime::now()
5297 /// # + time::Duration::new(20 * 60, 0))?
5298 /// # .keys().subkeys()
5299 /// # {
5300 /// # assert!(key.alive().is_err());
5301 /// # }
5302 /// # Ok(()) }
5303 /// ```
5304 pub fn set_key_expiration_time<P, R, E>(
5305 self,
5306 key: &Key<P, R>,
5307 expiration: E)
5308 -> Result<Self>
5309 where P: key::KeyParts,
5310 R: key::KeyRole,
5311 E: Into<Option<time::SystemTime>>,
5312 {
5313 if let Some(e) = expiration.into()
5314 .map(crate::types::normalize_systemtime)
5315 {
5316 let ct = key.creation_time();
5317 let vp = match e.duration_since(ct) {
5318 Ok(v) => v,
5319 Err(_) => return Err(Error::InvalidArgument(
5320 format!("Expiration time {:?} predates creation time \
5321 {:?}", e, ct)).into()),
5322 };
5323
5324 self.set_key_validity_period(Some(vp))
5325 } else {
5326 self.set_key_validity_period(None)
5327 }
5328 }
5329
5330 /// Sets the Preferred Symmetric Algorithms subpacket.
5331 ///
5332 /// Replaces any [Preferred Symmetric Algorithms subpacket] in the
5333 /// hashed subpacket area with a new subpacket containing the
5334 /// specified value. That is, this function first removes any
5335 /// Preferred Symmetric Algorithms subpacket from the hashed
5336 /// subpacket area, and then adds a new one.
5337 ///
5338 /// A Preferred Symmetric Algorithms subpacket lists what
5339 /// symmetric algorithms the user prefers. When encrypting a
5340 /// message for a recipient, the OpenPGP implementation should not
5341 /// use an algorithm that is not on this list.
5342 ///
5343 /// [Preferred Symmetric Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.14
5344 ///
5345 /// This subpacket is a type of preference. When looking up a
5346 /// preference, an OpenPGP implementation should first look for
5347 /// the subpacket on the binding signature of the User ID or the
5348 /// User Attribute used to locate the certificate (or the primary
5349 /// User ID, if it was addressed by Key ID or fingerprint). If
5350 /// the binding signature doesn't contain the subpacket, then the
5351 /// direct key signature should be checked. See the
5352 /// [`Preferences`] trait for details.
5353 ///
5354 /// Unless addressing different User IDs really should result in
5355 /// different behavior, it is best to only set this preference on
5356 /// the direct key signature. This guarantees that even if some
5357 /// or all User IDs are stripped, the behavior remains consistent.
5358 ///
5359 /// [`Preferences`]: crate::cert::Preferences
5360 ///
5361 /// # Examples
5362 ///
5363 /// ```
5364 /// use sequoia_openpgp as openpgp;
5365 /// use openpgp::cert::prelude::*;
5366 /// use openpgp::packet::prelude::*;
5367 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5368 /// use openpgp::policy::StandardPolicy;
5369 /// use openpgp::types::SymmetricAlgorithm;
5370 ///
5371 /// # fn main() -> openpgp::Result<()> {
5372 /// let p = &StandardPolicy::new();
5373 ///
5374 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
5375 /// let mut signer = cert.primary_key().key()
5376 /// .clone().parts_into_secret()?.into_keypair()?;
5377 ///
5378 /// let vc = cert.with_policy(p, None)?;
5379 ///
5380 /// let template = vc.direct_key_signature()
5381 /// .expect("CertBuilder always includes a direct key signature");
5382 /// let sig = SignatureBuilder::from(template.clone())
5383 /// .set_preferred_symmetric_algorithms(
5384 /// vec![ SymmetricAlgorithm::AES256,
5385 /// SymmetricAlgorithm::AES128,
5386 /// ])?
5387 /// .sign_direct_key(&mut signer, None)?;
5388 /// # assert_eq!(sig
5389 /// # .hashed_area()
5390 /// # .iter()
5391 /// # .filter(|sp| sp.tag() == SubpacketTag::PreferredSymmetricAlgorithms)
5392 /// # .count(),
5393 /// # 1);
5394 ///
5395 /// // Merge in the new signature.
5396 /// let cert = cert.insert_packets(sig)?.0;
5397 /// # assert_eq!(cert.bad_signatures().count(), 0);
5398 /// # Ok(()) }
5399 /// ```
5400 pub fn set_preferred_symmetric_algorithms(mut self,
5401 preferences: Vec<SymmetricAlgorithm>)
5402 -> Result<Self> {
5403 self.hashed_area.replace(Subpacket::new(
5404 SubpacketValue::PreferredSymmetricAlgorithms(preferences),
5405 false)?)?;
5406
5407 Ok(self)
5408 }
5409
5410 /// Sets the Revocation Key subpacket.
5411 ///
5412 /// Replaces any [Revocation Key subpacket] in the hashed
5413 /// subpacket area with one new subpacket for each of the
5414 /// specified values. That is, unlike
5415 /// [`super::SignatureBuilder::add_revocation_key`], this function
5416 /// first removes any Revocation Key subpackets from the hashed
5417 /// subpacket area, and then adds new ones.
5418 ///
5419 /// [Revocation Key subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
5420 ///
5421 /// A Revocation Key subpacket indicates certificates (so-called
5422 /// designated revokers) that are allowed to revoke the signer's
5423 /// certificate. For instance, if Alice trusts Bob, she can set
5424 /// him as a designated revoker. This is useful if Alice loses
5425 /// access to her key, and therefore is unable to generate a
5426 /// revocation certificate on her own. In this case, she can
5427 /// still Bob to generate one on her behalf.
5428 ///
5429 /// Due to the complexity of verifying such signatures, many
5430 /// OpenPGP implementations do not support this feature.
5431 ///
5432 /// # Examples
5433 ///
5434 /// ```
5435 /// use sequoia_openpgp as openpgp;
5436 /// use openpgp::cert::prelude::*;
5437 /// use openpgp::packet::prelude::*;
5438 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5439 /// use openpgp::policy::StandardPolicy;
5440 /// use openpgp::types::RevocationKey;
5441 ///
5442 /// # fn main() -> openpgp::Result<()> {
5443 /// let p = &StandardPolicy::new();
5444 ///
5445 /// let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
5446 /// let mut alices_signer = alice.primary_key().key()
5447 /// .clone().parts_into_secret()?.into_keypair()?;
5448 ///
5449 /// let (bob, _) = CertBuilder::new().add_userid("Bob").generate()?;
5450 ///
5451 /// let template = alice.with_policy(p, None)?.direct_key_signature()
5452 /// .expect("CertBuilder always includes a direct key signature");
5453 /// let sig = SignatureBuilder::from(template.clone())
5454 /// // Replace any revocation keys inherited from template.
5455 /// .set_revocation_key(
5456 /// RevocationKey::new(bob.primary_key().key().pk_algo(), bob.fingerprint(), false),
5457 /// )?
5458 /// .sign_direct_key(&mut alices_signer, None)?;
5459 /// # assert_eq!(sig
5460 /// # .hashed_area()
5461 /// # .iter()
5462 /// # .filter(|sp| sp.tag() == SubpacketTag::RevocationKey)
5463 /// # .count(),
5464 /// # 1);
5465 ///
5466 /// // Merge in the new signature.
5467 /// let alice = alice.insert_packets(sig)?.0;
5468 /// # assert_eq!(alice.bad_signatures().count(), 0);
5469 /// # assert_eq!(alice.primary_key().self_signatures().count(), 2);
5470 /// # Ok(()) }
5471 /// ```
5472 pub fn set_revocation_key(mut self, rk: RevocationKey) -> Result<Self> {
5473 self.hashed_area.remove_all(SubpacketTag::RevocationKey);
5474 self.add_revocation_key(rk)
5475 }
5476
5477 /// Adds a Revocation Key subpacket.
5478 ///
5479 /// Adds a [Revocation Key subpacket] to the hashed subpacket
5480 /// area. Unlike [`super::SignatureBuilder::set_revocation_key`],
5481 /// this function does not first remove any Revocation Key
5482 /// subpackets from the hashed subpacket area.
5483 ///
5484 /// [Revocation Key subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
5485 ///
5486 /// A Revocation Key subpacket indicates certificates (so-called
5487 /// designated revokers) that are allowed to revoke the signer's
5488 /// certificate. For instance, if Alice trusts Bob, she can set
5489 /// him as a designated revoker. This is useful if Alice loses
5490 /// access to her key, and therefore is unable to generate a
5491 /// revocation certificate on her own. In this case, she can
5492 /// still Bob to generate one on her behalf.
5493 ///
5494 /// Due to the complexity of verifying such signatures, many
5495 /// OpenPGP implementations do not support this feature.
5496 ///
5497 /// # Examples
5498 ///
5499 /// ```
5500 /// use sequoia_openpgp as openpgp;
5501 /// use openpgp::cert::prelude::*;
5502 /// use openpgp::packet::prelude::*;
5503 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5504 /// use openpgp::policy::StandardPolicy;
5505 /// use openpgp::types::RevocationKey;
5506 ///
5507 /// # fn main() -> openpgp::Result<()> {
5508 /// let p = &StandardPolicy::new();
5509 ///
5510 /// let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
5511 /// let mut alices_signer = alice.primary_key().key()
5512 /// .clone().parts_into_secret()?.into_keypair()?;
5513 ///
5514 /// let (bob, _) = CertBuilder::new().add_userid("Bob").generate()?;
5515 ///
5516 /// let template = alice.with_policy(p, None)?.direct_key_signature()
5517 /// .expect("CertBuilder always includes a direct key signature");
5518 /// let sig = SignatureBuilder::from(template.clone())
5519 /// // Add to any revocation keys inherited from template.
5520 /// .add_revocation_key(
5521 /// RevocationKey::new(bob.primary_key().key().pk_algo(), bob.fingerprint(), false),
5522 /// )?
5523 /// .sign_direct_key(&mut alices_signer, None)?;
5524 /// # assert_eq!(sig
5525 /// # .hashed_area()
5526 /// # .iter()
5527 /// # .filter(|sp| sp.tag() == SubpacketTag::RevocationKey)
5528 /// # .count(),
5529 /// # 1);
5530 ///
5531 /// // Merge in the new signature.
5532 /// let alice = alice.insert_packets(sig)?.0;
5533 /// # assert_eq!(alice.bad_signatures().count(), 0);
5534 /// # assert_eq!(alice.primary_key().self_signatures().count(), 2);
5535 /// # Ok(()) }
5536 /// ```
5537 pub fn add_revocation_key(mut self, rk: RevocationKey) -> Result<Self> {
5538 self.hashed_area.add(Subpacket::new(
5539 SubpacketValue::RevocationKey(rk),
5540 true)?)?;
5541
5542 Ok(self)
5543 }
5544
5545 /// Sets the Issuer subpacket.
5546 ///
5547 /// Adds an [Issuer subpacket] to the hashed subpacket area.
5548 /// Unlike [`add_issuer`], this function first removes any
5549 /// existing Issuer subpackets from the hashed and unhashed
5550 /// subpacket area.
5551 ///
5552 /// [Issuer subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
5553 /// [`add_issuer`]: super::SignatureBuilder::add_issuer()
5554 ///
5555 /// The Issuer subpacket is used when processing a signature to
5556 /// identify which certificate created the signature. Even though this
5557 /// information is self-authenticating (the act of validating the
5558 /// signature authenticates the subpacket), it is stored in the
5559 /// hashed subpacket area. This has the advantage that the signer
5560 /// authenticates the set of issuers. Furthermore, it makes
5561 /// handling of the resulting signatures more robust: If there are
5562 /// two signatures that are equal modulo the contents of the
5563 /// unhashed area, there is the question of how to merge the
5564 /// information in the unhashed areas. Storing issuer information
5565 /// in the hashed area avoids this problem.
5566 ///
5567 /// When creating a signature using a SignatureBuilder or the
5568 /// [streaming `Signer`], it is not necessary to explicitly set
5569 /// this subpacket: those functions automatically set both the
5570 /// [Issuer Fingerprint subpacket] (set using
5571 /// [`SignatureBuilder::set_issuer_fingerprint`]) and the Issuer
5572 /// subpacket, if they have not been set explicitly.
5573 ///
5574 /// [streaming `Signer`]: crate::serialize::stream::Signer
5575 /// [Issuer Fingerprint subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
5576 /// [`SignatureBuilder::set_issuer_fingerprint`]: super::SignatureBuilder::set_issuer_fingerprint()
5577 ///
5578 /// # Examples
5579 ///
5580 /// It is possible to use the same key material with different
5581 /// OpenPGP keys. This is useful when the OpenPGP format is
5582 /// upgraded, but not all deployed implementations support the new
5583 /// format. Here, Alice signs a message, and adds the fingerprint
5584 /// of her v4 key and her v5 key indicating that the recipient can
5585 /// use either key to verify the message:
5586 ///
5587 /// ```
5588 /// use sequoia_openpgp as openpgp;
5589 /// # use openpgp::cert::prelude::*;
5590 /// use openpgp::packet::prelude::*;
5591 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5592 /// use openpgp::types::SignatureType;
5593 ///
5594 /// # fn main() -> openpgp::Result<()> {
5595 /// #
5596 /// # let (alicev4, _) =
5597 /// # CertBuilder::general_purpose(Some("alice@example.org"))
5598 /// # .generate()?;
5599 /// # let mut alices_signer = alicev4.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
5600 /// # let (alicev5, _) =
5601 /// # CertBuilder::general_purpose(Some("alice@example.org"))
5602 /// # .generate()?;
5603 /// #
5604 /// let msg = b"Hi!";
5605 ///
5606 /// let sig = SignatureBuilder::new(SignatureType::Binary)
5607 /// .set_issuer(alicev4.keyid())?
5608 /// .add_issuer(alicev5.keyid())?
5609 /// .sign_message(&mut alices_signer, msg)?;
5610 /// # let mut sig = sig;
5611 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
5612 /// # assert_eq!(sig
5613 /// # .hashed_area()
5614 /// # .iter()
5615 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
5616 /// # .count(),
5617 /// # 2);
5618 /// # assert_eq!(sig
5619 /// # .hashed_area()
5620 /// # .iter()
5621 /// # .filter(|sp| sp.tag() == SubpacketTag::IssuerFingerprint)
5622 /// # .count(),
5623 /// # 0);
5624 /// # Ok(()) }
5625 /// ```
5626 pub fn set_issuer(mut self, id: KeyID) -> Result<Self> {
5627 self.hashed_area.replace(Subpacket::new(
5628 SubpacketValue::Issuer(id),
5629 false)?)?;
5630 self.unhashed_area.remove_all(SubpacketTag::Issuer);
5631
5632 Ok(self)
5633 }
5634
5635 /// Adds an Issuer subpacket.
5636 ///
5637 /// Adds an [Issuer subpacket] to the hashed subpacket area.
5638 /// Unlike [`set_issuer`], this function does not first remove any
5639 /// existing Issuer subpacket from neither the hashed nor the
5640 /// unhashed subpacket area.
5641 ///
5642 /// [Issuer subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
5643 /// [`set_issuer`]: super::SignatureBuilder::set_issuer()
5644 ///
5645 /// The Issuer subpacket is used when processing a signature to
5646 /// identify which certificate created the signature. Even though this
5647 /// information is self-authenticating (the act of validating the
5648 /// signature authenticates the subpacket), it is stored in the
5649 /// hashed subpacket area. This has the advantage that the signer
5650 /// authenticates the set of issuers. Furthermore, it makes
5651 /// handling of the resulting signatures more robust: If there are
5652 /// two signatures that are equal modulo the contents of the
5653 /// unhashed area, there is the question of how to merge the
5654 /// information in the unhashed areas. Storing issuer information
5655 /// in the hashed area avoids this problem.
5656 ///
5657 /// When creating a signature using a SignatureBuilder or the
5658 /// [streaming `Signer`], it is not necessary to explicitly set
5659 /// this subpacket: those functions automatically set both the
5660 /// [Issuer Fingerprint subpacket] (set using
5661 /// [`SignatureBuilder::set_issuer_fingerprint`]) and the Issuer
5662 /// subpacket, if they have not been set explicitly.
5663 ///
5664 /// [streaming `Signer`]: crate::serialize::stream::Signer
5665 /// [Issuer Fingerprint subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
5666 /// [`SignatureBuilder::set_issuer_fingerprint`]: super::SignatureBuilder::set_issuer_fingerprint()
5667 ///
5668 /// # Examples
5669 ///
5670 /// It is possible to use the same key material with different
5671 /// OpenPGP keys. This is useful when the OpenPGP format is
5672 /// upgraded, but not all deployed implementations support the new
5673 /// format. Here, Alice signs a message, and adds the fingerprint
5674 /// of her v4 key and her v5 key indicating that the recipient can
5675 /// use either key to verify the message:
5676 ///
5677 /// ```
5678 /// use sequoia_openpgp as openpgp;
5679 /// # use openpgp::cert::prelude::*;
5680 /// use openpgp::packet::prelude::*;
5681 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5682 /// use openpgp::types::SignatureType;
5683 ///
5684 /// # fn main() -> openpgp::Result<()> {
5685 /// #
5686 /// # let (alicev4, _) =
5687 /// # CertBuilder::general_purpose(Some("alice@example.org"))
5688 /// # .generate()?;
5689 /// # let mut alices_signer = alicev4.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
5690 /// # let (alicev5, _) =
5691 /// # CertBuilder::general_purpose(Some("alice@example.org"))
5692 /// # .generate()?;
5693 /// #
5694 /// let msg = b"Hi!";
5695 ///
5696 /// let sig = SignatureBuilder::new(SignatureType::Binary)
5697 /// .set_issuer(alicev4.keyid())?
5698 /// .add_issuer(alicev5.keyid())?
5699 /// .sign_message(&mut alices_signer, msg)?;
5700 /// # let mut sig = sig;
5701 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
5702 /// # assert_eq!(sig
5703 /// # .hashed_area()
5704 /// # .iter()
5705 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
5706 /// # .count(),
5707 /// # 2);
5708 /// # assert_eq!(sig
5709 /// # .hashed_area()
5710 /// # .iter()
5711 /// # .filter(|sp| sp.tag() == SubpacketTag::IssuerFingerprint)
5712 /// # .count(),
5713 /// # 0);
5714 /// # Ok(()) }
5715 /// ```
5716 pub fn add_issuer(mut self, id: KeyID) -> Result<Self> {
5717 self.hashed_area.add(Subpacket::new(
5718 SubpacketValue::Issuer(id),
5719 false)?)?;
5720
5721 Ok(self)
5722 }
5723
5724 /// Sets a Notation Data subpacket.
5725 ///
5726 /// Adds a [Notation Data subpacket] to the hashed subpacket area.
5727 /// Unlike the [`SignatureBuilder::add_notation`] method, this
5728 /// function first removes any existing Notation Data subpacket
5729 /// with the specified name from the hashed subpacket area.
5730 ///
5731 /// [Notation Data subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
5732 /// [`SignatureBuilder::add_notation`]: super::SignatureBuilder::add_notation()
5733 ///
5734 /// Notations are key-value pairs. They can be used by
5735 /// applications to annotate signatures in a structured way. For
5736 /// instance, they can define additional, application-specific
5737 /// security requirements. Because they are functionally
5738 /// equivalent to subpackets, they can also be used for OpenPGP
5739 /// extensions. This is how the [Intended Recipient subpacket]
5740 /// started life.
5741 ///
5742 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
5743 ///
5744 /// Notation names are structured, and are divided into two
5745 /// namespaces: the user namespace and the IETF namespace. Names
5746 /// in the user namespace have the form `name@example.org` and
5747 /// their meaning is defined by the owner of the domain. The
5748 /// meaning of the notation `name@example.org`, for instance, is
5749 /// defined by whoever controls `example.org`. Names in the IETF
5750 /// namespace do not contain an `@` and are managed by IANA. See
5751 /// [Section 5.2.3.24 of RFC 9580] for details.
5752 ///
5753 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
5754 ///
5755 /// # Examples
5756 ///
5757 /// Adds two [social proofs] to a certificate's primary User ID.
5758 /// This first clears any social proofs.
5759 ///
5760 /// [social proofs]: https://metacode.biz/openpgp/proofs
5761 ///
5762 /// ```
5763 /// use sequoia_openpgp as openpgp;
5764 /// use openpgp::cert::prelude::*;
5765 /// use openpgp::packet::prelude::*;
5766 /// use openpgp::packet::signature::subpacket::NotationDataFlags;
5767 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5768 /// use openpgp::policy::StandardPolicy;
5769 ///
5770 /// # fn main() -> openpgp::Result<()> {
5771 /// let p = &StandardPolicy::new();
5772 ///
5773 /// let (cert, _) = CertBuilder::new().add_userid("Wiktor").generate()?;
5774 /// let mut signer = cert.primary_key().key()
5775 /// .clone().parts_into_secret()?.into_keypair()?;
5776 ///
5777 /// let vc = cert.with_policy(p, None)?;
5778 /// let ua = vc.primary_userid().expect("Added a User ID");
5779 ///
5780 /// let template = ua.binding_signature();
5781 /// let sig = SignatureBuilder::from(template.clone())
5782 /// .set_notation("proof@metacode.biz", "https://metacode.biz/@wiktor",
5783 /// NotationDataFlags::empty().set_human_readable(), false)?
5784 /// .add_notation("proof@metacode.biz", "https://news.ycombinator.com/user?id=wiktor-k",
5785 /// NotationDataFlags::empty().set_human_readable(), false)?
5786 /// .sign_userid_binding(&mut signer, None, ua.userid())?;
5787 /// # assert_eq!(sig
5788 /// # .hashed_area()
5789 /// # .iter()
5790 /// # .filter(|sp| sp.tag() == SubpacketTag::NotationData)
5791 /// # .count(),
5792 /// # 3);
5793 ///
5794 /// // Merge in the new signature.
5795 /// let cert = cert.insert_packets(sig)?.0;
5796 /// # assert_eq!(cert.bad_signatures().count(), 0);
5797 /// # Ok(()) }
5798 /// ```
5799 pub fn set_notation<N, V, F>(mut self, name: N, value: V, flags: F,
5800 critical: bool)
5801 -> Result<Self>
5802 where N: AsRef<str>,
5803 V: AsRef<[u8]>,
5804 F: Into<Option<NotationDataFlags>>,
5805 {
5806 self.hashed_area.packets.retain(|s| {
5807 ! matches!(
5808 s.value,
5809 SubpacketValue::NotationData(ref v) if v.name == name.as_ref())
5810 });
5811 self.add_notation(name.as_ref(), value.as_ref(),
5812 flags.into().unwrap_or_else(NotationDataFlags::empty),
5813 critical)
5814 }
5815
5816 /// Adds a Notation Data subpacket.
5817 ///
5818 /// Adds a [Notation Data subpacket] to the hashed subpacket area.
5819 /// Unlike the [`SignatureBuilder::set_notation`] method, this
5820 /// function does not first remove any existing Notation Data
5821 /// subpacket with the specified name from the hashed subpacket
5822 /// area.
5823 ///
5824 /// [Notation Data subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
5825 /// [`SignatureBuilder::set_notation`]: super::SignatureBuilder::set_notation()
5826 ///
5827 /// Notations are key-value pairs. They can be used by
5828 /// applications to annotate signatures in a structured way. For
5829 /// instance, they can define additional, application-specific
5830 /// security requirements. Because they are functionally
5831 /// equivalent to subpackets, they can also be used for OpenPGP
5832 /// extensions. This is how the [Intended Recipient subpacket]
5833 /// started life.
5834 ///
5835 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
5836 ///
5837 /// Notation names are structured, and are divided into two
5838 /// namespaces: the user namespace and the IETF namespace. Names
5839 /// in the user namespace have the form `name@example.org` and
5840 /// their meaning is defined by the owner of the domain. The
5841 /// meaning of the notation `name@example.org`, for instance, is
5842 /// defined by whoever controls `example.org`. Names in the IETF
5843 /// namespace do not contain an `@` and are managed by IANA. See
5844 /// [Section 5.2.3.24 of RFC 9580] for details.
5845 ///
5846 /// [Section 5.2.3.24 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.24
5847 ///
5848 /// # Examples
5849 ///
5850 /// Adds two new [social proofs] to a certificate's primary User
5851 /// ID. A more sophisticated program will check that the new
5852 /// notations aren't already present.
5853 ///
5854 /// [social proofs]: https://metacode.biz/openpgp/proofs
5855 ///
5856 /// ```
5857 /// use sequoia_openpgp as openpgp;
5858 /// use openpgp::cert::prelude::*;
5859 /// use openpgp::packet::prelude::*;
5860 /// use openpgp::packet::signature::subpacket::NotationDataFlags;
5861 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5862 /// use openpgp::policy::StandardPolicy;
5863 ///
5864 /// # fn main() -> openpgp::Result<()> {
5865 /// let p = &StandardPolicy::new();
5866 ///
5867 /// let (cert, _) = CertBuilder::new().add_userid("Wiktor").generate()?;
5868 /// let mut signer = cert.primary_key().key()
5869 /// .clone().parts_into_secret()?.into_keypair()?;
5870 ///
5871 /// let vc = cert.with_policy(p, None)?;
5872 /// let ua = vc.primary_userid().expect("Added a User ID");
5873 ///
5874 /// let template = ua.binding_signature();
5875 /// let sig = SignatureBuilder::from(template.clone())
5876 /// .add_notation("proof@metacode.biz", "https://metacode.biz/@wiktor",
5877 /// NotationDataFlags::empty().set_human_readable(), false)?
5878 /// .add_notation("proof@metacode.biz", "https://news.ycombinator.com/user?id=wiktor-k",
5879 /// NotationDataFlags::empty().set_human_readable(), false)?
5880 /// .sign_userid_binding(&mut signer, None, ua.userid())?;
5881 /// # assert_eq!(sig
5882 /// # .hashed_area()
5883 /// # .iter()
5884 /// # .filter(|sp| sp.tag() == SubpacketTag::NotationData)
5885 /// # .count(),
5886 /// # 3);
5887 ///
5888 /// // Merge in the new signature.
5889 /// let cert = cert.insert_packets(sig)?.0;
5890 /// # assert_eq!(cert.bad_signatures().count(), 0);
5891 /// # Ok(()) }
5892 /// ```
5893 pub fn add_notation<N, V, F>(mut self, name: N, value: V, flags: F,
5894 critical: bool)
5895 -> Result<Self>
5896 where N: AsRef<str>,
5897 V: AsRef<[u8]>,
5898 F: Into<Option<NotationDataFlags>>,
5899 {
5900 self.hashed_area.add(Subpacket::new(SubpacketValue::NotationData(
5901 NotationData::new(name.as_ref(), value.as_ref(),
5902 flags.into().unwrap_or_else(NotationDataFlags::empty))),
5903 critical)?)?;
5904 Ok(self)
5905 }
5906
5907 /// Sets the Preferred Hash Algorithms subpacket.
5908 ///
5909 /// Replaces any [Preferred Hash Algorithms subpacket] in the
5910 /// hashed subpacket area with a new subpacket containing the
5911 /// specified value. That is, this function first removes any
5912 /// Preferred Hash Algorithms subpacket from the hashed subpacket
5913 /// area, and then adds a new one.
5914 ///
5915 /// A Preferred Hash Algorithms subpacket lists what hash
5916 /// algorithms the user prefers. When signing a message that
5917 /// should be verified by a particular recipient, the OpenPGP
5918 /// implementation should not use an algorithm that is not on this
5919 /// list.
5920 ///
5921 /// [Preferred Hash Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.16
5922 ///
5923 /// This subpacket is a type of preference. When looking up a
5924 /// preference, an OpenPGP implementation should first look for
5925 /// the subpacket on the binding signature of the User ID or the
5926 /// User Attribute used to locate the certificate (or the primary
5927 /// User ID, if it was addressed by Key ID or fingerprint). If
5928 /// the binding signature doesn't contain the subpacket, then the
5929 /// direct key signature should be checked. See the
5930 /// [`Preferences`] trait for details.
5931 ///
5932 /// Unless addressing different User IDs really should result in
5933 /// different behavior, it is best to only set this preference on
5934 /// the direct key signature. This guarantees that even if some
5935 /// or all User IDs are stripped, the behavior remains consistent.
5936 ///
5937 /// [`Preferences`]: crate::cert::Preferences
5938 ///
5939 /// # Examples
5940 ///
5941 /// ```
5942 /// use sequoia_openpgp as openpgp;
5943 /// use openpgp::cert::prelude::*;
5944 /// use openpgp::packet::prelude::*;
5945 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
5946 /// use openpgp::policy::StandardPolicy;
5947 /// use openpgp::types::HashAlgorithm;
5948 ///
5949 /// # fn main() -> openpgp::Result<()> {
5950 /// let p = &StandardPolicy::new();
5951 ///
5952 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
5953 /// let mut signer = cert.primary_key().key()
5954 /// .clone().parts_into_secret()?.into_keypair()?;
5955 ///
5956 /// let vc = cert.with_policy(p, None)?;
5957 ///
5958 /// let template = vc.direct_key_signature()
5959 /// .expect("CertBuilder always includes a direct key signature");
5960 /// let sig = SignatureBuilder::from(template.clone())
5961 /// .set_preferred_hash_algorithms(
5962 /// vec![ HashAlgorithm::SHA512,
5963 /// HashAlgorithm::SHA256,
5964 /// ])?
5965 /// .sign_direct_key(&mut signer, None)?;
5966 /// # assert_eq!(sig
5967 /// # .hashed_area()
5968 /// # .iter()
5969 /// # .filter(|sp| sp.tag() == SubpacketTag::PreferredHashAlgorithms)
5970 /// # .count(),
5971 /// # 1);
5972 ///
5973 /// // Merge in the new signature.
5974 /// let cert = cert.insert_packets(sig)?.0;
5975 /// # assert_eq!(cert.bad_signatures().count(), 0);
5976 /// # Ok(()) }
5977 /// ```
5978 pub fn set_preferred_hash_algorithms(mut self,
5979 preferences: Vec<HashAlgorithm>)
5980 -> Result<Self> {
5981 self.hashed_area.replace(Subpacket::new(
5982 SubpacketValue::PreferredHashAlgorithms(preferences),
5983 false)?)?;
5984
5985 Ok(self)
5986 }
5987
5988 /// Sets the Preferred Compression Algorithms subpacket.
5989 ///
5990 /// Replaces any [Preferred Compression Algorithms subpacket] in
5991 /// the hashed subpacket area with a new subpacket containing the
5992 /// specified value. That is, this function first removes any
5993 /// Preferred Compression Algorithms subpacket from the hashed
5994 /// subpacket area, and then adds a new one.
5995 ///
5996 /// A Preferred Compression Algorithms subpacket lists what
5997 /// compression algorithms the user prefers. When compressing a
5998 /// message for a recipient, the OpenPGP implementation should not
5999 /// use an algorithm that is not on the list.
6000 ///
6001 /// [Preferred Compression Algorithms subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.17
6002 ///
6003 /// This subpacket is a type of preference. When looking up a
6004 /// preference, an OpenPGP implementation should first look for
6005 /// the subpacket on the binding signature of the User ID or the
6006 /// User Attribute used to locate the certificate (or the primary
6007 /// User ID, if it was addressed by Key ID or fingerprint). If
6008 /// the binding signature doesn't contain the subpacket, then the
6009 /// direct key signature should be checked. See the
6010 /// [`Preferences`] trait for details.
6011 ///
6012 /// Unless addressing different User IDs really should result in
6013 /// different behavior, it is best to only set this preference on
6014 /// the direct key signature. This guarantees that even if some
6015 /// or all User IDs are stripped, the behavior remains consistent.
6016 ///
6017 /// [`Preferences`]: crate::cert::Preferences
6018 ///
6019 /// # Examples
6020 ///
6021 /// ```
6022 /// use sequoia_openpgp as openpgp;
6023 /// use openpgp::cert::prelude::*;
6024 /// use openpgp::packet::prelude::*;
6025 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6026 /// use openpgp::policy::StandardPolicy;
6027 /// use openpgp::types::CompressionAlgorithm;
6028 ///
6029 /// # fn main() -> openpgp::Result<()> {
6030 /// let p = &StandardPolicy::new();
6031 ///
6032 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
6033 /// let mut signer = cert.primary_key().key()
6034 /// .clone().parts_into_secret()?.into_keypair()?;
6035 ///
6036 /// let vc = cert.with_policy(p, None)?;
6037 ///
6038 /// let template = vc.direct_key_signature()
6039 /// .expect("CertBuilder always includes a direct key signature");
6040 /// let sig = SignatureBuilder::from(template.clone())
6041 /// .set_preferred_compression_algorithms(
6042 /// vec![ CompressionAlgorithm::Zlib,
6043 /// CompressionAlgorithm::Zip,
6044 /// CompressionAlgorithm::BZip2,
6045 /// ])?
6046 /// .sign_direct_key(&mut signer, None)?;
6047 /// # assert_eq!(sig
6048 /// # .hashed_area()
6049 /// # .iter()
6050 /// # .filter(|sp| sp.tag() == SubpacketTag::PreferredCompressionAlgorithms)
6051 /// # .count(),
6052 /// # 1);
6053 ///
6054 /// // Merge in the new signature.
6055 /// let cert = cert.insert_packets(sig)?.0;
6056 /// # assert_eq!(cert.bad_signatures().count(), 0);
6057 /// # Ok(()) }
6058 /// ```
6059 pub fn set_preferred_compression_algorithms(mut self,
6060 preferences: Vec<CompressionAlgorithm>)
6061 -> Result<Self> {
6062 self.hashed_area.replace(Subpacket::new(
6063 SubpacketValue::PreferredCompressionAlgorithms(preferences),
6064 false)?)?;
6065
6066 Ok(self)
6067 }
6068
6069 /// Sets the Key Server Preferences subpacket.
6070 ///
6071 /// Replaces any [Key Server Preferences subpacket] in the hashed
6072 /// subpacket area with a new subpacket containing the specified
6073 /// value. That is, this function first removes any Key Server
6074 /// Preferences subpacket from the hashed subpacket area, and then
6075 /// adds a new one.
6076 ///
6077 /// The Key Server Preferences subpacket indicates to key servers
6078 /// how they should handle the certificate.
6079 ///
6080 /// [Key Server Preferences subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.25
6081 ///
6082 /// This subpacket is a type of preference. When looking up a
6083 /// preference, an OpenPGP implementation should first look for
6084 /// the subpacket on the binding signature of the User ID or the
6085 /// User Attribute used to locate the certificate (or the primary
6086 /// User ID, if it was addressed by Key ID or fingerprint). If
6087 /// the binding signature doesn't contain the subpacket, then the
6088 /// direct key signature should be checked. See the
6089 /// [`Preferences`] trait for details.
6090 ///
6091 /// Unless addressing different User IDs really should result in
6092 /// different behavior, it is best to only set this preference on
6093 /// the direct key signature. This guarantees that even if some
6094 /// or all User IDs are stripped, the behavior remains consistent.
6095 ///
6096 /// [`Preferences`]: crate::cert::Preferences
6097 ///
6098 /// # Examples
6099 ///
6100 /// ```
6101 /// use sequoia_openpgp as openpgp;
6102 /// use openpgp::cert::prelude::*;
6103 /// use openpgp::packet::prelude::*;
6104 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6105 /// use openpgp::policy::StandardPolicy;
6106 /// use openpgp::types::KeyServerPreferences;
6107 ///
6108 /// # fn main() -> openpgp::Result<()> {
6109 /// let p = &StandardPolicy::new();
6110 ///
6111 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
6112 /// let mut signer = cert.primary_key().key()
6113 /// .clone().parts_into_secret()?.into_keypair()?;
6114 ///
6115 /// let vc = cert.with_policy(p, None)?;
6116 ///
6117 /// let sig = vc.direct_key_signature()
6118 /// .expect("CertBuilder always includes a direct key signature");
6119 /// let sig =
6120 /// SignatureBuilder::from(sig.clone())
6121 /// .set_key_server_preferences(
6122 /// KeyServerPreferences::empty().set_no_modify())?
6123 /// .sign_direct_key(&mut signer, None)?;
6124 /// # assert_eq!(sig
6125 /// # .hashed_area()
6126 /// # .iter()
6127 /// # .filter(|sp| sp.tag() == SubpacketTag::KeyServerPreferences)
6128 /// # .count(),
6129 /// # 1);
6130 ///
6131 /// // Merge in the new signature.
6132 /// let cert = cert.insert_packets(sig)?.0;
6133 /// # assert_eq!(cert.bad_signatures().count(), 0);
6134 /// # Ok(()) }
6135 /// ```
6136 pub fn set_key_server_preferences(mut self,
6137 preferences: KeyServerPreferences)
6138 -> Result<Self> {
6139 self.hashed_area.replace(Subpacket::new(
6140 SubpacketValue::KeyServerPreferences(preferences),
6141 false)?)?;
6142
6143 Ok(self)
6144 }
6145
6146 /// Sets the Preferred Key Server subpacket.
6147 ///
6148 /// Adds a [Preferred Key Server subpacket] to the hashed
6149 /// subpacket area. This function first removes any Preferred Key
6150 /// Server subpacket from the hashed subpacket area.
6151 ///
6152 /// [Preferred Key Server subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.26
6153 ///
6154 /// The Preferred Key Server subpacket contains a link to a key
6155 /// server where the certificate holder plans to publish updates
6156 /// to their certificate (e.g., extensions to the expiration time,
6157 /// new subkeys, revocation certificates).
6158 ///
6159 /// The Preferred Key Server subpacket should be handled
6160 /// cautiously, because it can be used by a certificate holder to
6161 /// track communication partners.
6162 ///
6163 /// This subpacket is a type of preference. When looking up a
6164 /// preference, an OpenPGP implementation should first look for
6165 /// the subpacket on the binding signature of the User ID or the
6166 /// User Attribute used to locate the certificate (or the primary
6167 /// User ID, if it was addressed by Key ID or fingerprint). If
6168 /// the binding signature doesn't contain the subpacket, then the
6169 /// direct key signature should be checked. See the
6170 /// [`Preferences`] trait for details.
6171 ///
6172 /// Unless addressing different User IDs really should result in
6173 /// different behavior, it is best to only set this preference on
6174 /// the direct key signature. This guarantees that even if some
6175 /// or all User IDs are stripped, the behavior remains consistent.
6176 ///
6177 /// [`Preferences`]: crate::cert::Preferences
6178 ///
6179 /// # Examples
6180 ///
6181 /// ```
6182 /// use sequoia_openpgp as openpgp;
6183 /// use openpgp::cert::prelude::*;
6184 /// use openpgp::packet::prelude::*;
6185 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6186 /// use openpgp::policy::StandardPolicy;
6187 ///
6188 /// # fn main() -> openpgp::Result<()> {
6189 /// let p = &StandardPolicy::new();
6190 ///
6191 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
6192 /// let mut signer = cert.primary_key().key()
6193 /// .clone().parts_into_secret()?.into_keypair()?;
6194 ///
6195 /// let vc = cert.with_policy(p, None)?;
6196 ///
6197 /// let sig = vc.direct_key_signature()
6198 /// .expect("CertBuilder always includes a direct key signature");
6199 /// let sig =
6200 /// SignatureBuilder::from(sig.clone())
6201 /// .set_preferred_key_server(&"https://keys.openpgp.org")?
6202 /// .sign_direct_key(&mut signer, None)?;
6203 /// # assert_eq!(sig
6204 /// # .hashed_area()
6205 /// # .iter()
6206 /// # .filter(|sp| sp.tag() == SubpacketTag::PreferredKeyServer)
6207 /// # .count(),
6208 /// # 1);
6209 ///
6210 /// // Merge in the new signature.
6211 /// let cert = cert.insert_packets(sig)?.0;
6212 /// # assert_eq!(cert.bad_signatures().count(), 0);
6213 /// # Ok(()) }
6214 /// ```
6215 pub fn set_preferred_key_server<U>(mut self, uri: U)
6216 -> Result<Self>
6217 where U: AsRef<[u8]>,
6218 {
6219 self.hashed_area.replace(Subpacket::new(
6220 SubpacketValue::PreferredKeyServer(uri.as_ref().to_vec()),
6221 false)?)?;
6222
6223 Ok(self)
6224 }
6225
6226 /// Sets the Primary User ID subpacket.
6227 ///
6228 /// Adds a [Primary User ID subpacket] to the hashed subpacket
6229 /// area. This function first removes any Primary User ID
6230 /// subpacket from the hashed subpacket area.
6231 ///
6232 /// [Primary User ID subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.27
6233 ///
6234 /// The Primary User ID subpacket indicates whether the associated
6235 /// User ID or User Attribute should be considered the primary
6236 /// User ID. It is possible that this is set on multiple User
6237 /// IDs. See the documentation for [`ValidCert::primary_userid`] for
6238 /// an explanation of how Sequoia resolves this ambiguity.
6239 ///
6240 /// [`ValidCert::primary_userid`]: crate::cert::ValidCert::primary_userid()
6241 ///
6242 /// # Examples
6243 ///
6244 /// Change the primary User ID:
6245 ///
6246 /// ```
6247 /// use sequoia_openpgp as openpgp;
6248 /// use openpgp::cert::prelude::*;
6249 /// use openpgp::packet::prelude::*;
6250 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6251 /// use openpgp::policy::StandardPolicy;
6252 ///
6253 /// # fn main() -> openpgp::Result<()> {
6254 /// let p = &StandardPolicy::new();
6255 ///
6256 /// let club = "Alice <alice@club.org>";
6257 /// let home = "Alice <alice@home.org>";
6258 ///
6259 /// // CertBuilder makes the first User ID (club) the primary User ID.
6260 /// let (cert, _) = CertBuilder::new()
6261 /// # // Create it in the past.
6262 /// # .set_creation_time(std::time::SystemTime::now()
6263 /// # - std::time::Duration::new(10, 0))
6264 /// .add_userid(club)
6265 /// .add_userid(home)
6266 /// .generate()?;
6267 /// # assert_eq!(cert.userids().count(), 2);
6268 /// assert_eq!(cert.with_policy(p, None)?.primary_userid().unwrap().userid(),
6269 /// &UserID::from(club));
6270 ///
6271 /// // Make the `home` User ID the primary User ID.
6272 ///
6273 /// // Derive a signer.
6274 /// let pk = cert.primary_key().key();
6275 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
6276 ///
6277 /// let mut sig = None;
6278 /// for ua in cert.with_policy(p, None)?.userids() {
6279 /// if ua.userid() == &UserID::from(home) {
6280 /// sig = Some(SignatureBuilder::from(ua.binding_signature().clone())
6281 /// .set_primary_userid(true)?
6282 /// .sign_userid_binding(&mut signer, pk, ua.userid())?);
6283 /// # assert_eq!(sig.as_ref().unwrap()
6284 /// # .hashed_area()
6285 /// # .iter()
6286 /// # .filter(|sp| sp.tag() == SubpacketTag::PrimaryUserID)
6287 /// # .count(),
6288 /// # 1);
6289 /// break;
6290 /// }
6291 /// }
6292 /// assert!(sig.is_some());
6293 ///
6294 /// let cert = cert.insert_packets(sig)?.0;
6295 ///
6296 /// assert_eq!(cert.with_policy(p, None)?.primary_userid().unwrap().userid(),
6297 /// &UserID::from(home));
6298 /// # Ok(())
6299 /// # }
6300 /// ```
6301 pub fn set_primary_userid(mut self, primary: bool) -> Result<Self> {
6302 self.hashed_area.replace(Subpacket::new(
6303 SubpacketValue::PrimaryUserID(primary),
6304 true)?)?;
6305
6306 Ok(self)
6307 }
6308
6309 /// Sets the Policy URI subpacket.
6310 ///
6311 /// Adds a [Policy URI subpacket] to the hashed subpacket area.
6312 /// This function first removes any Policy URI subpacket from the
6313 /// hashed subpacket area.
6314 ///
6315 /// [Policy URI subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.28
6316 ///
6317 /// The Policy URI subpacket contains a link to a policy document,
6318 /// which contains information about the conditions under which
6319 /// the signature was made.
6320 ///
6321 /// This subpacket is a type of preference. When looking up a
6322 /// preference, an OpenPGP implementation should first look for
6323 /// the subpacket on the binding signature of the User ID or the
6324 /// User Attribute used to locate the certificate (or the primary
6325 /// User ID, if it was addressed by Key ID or fingerprint). If
6326 /// the binding signature doesn't contain the subpacket, then the
6327 /// direct key signature should be checked. See the
6328 /// [`Preferences`] trait for details.
6329 ///
6330 /// Unless addressing different User IDs really should result in
6331 /// different behavior, it is best to only set this preference on
6332 /// the direct key signature. This guarantees that even if some
6333 /// or all User IDs are stripped, the behavior remains consistent.
6334 ///
6335 /// [`Preferences`]: crate::cert::Preferences
6336 ///
6337 /// # Examples
6338 ///
6339 /// Alice updates her direct key signature to include a Policy URI
6340 /// subpacket:
6341 ///
6342 /// ```
6343 /// use sequoia_openpgp as openpgp;
6344 /// use openpgp::cert::prelude::*;
6345 /// use openpgp::packet::prelude::*;
6346 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6347 /// use openpgp::policy::StandardPolicy;
6348 ///
6349 /// # fn main() -> openpgp::Result<()> {
6350 /// let p = &StandardPolicy::new();
6351 ///
6352 /// let (alice, _) = CertBuilder::new().add_userid("Alice").generate()?;
6353 /// let pk = alice.primary_key().key();
6354 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
6355 ///
6356 /// let sig = SignatureBuilder::from(
6357 /// alice
6358 /// .with_policy(p, None)?
6359 /// .direct_key_signature().expect("Direct key signature")
6360 /// .clone()
6361 /// )
6362 /// .set_policy_uri("https://example.org/~alice/signing-policy.txt")?
6363 /// .sign_direct_key(&mut signer, None)?;
6364 /// # let mut sig = sig;
6365 /// # sig.verify_direct_key(signer.public(), pk)?;
6366 /// # assert_eq!(sig
6367 /// # .hashed_area()
6368 /// # .iter()
6369 /// # .filter(|sp| sp.tag() == SubpacketTag::PolicyURI)
6370 /// # .count(),
6371 /// # 1);
6372 ///
6373 /// // Merge it into the certificate.
6374 /// let alice = alice.insert_packets(sig)?.0;
6375 /// #
6376 /// # assert_eq!(alice.bad_signatures().count(), 0);
6377 /// # Ok(())
6378 /// # }
6379 /// ```
6380 pub fn set_policy_uri<U>(mut self, uri: U) -> Result<Self>
6381 where U: AsRef<[u8]>,
6382 {
6383 self.hashed_area.replace(Subpacket::new(
6384 SubpacketValue::PolicyURI(uri.as_ref().to_vec()),
6385 false)?)?;
6386
6387 Ok(self)
6388 }
6389
6390 /// Sets the Key Flags subpacket.
6391 ///
6392 /// Adds a [Key Flags subpacket] to the hashed subpacket area.
6393 /// This function first removes any Key Flags subpacket from the
6394 /// hashed subpacket area.
6395 ///
6396 /// [Key Flags subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
6397 ///
6398 /// The Key Flags subpacket describes a key's capabilities
6399 /// (certification capable, signing capable, etc.). In the case
6400 /// of subkeys, the Key Flags are located on the subkey's binding
6401 /// signature. For primary keys, locating the correct Key Flags
6402 /// subpacket is more complex: First, the primary User ID is
6403 /// consulted. If the primary User ID contains a Key Flags
6404 /// subpacket, that is used. Otherwise, any direct key signature
6405 /// is considered. If that still doesn't contain a Key Flags
6406 /// packet, then the primary key should be assumed to be
6407 /// certification capable.
6408 ///
6409 /// # Examples
6410 ///
6411 /// Adds a new subkey, which is intended for encrypting data at
6412 /// rest, to a certificate:
6413 ///
6414 /// ```
6415 /// use sequoia_openpgp as openpgp;
6416 /// use openpgp::cert::prelude::*;
6417 /// use openpgp::packet::prelude::*;
6418 /// use openpgp::policy::StandardPolicy;
6419 /// use openpgp::types::{
6420 /// Curve,
6421 /// KeyFlags,
6422 /// SignatureType
6423 /// };
6424 ///
6425 /// # fn main() -> openpgp::Result<()> {
6426 /// let p = &StandardPolicy::new();
6427 ///
6428 /// // Generate a Cert, and create a keypair from the primary key.
6429 /// let (cert, _) = CertBuilder::new().generate()?;
6430 /// # assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
6431 /// # .key_flags(&KeyFlags::empty().set_storage_encryption()).count(),
6432 /// # 0);
6433 /// let mut signer = cert.primary_key().key().clone()
6434 /// .parts_into_secret()?.into_keypair()?;
6435 ///
6436 /// // Generate a subkey and a binding signature.
6437 /// let subkey: Key<_, key::SubordinateRole>
6438 /// = Key6::generate_ecc(false, Curve::Cv25519)?
6439 /// .into();
6440 /// let builder = signature::SignatureBuilder::new(SignatureType::SubkeyBinding)
6441 /// .set_key_flags(KeyFlags::empty().set_storage_encryption())?;
6442 /// let binding = subkey.bind(&mut signer, &cert, builder)?;
6443 ///
6444 /// // Now merge the key and binding signature into the Cert.
6445 /// let cert = cert.insert_packets(vec![Packet::from(subkey),
6446 /// binding.into()])?.0;
6447 ///
6448 /// # assert_eq!(cert.keys().with_policy(p, None).alive().revoked(false)
6449 /// # .key_flags(&KeyFlags::empty().set_storage_encryption()).count(),
6450 /// # 1);
6451 /// # Ok(()) }
6452 /// ```
6453 pub fn set_key_flags(mut self, flags: KeyFlags) -> Result<Self> {
6454 self.hashed_area.replace(Subpacket::new(
6455 SubpacketValue::KeyFlags(flags),
6456 true)?)?;
6457
6458 Ok(self)
6459 }
6460
6461 /// Sets the Signer's User ID subpacket.
6462 ///
6463 /// Adds a [Signer's User ID subpacket] to the hashed subpacket
6464 /// area. This function first removes any Signer's User ID
6465 /// subpacket from the hashed subpacket area.
6466 ///
6467 /// [Signer's User ID subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.30
6468 ///
6469 /// The Signer's User ID subpacket indicates, which User ID made
6470 /// the signature. This is useful when a key has multiple User
6471 /// IDs, which correspond to different roles. For instance, it is
6472 /// not uncommon to use the same certificate in private as well as
6473 /// for a club.
6474 ///
6475 /// # Examples
6476 ///
6477 /// Sign a message being careful to set the Signer's User ID
6478 /// subpacket to the user's private identity and not their club
6479 /// identity:
6480 ///
6481 /// ```rust
6482 /// use sequoia_openpgp as openpgp;
6483 /// use openpgp::cert::prelude::*;
6484 /// use openpgp::packet::prelude::*;
6485 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6486 /// use openpgp::types::SignatureType;
6487 ///
6488 /// # fn main() -> openpgp::Result<()> {
6489 /// let (cert, _) = CertBuilder::new()
6490 /// .add_userid("Alice <alice@home.org>")
6491 /// .add_userid("Alice (President) <alice@club.org>")
6492 /// .generate()?;
6493 /// let mut signer = cert.primary_key().key().clone()
6494 /// .parts_into_secret()?.into_keypair()?;
6495 ///
6496 /// let msg = "Speaking for myself, I agree.";
6497 ///
6498 /// let sig = SignatureBuilder::new(SignatureType::Binary)
6499 /// .set_signers_user_id(&b"Alice <alice@home.org>"[..])?
6500 /// .sign_message(&mut signer, msg)?;
6501 /// # let mut sig = sig;
6502 /// # assert!(sig.verify_message(signer.public(), msg).is_ok());
6503 /// # assert_eq!(sig
6504 /// # .hashed_area()
6505 /// # .iter()
6506 /// # .filter(|sp| sp.tag() == SubpacketTag::SignersUserID)
6507 /// # .count(),
6508 /// # 1);
6509 /// # Ok(()) }
6510 /// ```
6511 pub fn set_signers_user_id<U>(mut self, uid: U) -> Result<Self>
6512 where U: AsRef<[u8]>,
6513 {
6514 self.hashed_area.replace(Subpacket::new(
6515 SubpacketValue::SignersUserID(uid.as_ref().to_vec()),
6516 false)?)?;
6517
6518 Ok(self)
6519 }
6520
6521 /// Sets the value of the Reason for Revocation subpacket.
6522 ///
6523 /// Adds a [Reason For Revocation subpacket] to the hashed
6524 /// subpacket area. This function first removes any Reason For
6525 /// Revocation subpacket from the hashed subpacket
6526 /// area.
6527 ///
6528 /// [Reason For Revocation subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.31
6529 ///
6530 /// The Reason For Revocation subpacket indicates why a key, User
6531 /// ID, or User Attribute is being revoked. It includes both a
6532 /// machine-readable code, and a human-readable string. The code
6533 /// is essential as it indicates to the OpenPGP implementation
6534 /// that reads the certificate whether the key was compromised (a
6535 /// hard revocation), or is no longer used (a soft revocation).
6536 /// In the former case, the OpenPGP implementation must
6537 /// conservatively consider all past signatures as suspect whereas
6538 /// in the latter case, past signatures can still be considered
6539 /// valid.
6540 ///
6541 /// # Examples
6542 ///
6543 /// Revoke a certificate whose private key material has been
6544 /// compromised:
6545 ///
6546 /// ```rust
6547 /// use sequoia_openpgp as openpgp;
6548 /// use openpgp::cert::prelude::*;
6549 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6550 /// use openpgp::policy::StandardPolicy;
6551 /// use openpgp::types::ReasonForRevocation;
6552 /// use openpgp::types::RevocationStatus;
6553 ///
6554 /// # fn main() -> openpgp::Result<()> {
6555 /// let p = &StandardPolicy::new();
6556 ///
6557 /// let (cert, _) = CertBuilder::new().generate()?;
6558 /// assert_eq!(RevocationStatus::NotAsFarAsWeKnow,
6559 /// cert.revocation_status(p, None));
6560 ///
6561 /// // Create and sign a revocation certificate.
6562 /// let mut signer = cert.primary_key().key().clone()
6563 /// .parts_into_secret()?.into_keypair()?;
6564 /// let sig = CertRevocationBuilder::new()
6565 /// .set_reason_for_revocation(ReasonForRevocation::KeyCompromised,
6566 /// b"It was the maid :/")?
6567 /// .build(&mut signer, &cert, None)?;
6568 ///
6569 /// // Merge it into the certificate.
6570 /// let cert = cert.insert_packets(sig.clone())?.0;
6571 ///
6572 /// // Now it's revoked.
6573 /// assert_eq!(RevocationStatus::Revoked(vec![ &sig ]),
6574 /// cert.revocation_status(p, None));
6575 /// # assert_eq!(sig
6576 /// # .hashed_area()
6577 /// # .iter()
6578 /// # .filter(|sp| sp.tag() == SubpacketTag::ReasonForRevocation)
6579 /// # .count(),
6580 /// # 1);
6581 /// # Ok(())
6582 /// # }
6583 /// ```
6584 pub fn set_reason_for_revocation<R>(mut self, code: ReasonForRevocation,
6585 reason: R)
6586 -> Result<Self>
6587 where R: AsRef<[u8]>,
6588 {
6589 self.hashed_area.replace(Subpacket::new(
6590 SubpacketValue::ReasonForRevocation {
6591 code,
6592 reason: reason.as_ref().to_vec(),
6593 },
6594 false)?)?;
6595
6596 Ok(self)
6597 }
6598
6599 /// Sets the Features subpacket.
6600 ///
6601 /// Adds a [Feature subpacket] to the hashed subpacket area. This
6602 /// function first removes any Feature subpacket from the hashed
6603 /// subpacket area.
6604 ///
6605 /// A Feature subpacket lists what OpenPGP features the user wants
6606 /// to use. When creating a message, features that the intended
6607 /// recipients do not support should not be used. However,
6608 /// because this information is rarely held up to date in
6609 /// practice, this information is only advisory, and
6610 /// implementations are allowed to infer what features the
6611 /// recipients support from contextual clues, e.g., their past
6612 /// behavior.
6613 ///
6614 /// [Feature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.32
6615 /// [features]: crate::types::Features
6616 ///
6617 /// This subpacket is a type of preference. When looking up a
6618 /// preference, an OpenPGP implementation should first look for
6619 /// the subpacket on the binding signature of the User ID or the
6620 /// User Attribute used to locate the certificate (or the primary
6621 /// User ID, if it was addressed by Key ID or fingerprint). If
6622 /// the binding signature doesn't contain the subpacket, then the
6623 /// direct key signature should be checked. See the
6624 /// [`Preferences`] trait for details.
6625 ///
6626 /// Unless addressing different User IDs really should result in
6627 /// different behavior, it is best to only set this preference on
6628 /// the direct key signature. This guarantees that even if some
6629 /// or all User IDs are stripped, the behavior remains consistent.
6630 ///
6631 /// [`Preferences`]: crate::cert::Preferences
6632 ///
6633 /// # Examples
6634 ///
6635 /// Update a certificate's binding signatures to indicate support for AEAD:
6636 ///
6637 /// ```
6638 /// use sequoia_openpgp as openpgp;
6639 /// use openpgp::cert::prelude::*;
6640 /// use openpgp::packet::prelude::*;
6641 /// use openpgp::policy::StandardPolicy;
6642 /// use openpgp::types::{AEADAlgorithm, Features};
6643 ///
6644 /// # fn main() -> openpgp::Result<()> {
6645 /// use sequoia_openpgp::types::SymmetricAlgorithm;
6646 /// let p = &StandardPolicy::new();
6647 ///
6648 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
6649 ///
6650 /// // Derive a signer (the primary key is always certification capable).
6651 /// let pk = cert.primary_key().key();
6652 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
6653 ///
6654 /// let mut sigs = Vec::new();
6655 ///
6656 /// let vc = cert.with_policy(p, None)?;
6657 ///
6658 /// if let Ok(sig) = vc.direct_key_signature() {
6659 /// sigs.push(
6660 /// SignatureBuilder::from(sig.clone())
6661 /// .set_preferred_aead_ciphersuites(vec![(SymmetricAlgorithm::AES256, AEADAlgorithm::EAX) ])?
6662 /// .set_features(
6663 /// sig.features().unwrap_or_else(Features::sequoia)
6664 /// .set_seipdv2())?
6665 /// .sign_direct_key(&mut signer, None)?);
6666 /// }
6667 ///
6668 /// for ua in vc.userids() {
6669 /// let sig = ua.binding_signature();
6670 /// sigs.push(
6671 /// SignatureBuilder::from(sig.clone())
6672 /// .set_preferred_aead_ciphersuites(vec![(SymmetricAlgorithm::AES256, AEADAlgorithm::EAX) ])?
6673 /// .set_features(
6674 /// sig.features().unwrap_or_else(Features::sequoia)
6675 /// .set_seipdv2())?
6676 /// .sign_userid_binding(&mut signer, pk, ua.userid())?);
6677 /// }
6678 ///
6679 /// // Merge in the new signatures.
6680 /// let cert = cert.insert_packets(sigs)?.0;
6681 /// # assert_eq!(cert.bad_signatures().count(), 0);
6682 /// # Ok(())
6683 /// # }
6684 /// ```
6685 pub fn set_features(mut self, features: Features) -> Result<Self> {
6686 self.hashed_area.replace(Subpacket::new(
6687 SubpacketValue::Features(features),
6688 false)?)?;
6689
6690 Ok(self)
6691 }
6692
6693 /// Sets the Signature Target subpacket.
6694 ///
6695 /// Adds a [Signature Target subpacket] to the hashed subpacket
6696 /// area. This function first removes any Signature Target
6697 /// subpacket from the hashed subpacket area.
6698 ///
6699 /// The Signature Target subpacket is used to identify the target
6700 /// of a signature. This is used when revoking a signature, and
6701 /// by timestamp signatures. It contains a hash of the target
6702 /// signature.
6703 ///
6704 /// [Signature Target subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.33
6705 pub fn set_signature_target<D>(mut self,
6706 pk_algo: PublicKeyAlgorithm,
6707 hash_algo: HashAlgorithm,
6708 digest: D)
6709 -> Result<Self>
6710 where D: AsRef<[u8]>,
6711 {
6712 self.hashed_area.replace(Subpacket::new(
6713 SubpacketValue::SignatureTarget {
6714 pk_algo,
6715 hash_algo,
6716 digest: digest.as_ref().to_vec(),
6717 },
6718 true)?)?;
6719
6720 Ok(self)
6721 }
6722
6723 /// Sets the value of the Embedded Signature subpacket.
6724 ///
6725 /// Adds an [Embedded Signature subpacket] to the hashed
6726 /// subpacket area. This function first removes any Embedded
6727 /// Signature subpacket from both the hashed and the unhashed
6728 /// subpacket area.
6729 ///
6730 /// [Embedded Signature subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.34
6731 ///
6732 /// The Embedded Signature subpacket is normally used to hold a
6733 /// [Primary Key Binding signature], which binds a
6734 /// signing-capable, authentication-capable, or
6735 /// certification-capable subkey to the primary key. Since this
6736 /// information is self-authenticating, it is usually stored in the
6737 /// unhashed subpacket area.
6738 ///
6739 /// [Primary Key Binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
6740 ///
6741 /// # Examples
6742 ///
6743 /// Add a new signing-capable subkey to a certificate:
6744 ///
6745 /// ```
6746 /// use sequoia_openpgp as openpgp;
6747 /// use openpgp::cert::prelude::*;
6748 /// use openpgp::packet::prelude::*;
6749 /// use openpgp::policy::StandardPolicy;
6750 /// use openpgp::types::KeyFlags;
6751 /// use openpgp::types::SignatureType;
6752 ///
6753 /// # fn main() -> openpgp::Result<()> {
6754 /// let p = &StandardPolicy::new();
6755 ///
6756 /// let (cert, _) = CertBuilder::new().generate()?;
6757 /// # assert_eq!(cert.keys().count(), 1);
6758 ///
6759 /// let pk = cert.primary_key().key().clone().parts_into_secret()?;
6760 /// // Derive a signer.
6761 /// let mut pk_signer = pk.clone().into_keypair()?;
6762 ///
6763 /// // Generate a new signing subkey.
6764 /// let mut subkey: Key<_, _> = Key4::generate_rsa(3072)?.into();
6765 /// // Derive a signer.
6766 /// let mut sk_signer = subkey.clone().into_keypair()?;
6767 ///
6768 /// // Create the binding signature.
6769 /// let sig = SignatureBuilder::new(SignatureType::SubkeyBinding)
6770 /// .set_key_flags(KeyFlags::empty().set_signing())?
6771 /// // And, the backsig. This is essential for subkeys that create signatures!
6772 /// .set_embedded_signature(
6773 /// SignatureBuilder::new(SignatureType::PrimaryKeyBinding)
6774 /// .sign_primary_key_binding(&mut sk_signer, &pk, &subkey)?)?
6775 /// .sign_subkey_binding(&mut pk_signer, None, &subkey)?;
6776 ///
6777 /// let cert = cert.insert_packets(vec![Packet::SecretSubkey(subkey),
6778 /// sig.into()])?.0;
6779 ///
6780 /// assert_eq!(cert.keys().count(), 2);
6781 /// # Ok(())
6782 /// # }
6783 /// ```
6784 pub fn set_embedded_signature(mut self, signature: Signature)
6785 -> Result<Self> {
6786 self.hashed_area.replace(Subpacket::new(
6787 SubpacketValue::EmbeddedSignature(signature),
6788 true)?)?;
6789 self.unhashed_area.remove_all(SubpacketTag::EmbeddedSignature);
6790
6791 Ok(self)
6792 }
6793
6794 /// Sets the Issuer Fingerprint subpacket.
6795 ///
6796 /// Adds an [Issuer Fingerprint subpacket] to the hashed
6797 /// subpacket area. Unlike [`add_issuer_fingerprint`], this
6798 /// function first removes any existing Issuer Fingerprint
6799 /// subpackets from the hashed and unhashed subpacket area.
6800 ///
6801 /// [Issuer Fingerprint subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
6802 /// [`add_issuer_fingerprint`]: super::SignatureBuilder::add_issuer_fingerprint()
6803 ///
6804 /// The Issuer Fingerprint subpacket is used when processing a
6805 /// signature to identify which certificate created the signature.
6806 /// Even though this information is self-authenticating (the act of
6807 /// validating the signature authenticates the subpacket), it is
6808 /// stored in the hashed subpacket area. This has the advantage
6809 /// that the signer authenticates the set of issuers.
6810 /// Furthermore, it makes handling of the resulting signatures
6811 /// more robust: If there are two signatures that are equal
6812 /// modulo the contents of the unhashed area, there is the
6813 /// question of how to merge the information in the unhashed
6814 /// areas. Storing issuer information in the hashed area avoids
6815 /// this problem.
6816 ///
6817 /// When creating a signature using a SignatureBuilder or the
6818 /// [streaming `Signer`], it is not necessary to explicitly set
6819 /// this subpacket: those functions automatically set both the
6820 /// Issuer Fingerprint subpacket, and the [Issuer subpacket] (set
6821 /// using [`SignatureBuilder::set_issuer`]), if they have not been
6822 /// set explicitly.
6823 ///
6824 /// [streaming `Signer`]: crate::serialize::stream::Signer
6825 /// [Issuer subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
6826 /// [`SignatureBuilder::set_issuer`]: super::SignatureBuilder::set_issuer()
6827 ///
6828 /// # Examples
6829 ///
6830 /// It is possible to use the same key material with different
6831 /// OpenPGP keys. This is useful when the OpenPGP format is
6832 /// upgraded, but not all deployed implementations support the new
6833 /// format. Here, Alice signs a message, and adds the fingerprint
6834 /// of her v4 key and her v5 key indicating that the recipient can
6835 /// use either key to verify the message:
6836 ///
6837 /// ```
6838 /// use sequoia_openpgp as openpgp;
6839 /// # use openpgp::cert::prelude::*;
6840 /// use openpgp::packet::prelude::*;
6841 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6842 /// use openpgp::types::SignatureType;
6843 ///
6844 /// # fn main() -> openpgp::Result<()> {
6845 /// #
6846 /// # let (alicev4, _) =
6847 /// # CertBuilder::general_purpose(Some("alice@example.org"))
6848 /// # .generate()?;
6849 /// # let mut alices_signer = alicev4.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
6850 /// # let (alicev5, _) =
6851 /// # CertBuilder::general_purpose(Some("alice@example.org"))
6852 /// # .generate()?;
6853 /// #
6854 /// let msg = b"Hi!";
6855 ///
6856 /// let sig = SignatureBuilder::new(SignatureType::Binary)
6857 /// .set_issuer_fingerprint(alicev4.fingerprint())?
6858 /// .add_issuer_fingerprint(alicev5.fingerprint())?
6859 /// .sign_message(&mut alices_signer, msg)?;
6860 /// # let mut sig = sig;
6861 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
6862 /// # assert_eq!(sig
6863 /// # .hashed_area()
6864 /// # .iter()
6865 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
6866 /// # .count(),
6867 /// # 0);
6868 /// # assert_eq!(sig
6869 /// # .hashed_area()
6870 /// # .iter()
6871 /// # .filter(|sp| sp.tag() == SubpacketTag::IssuerFingerprint)
6872 /// # .count(),
6873 /// # 2);
6874 /// # Ok(()) }
6875 /// ```
6876 pub fn set_issuer_fingerprint(mut self, fp: Fingerprint) -> Result<Self> {
6877 self.hashed_area.replace(Subpacket::new(
6878 SubpacketValue::IssuerFingerprint(fp),
6879 false)?)?;
6880 self.unhashed_area.remove_all(SubpacketTag::IssuerFingerprint);
6881
6882 Ok(self)
6883 }
6884
6885 /// Adds an Issuer Fingerprint subpacket.
6886 ///
6887 /// Adds an [Issuer Fingerprint subpacket] to the hashed
6888 /// subpacket area. Unlike [`set_issuer_fingerprint`], this
6889 /// function does not first remove any existing Issuer Fingerprint
6890 /// subpacket from neither the hashed nor the unhashed subpacket
6891 /// area.
6892 ///
6893 /// [Issuer Fingerprint subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-issuer-fingerprint
6894 /// [`set_issuer_fingerprint`]: super::SignatureBuilder::set_issuer_fingerprint()
6895 ///
6896 /// The Issuer Fingerprint subpacket is used when processing a
6897 /// signature to identify which certificate created the signature.
6898 /// Even though this information is self-authenticating (the act of
6899 /// validating the signature authenticates the subpacket), it is
6900 /// stored in the hashed subpacket area. This has the advantage
6901 /// that the signer authenticates the set of issuers.
6902 /// Furthermore, it makes handling of the resulting signatures
6903 /// more robust: If there are two signatures that are equal
6904 /// modulo the contents of the unhashed area, there is the
6905 /// question of how to merge the information in the unhashed
6906 /// areas. Storing issuer information in the hashed area avoids
6907 /// this problem.
6908 ///
6909 /// When creating a signature using a SignatureBuilder or the
6910 /// [streaming `Signer`], it is not necessary to explicitly set
6911 /// this subpacket: those functions automatically set both the
6912 /// Issuer Fingerprint subpacket, and the [Issuer subpacket] (set
6913 /// using [`SignatureBuilder::set_issuer`]), if they have not been
6914 /// set explicitly.
6915 ///
6916 /// [streaming `Signer`]: crate::serialize::stream::Signer
6917 /// [Issuer subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.12
6918 /// [`SignatureBuilder::set_issuer`]: super::SignatureBuilder::set_issuer()
6919 ///
6920 /// # Examples
6921 ///
6922 /// It is possible to use the same key material with different
6923 /// OpenPGP keys. This is useful when the OpenPGP format is
6924 /// upgraded, but not all deployed implementations support the new
6925 /// format. Here, Alice signs a message, and adds the fingerprint
6926 /// of her v4 key and her v5 key indicating that the recipient can
6927 /// use either key to verify the message:
6928 ///
6929 /// ```
6930 /// use sequoia_openpgp as openpgp;
6931 /// # use openpgp::cert::prelude::*;
6932 /// use openpgp::packet::prelude::*;
6933 /// # use openpgp::packet::signature::subpacket::SubpacketTag;
6934 /// use openpgp::types::SignatureType;
6935 ///
6936 /// # fn main() -> openpgp::Result<()> {
6937 /// #
6938 /// # let (alicev4, _) =
6939 /// # CertBuilder::general_purpose(Some("alice@example.org"))
6940 /// # .generate()?;
6941 /// # let mut alices_signer = alicev4.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
6942 /// # let (alicev5, _) =
6943 /// # CertBuilder::general_purpose(Some("alice@example.org"))
6944 /// # .generate()?;
6945 /// #
6946 /// let msg = b"Hi!";
6947 ///
6948 /// let sig = SignatureBuilder::new(SignatureType::Binary)
6949 /// .set_issuer_fingerprint(alicev4.fingerprint())?
6950 /// .add_issuer_fingerprint(alicev5.fingerprint())?
6951 /// .sign_message(&mut alices_signer, msg)?;
6952 /// # let mut sig = sig;
6953 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
6954 /// # assert_eq!(sig
6955 /// # .hashed_area()
6956 /// # .iter()
6957 /// # .filter(|sp| sp.tag() == SubpacketTag::Issuer)
6958 /// # .count(),
6959 /// # 0);
6960 /// # assert_eq!(sig
6961 /// # .hashed_area()
6962 /// # .iter()
6963 /// # .filter(|sp| sp.tag() == SubpacketTag::IssuerFingerprint)
6964 /// # .count(),
6965 /// # 2);
6966 /// # Ok(()) }
6967 /// ```
6968 pub fn add_issuer_fingerprint(mut self, fp: Fingerprint) -> Result<Self> {
6969 self.hashed_area.add(Subpacket::new(
6970 SubpacketValue::IssuerFingerprint(fp),
6971 false)?)?;
6972
6973 Ok(self)
6974 }
6975
6976 /// Sets the Preferred AEAD Ciphersuites subpacket.
6977 ///
6978 /// Replaces any [Preferred AEAD Ciphersuites subpacket] in the
6979 /// hashed subpacket area with a new subpacket containing the
6980 /// specified value. That is, this function first removes any
6981 /// Preferred AEAD Ciphersuites subpacket from the hashed
6982 /// subpacket area, and then adds a Preferred AEAD Ciphersuites
6983 /// subpacket.
6984 ///
6985 /// [Preferred AEAD Ciphersuites subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-preferred-aead-ciphersuites
6986 ///
6987 /// The Preferred AEAD Ciphersuites subpacket indicates what AEAD
6988 /// ciphersuites the key holder prefers ordered by preference. If
6989 /// this is set, then the `Version 2 Symmetrically Encrypted and
6990 /// Integrity Protected Data packet` feature flag should in the
6991 /// [Features subpacket] should also be set.
6992 ///
6993 /// [Features subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-features
6994 ///
6995 /// This subpacket is a type of preference. When looking up a
6996 /// preference, an OpenPGP implementation should first look for
6997 /// the subpacket on the binding signature of the User ID or the
6998 /// User Attribute used to locate the certificate (or the primary
6999 /// User ID, if it was addressed by Key ID or fingerprint). If
7000 /// the binding signature doesn't contain the subpacket, then the
7001 /// direct key signature should be checked. See the
7002 /// [`Preferences`] trait for details.
7003 ///
7004 /// Unless addressing different User IDs really should result in
7005 /// different behavior, it is best to only set this preference on
7006 /// the direct key signature. This guarantees that even if some
7007 /// or all User IDs are stripped, the behavior remains consistent.
7008 ///
7009 /// [`Preferences`]: crate::cert::Preferences
7010 ///
7011 /// # Examples
7012 ///
7013 /// Update a certificate's binding signatures to indicate support for AEAD:
7014 ///
7015 /// ```
7016 /// use sequoia_openpgp as openpgp;
7017 /// use openpgp::cert::prelude::*;
7018 /// use openpgp::packet::prelude::*;
7019 /// use openpgp::policy::StandardPolicy;
7020 /// use openpgp::types::{AEADAlgorithm, Features, SymmetricAlgorithm};
7021 ///
7022 /// # fn main() -> openpgp::Result<()> {
7023 /// let p = &StandardPolicy::new();
7024 ///
7025 /// let (cert, _) = CertBuilder::new().add_userid("Alice").generate()?;
7026 ///
7027 /// // Derive a signer (the primary key is always certification capable).
7028 /// let pk = cert.primary_key().key();
7029 /// let mut signer = pk.clone().parts_into_secret()?.into_keypair()?;
7030 ///
7031 /// // Update the cert to advocate support for SEIPDv2 with a
7032 /// // preferred AEAD cipher suite.
7033 /// let symm = SymmetricAlgorithm::default();
7034 /// let aead = AEADAlgorithm::default();
7035 ///
7036 /// let mut sigs = Vec::new();
7037 ///
7038 /// let vc = cert.with_policy(p, None)?;
7039 ///
7040 /// // Update the direct key signature.
7041 /// if let Ok(sig) = vc.direct_key_signature() {
7042 /// sigs.push(
7043 /// SignatureBuilder::from(sig.clone())
7044 /// .set_preferred_aead_ciphersuites(vec![(symm, aead)])?
7045 /// .set_features(
7046 /// sig.features().unwrap_or_else(Features::sequoia)
7047 /// .set_seipdv2())?
7048 /// .sign_direct_key(&mut signer, None)?);
7049 /// }
7050 ///
7051 /// // Update the user ID binding signatures.
7052 /// for ua in vc.userids() {
7053 /// let sig = ua.binding_signature();
7054 /// sigs.push(
7055 /// SignatureBuilder::from(sig.clone())
7056 /// .set_preferred_aead_ciphersuites(vec![(symm, aead)])?
7057 /// .set_features(
7058 /// sig.features().unwrap_or_else(Features::sequoia)
7059 /// .set_seipdv2())?
7060 /// .sign_userid_binding(&mut signer, pk, ua.userid())?);
7061 /// }
7062 ///
7063 /// // Merge in the new signatures.
7064 /// let cert = cert.insert_packets(sigs)?.0;
7065 /// # assert_eq!(cert.bad_signatures().count(), 0);
7066 /// # Ok(())
7067 /// # }
7068 /// ```
7069 pub fn set_preferred_aead_ciphersuites(
7070 mut self,
7071 preferences: Vec<(SymmetricAlgorithm, AEADAlgorithm)>)
7072 -> Result<Self>
7073 {
7074 self.hashed_area.replace(Subpacket::new(
7075 SubpacketValue::PreferredAEADCiphersuites(preferences),
7076 false)?)?;
7077
7078 Ok(self)
7079 }
7080
7081 /// Sets the Intended Recipient subpacket.
7082 ///
7083 /// Replaces any [Intended Recipient subpacket] in the hashed
7084 /// subpacket area with one new subpacket for each of the
7085 /// specified values. That is, unlike
7086 /// [`SignatureBuilder::add_intended_recipient`], this function
7087 /// first removes any Intended Recipient subpackets from the
7088 /// hashed subpacket area, and then adds new ones.
7089 ///
7090 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
7091 /// [`SignatureBuilder::add_intended_recipient`]: super::SignatureBuilder::add_intended_recipient()
7092 ///
7093 /// The Intended Recipient subpacket holds the fingerprint of a
7094 /// certificate.
7095 ///
7096 /// When signing a message, the message should include one such
7097 /// subpacket for each intended recipient. Note: not all messages
7098 /// have intended recipients. For instance, when signing an open
7099 /// letter, or a software release, the message is intended for
7100 /// anyone.
7101 ///
7102 /// When processing a signature, the application should ensure
7103 /// that if there are any such subpackets, then one of the
7104 /// subpackets identifies the recipient's certificate (or user
7105 /// signed the message). If this is not the case, then an
7106 /// attacker may have taken the message out of its original
7107 /// context. For instance, if Alice sends a signed email to Bob,
7108 /// with the content: "I agree to the contract", and Bob forwards
7109 /// that message to Carol, then Carol may think that Alice agreed
7110 /// to a contract with her if the signature appears to be valid!
7111 /// By adding an intended recipient, it is possible for Carol's
7112 /// mail client to warn her that although Alice signed the
7113 /// message, the content was intended for Bob and not for her.
7114 ///
7115 /// # Examples
7116 ///
7117 /// To create a signed message intended for both Bob and Carol,
7118 /// Alice adds an intended recipient subpacket for each of their
7119 /// certificates. Because this function first removes any
7120 /// existing Intended Recipient subpackets both recipients must be
7121 /// added at once (cf. [`SignatureBuilder::add_intended_recipient`]):
7122 ///
7123 /// ```
7124 /// use sequoia_openpgp as openpgp;
7125 /// use openpgp::cert::prelude::*;
7126 /// use openpgp::packet::signature::SignatureBuilder;
7127 /// use openpgp::types::SignatureType;
7128 ///
7129 /// # fn main() -> openpgp::Result<()> {
7130 /// #
7131 /// # let (alice, _) =
7132 /// # CertBuilder::general_purpose(Some("alice@example.org"))
7133 /// # .generate()?;
7134 /// # let mut alices_signer = alice.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
7135 /// # let (bob, _) =
7136 /// # CertBuilder::general_purpose(Some("bob@example.org"))
7137 /// # .generate()?;
7138 /// # let (carol, _) =
7139 /// # CertBuilder::general_purpose(Some("carol@example.org"))
7140 /// # .generate()?;
7141 /// #
7142 /// let msg = b"Let's do it!";
7143 ///
7144 /// let sig = SignatureBuilder::new(SignatureType::Binary)
7145 /// .set_intended_recipients(&[ bob.fingerprint(), carol.fingerprint() ])?
7146 /// .sign_message(&mut alices_signer, msg)?;
7147 /// # let mut sig = sig;
7148 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
7149 /// # assert_eq!(sig.intended_recipients().count(), 2);
7150 /// # Ok(()) }
7151 /// ```
7152 pub fn set_intended_recipients<T>(mut self, recipients: T)
7153 -> Result<Self>
7154 where T: AsRef<[Fingerprint]>
7155 {
7156 self.hashed_area.remove_all(SubpacketTag::IntendedRecipient);
7157 for fp in recipients.as_ref().iter() {
7158 self.hashed_area.add(
7159 Subpacket::new(SubpacketValue::IntendedRecipient(fp.clone()), false)?)?;
7160 }
7161
7162 Ok(self)
7163 }
7164
7165 /// Adds an Intended Recipient subpacket.
7166 ///
7167 /// Adds an [Intended Recipient subpacket] to the hashed subpacket
7168 /// area. Unlike [`SignatureBuilder::set_intended_recipients`], this function does
7169 /// not first remove any Intended Recipient subpackets from the
7170 /// hashed subpacket area.
7171 ///
7172 /// [Intended Recipient subpacket]: https://www.rfc-editor.org/rfc/rfc9580.html#name-intended-recipient-fingerpr
7173 /// [`SignatureBuilder::set_intended_recipients`]: super::SignatureBuilder::set_intended_recipients()
7174 ///
7175 /// The Intended Recipient subpacket holds the fingerprint of a
7176 /// certificate.
7177 ///
7178 /// When signing a message, the message should include one such
7179 /// subpacket for each intended recipient. Note: not all messages
7180 /// have intended recipients. For instance, when signing an open
7181 /// letter, or a software release, the message is intended for
7182 /// anyone.
7183 ///
7184 /// When processing a signature, the application should ensure
7185 /// that if there are any such subpackets, then one of the
7186 /// subpackets identifies the recipient's certificate (or user
7187 /// signed the message). If this is not the case, then an
7188 /// attacker may have taken the message out of its original
7189 /// context. For instance, if Alice sends a signed email to Bob,
7190 /// with the content: "I agree to the contract", and Bob forwards
7191 /// that message to Carol, then Carol may think that Alice agreed
7192 /// to a contract with her if the signature appears to be valid!
7193 /// By adding an intended recipient, it is possible for Carol's
7194 /// mail client to warn her that although Alice signed the
7195 /// message, the content was intended for Bob and not for her.
7196 ///
7197 /// # Examples
7198 ///
7199 /// To create a signed message intended for both Bob and Carol,
7200 /// Alice adds an Intended Recipient subpacket for each of their
7201 /// certificates. Unlike
7202 /// [`SignatureBuilder::set_intended_recipients`], which first
7203 /// removes any existing Intended Recipient subpackets, with this
7204 /// function we can add one recipient after the other:
7205 ///
7206 /// [`SignatureBuilder::set_intended_recipients`]: NotationDataFlags::set_intended_recipients()
7207 ///
7208 /// ```
7209 /// use sequoia_openpgp as openpgp;
7210 /// use openpgp::cert::prelude::*;
7211 /// use openpgp::packet::signature::SignatureBuilder;
7212 /// use openpgp::types::SignatureType;
7213 ///
7214 /// # fn main() -> openpgp::Result<()> {
7215 /// #
7216 /// # let (alice, _) =
7217 /// # CertBuilder::general_purpose(Some("alice@example.org"))
7218 /// # .generate()?;
7219 /// # let mut alices_signer = alice.primary_key().key().clone().parts_into_secret()?.into_keypair()?;
7220 /// # let (bob, _) =
7221 /// # CertBuilder::general_purpose(Some("bob@example.org"))
7222 /// # .generate()?;
7223 /// # let (carol, _) =
7224 /// # CertBuilder::general_purpose(Some("carol@example.org"))
7225 /// # .generate()?;
7226 /// #
7227 /// let msg = b"Let's do it!";
7228 ///
7229 /// let sig = SignatureBuilder::new(SignatureType::Binary)
7230 /// .add_intended_recipient(bob.fingerprint())?
7231 /// .add_intended_recipient(carol.fingerprint())?
7232 /// .sign_message(&mut alices_signer, msg)?;
7233 /// # let mut sig = sig;
7234 /// # assert!(sig.verify_message(alices_signer.public(), msg).is_ok());
7235 /// # assert_eq!(sig.intended_recipients().count(), 2);
7236 /// # Ok(()) }
7237 /// ```
7238 pub fn add_intended_recipient(mut self, recipient: Fingerprint)
7239 -> Result<Self>
7240 {
7241 self.hashed_area.add(
7242 Subpacket::new(SubpacketValue::IntendedRecipient(recipient),
7243 false)?)?;
7244
7245 Ok(self)
7246 }
7247
7248 /// Adds an approved certifications subpacket.
7249 ///
7250 /// This feature is [experimental](crate#experimental-features).
7251 ///
7252 /// Allows the certificate holder to attest to third party
7253 /// certifications, allowing them to be distributed with the
7254 /// certificate. This can be used to address certificate flooding
7255 /// concerns.
7256 ///
7257 /// Sorts the digests and adds an [Approved Certification
7258 /// subpacket] to the hashed subpacket area. The digests must be
7259 /// calculated using the same hash algorithm that is used in the
7260 /// resulting signature. To attest a signature, hash it with
7261 /// [`super::Signature::hash_for_confirmation`].
7262 ///
7263 /// Note: The maximum size of the hashed signature subpacket area
7264 /// constrains the number of attestations that can be stored in a
7265 /// signature. If you need to attest to more certifications,
7266 /// split the digests into chunks and create multiple approved key
7267 /// signatures with the same creation time.
7268 ///
7269 /// See [Approved Certification subpacket] for details.
7270 ///
7271 /// [Approved Certification subpacket]: https://www.ietf.org/archive/id/draft-dkg-openpgp-1pa3pc-02.html#approved-certifications-subpacket
7272 pub fn set_approved_certifications<A, C>(mut self, certifications: C)
7273 -> Result<Self>
7274 where C: IntoIterator<Item = A>,
7275 A: AsRef<[u8]>,
7276 {
7277 let mut digests: Vec<_> = certifications.into_iter()
7278 .map(|d| d.as_ref().to_vec().into_boxed_slice())
7279 .collect();
7280
7281 if let Some(first) = digests.get(0) {
7282 if digests.iter().any(|d| d.len() != first.len()) {
7283 return Err(Error::InvalidOperation(
7284 "Inconsistent digest algorithm used".into()).into());
7285 }
7286 }
7287
7288 // Hashes SHOULD be sorted. This optimizes lookups for the
7289 // consumer and provides a canonical form.
7290 digests.sort_unstable();
7291
7292 self.hashed_area_mut().replace(
7293 Subpacket::new(
7294 SubpacketValue::ApprovedCertifications(digests),
7295 true)?)?;
7296
7297 Ok(self)
7298 }
7299}
7300
7301#[test]
7302fn accessors() {
7303 use crate::types::Curve;
7304
7305 let pk_algo = PublicKeyAlgorithm::EdDSA;
7306 let hash_algo = HashAlgorithm::SHA512;
7307 let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
7308 let mut key: crate::packet::key::SecretKey =
7309 crate::packet::key::Key6::generate_ecc(true, Curve::Ed25519).unwrap().into();
7310 let mut keypair = key.clone().into_keypair().unwrap();
7311 let hash = hash_algo.context().unwrap().for_signature(key.version());
7312
7313 // Cook up a timestamp without ns resolution.
7314 use std::convert::TryFrom;
7315 let now: time::SystemTime =
7316 Timestamp::try_from(crate::now()).unwrap().into();
7317
7318 sig = sig.set_signature_creation_time(now).unwrap();
7319 let sig_ =
7320 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7321 assert_eq!(sig_.signature_creation_time(), Some(now));
7322
7323 let zero_s = time::Duration::new(0, 0);
7324 let minute = time::Duration::new(60, 0);
7325 let five_minutes = 5 * minute;
7326 let ten_minutes = 10 * minute;
7327 sig = sig.set_signature_validity_period(five_minutes).unwrap();
7328 let sig_ =
7329 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7330 assert_eq!(sig_.signature_validity_period(), Some(five_minutes));
7331
7332 assert!(sig_.signature_alive(None, zero_s).is_ok());
7333 assert!(sig_.signature_alive(now, zero_s).is_ok());
7334 assert!(!sig_.signature_alive(now - five_minutes, zero_s).is_ok());
7335 assert!(!sig_.signature_alive(now + ten_minutes, zero_s).is_ok());
7336
7337 sig = sig.modify_hashed_area(|mut a| {
7338 a.remove_all(SubpacketTag::SignatureExpirationTime);
7339 Ok(a)
7340 }).unwrap();
7341 let sig_ =
7342 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7343 assert_eq!(sig_.signature_validity_period(), None);
7344
7345 assert!(sig_.signature_alive(None, zero_s).is_ok());
7346 assert!(sig_.signature_alive(now, zero_s).is_ok());
7347 assert!(!sig_.signature_alive(now - five_minutes, zero_s).is_ok());
7348 assert!(sig_.signature_alive(now + ten_minutes, zero_s).is_ok());
7349
7350 sig = sig.set_exportable_certification(true).unwrap();
7351 let sig_ =
7352 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7353 assert_eq!(sig_.exportable_certification(), Some(true));
7354 sig = sig.set_exportable_certification(false).unwrap();
7355 let sig_ =
7356 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7357 assert_eq!(sig_.exportable_certification(), Some(false));
7358
7359 sig = sig.set_trust_signature(2, 3).unwrap();
7360 let sig_ =
7361 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7362 assert_eq!(sig_.trust_signature(), Some((2, 3)));
7363
7364 sig = sig.set_regular_expression(b"foobar").unwrap();
7365 let sig_ =
7366 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7367 assert_eq!(sig_.regular_expressions().collect::<Vec<&[u8]>>(),
7368 vec![ &b"foobar"[..] ]);
7369
7370 sig = sig.set_revocable(true).unwrap();
7371 let sig_ =
7372 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7373 assert_eq!(sig_.revocable(), Some(true));
7374 sig = sig.set_revocable(false).unwrap();
7375 let sig_ =
7376 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7377 assert_eq!(sig_.revocable(), Some(false));
7378
7379 key.set_creation_time(now).unwrap();
7380 sig = sig.set_key_validity_period(Some(five_minutes)).unwrap();
7381 let sig_ =
7382 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7383 assert_eq!(sig_.key_validity_period(), Some(five_minutes));
7384
7385 assert!(sig_.key_alive(&key, None).is_ok());
7386 assert!(sig_.key_alive(&key, now).is_ok());
7387 assert!(!sig_.key_alive(&key, now - five_minutes).is_ok());
7388 assert!(!sig_.key_alive(&key, now + ten_minutes).is_ok());
7389
7390 sig = sig.set_key_validity_period(None).unwrap();
7391 let sig_ =
7392 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7393 assert_eq!(sig_.key_validity_period(), None);
7394
7395 assert!(sig_.key_alive(&key, None).is_ok());
7396 assert!(sig_.key_alive(&key, now).is_ok());
7397 assert!(!sig_.key_alive(&key, now - five_minutes).is_ok());
7398 assert!(sig_.key_alive(&key, now + ten_minutes).is_ok());
7399
7400 let pref = vec![SymmetricAlgorithm::AES256,
7401 SymmetricAlgorithm::AES192,
7402 SymmetricAlgorithm::AES128];
7403 sig = sig.set_preferred_symmetric_algorithms(pref.clone()).unwrap();
7404 let sig_ =
7405 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7406 assert_eq!(sig_.preferred_symmetric_algorithms(), Some(&pref[..]));
7407
7408 let fp = Fingerprint::from_bytes(4, b"bbbbbbbbbbbbbbbbbbbb").unwrap();
7409 let rk = RevocationKey::new(pk_algo, fp.clone(), true);
7410 sig = sig.set_revocation_key(rk.clone()).unwrap();
7411 sig = sig.set_revocation_key(rk.clone()).unwrap();
7412 let sig_ =
7413 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7414 assert_eq!(sig_.revocation_keys().next().unwrap(), &rk);
7415 assert_eq!(sig_.revocation_keys().count(), 1);
7416
7417 sig = sig.add_revocation_key(rk.clone()).unwrap();
7418 sig = sig.add_revocation_key(rk.clone()).unwrap();
7419 let sig_ =
7420 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7421 assert_eq!(sig_.revocation_keys().count(), 3);
7422
7423 sig = sig.set_issuer(fp.clone().into()).unwrap();
7424 let sig_ =
7425 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7426 assert_eq!(sig_.issuers().collect::<Vec<_>>(),
7427 vec![ &fp.clone().into() ]);
7428
7429 let pref = vec![HashAlgorithm::SHA512,
7430 HashAlgorithm::SHA384,
7431 HashAlgorithm::SHA256];
7432 sig = sig.set_preferred_hash_algorithms(pref.clone()).unwrap();
7433 let sig_ =
7434 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7435 assert_eq!(sig_.preferred_hash_algorithms(), Some(&pref[..]));
7436
7437 let pref = vec![CompressionAlgorithm::BZip2,
7438 CompressionAlgorithm::Zlib,
7439 CompressionAlgorithm::Zip];
7440 sig = sig.set_preferred_compression_algorithms(pref.clone()).unwrap();
7441 let sig_ =
7442 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7443 assert_eq!(sig_.preferred_compression_algorithms(), Some(&pref[..]));
7444
7445 let pref = KeyServerPreferences::empty()
7446 .set_no_modify();
7447 sig = sig.set_key_server_preferences(pref.clone()).unwrap();
7448 let sig_ =
7449 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7450 assert_eq!(sig_.key_server_preferences().unwrap(), pref);
7451
7452 sig = sig.set_primary_userid(true).unwrap();
7453 let sig_ =
7454 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7455 assert_eq!(sig_.primary_userid(), Some(true));
7456 sig = sig.set_primary_userid(false).unwrap();
7457 let sig_ =
7458 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7459 assert_eq!(sig_.primary_userid(), Some(false));
7460
7461 sig = sig.set_policy_uri(b"foobar").unwrap();
7462 let sig_ =
7463 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7464 assert_eq!(sig_.policy_uri(), Some(&b"foobar"[..]));
7465
7466 let key_flags = KeyFlags::empty()
7467 .set_certification()
7468 .set_signing();
7469 sig = sig.set_key_flags(key_flags.clone()).unwrap();
7470 let sig_ =
7471 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7472 assert_eq!(sig_.key_flags().unwrap(), key_flags);
7473
7474 sig = sig.set_signers_user_id(b"foobar").unwrap();
7475 let sig_ =
7476 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7477 assert_eq!(sig_.signers_user_id(), Some(&b"foobar"[..]));
7478
7479 sig = sig.set_reason_for_revocation(ReasonForRevocation::KeyRetired,
7480 b"foobar").unwrap();
7481 let sig_ =
7482 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7483 assert_eq!(sig_.reason_for_revocation(),
7484 Some((ReasonForRevocation::KeyRetired, &b"foobar"[..])));
7485
7486 let feats = Features::empty().set_seipdv1();
7487 sig = sig.set_features(feats.clone()).unwrap();
7488 let sig_ =
7489 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7490 assert_eq!(sig_.features().unwrap(), feats);
7491
7492 let feats = Features::empty().set_seipdv2();
7493 sig = sig.set_features(feats.clone()).unwrap();
7494 let sig_ =
7495 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7496 assert_eq!(sig_.features().unwrap(), feats);
7497
7498 let digest = vec![0; hash_algo.digest_size().unwrap()];
7499 sig = sig.set_signature_target(pk_algo, hash_algo, &digest).unwrap();
7500 let sig_ =
7501 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7502 assert_eq!(sig_.signature_target(), Some((pk_algo,
7503 hash_algo,
7504 &digest[..])));
7505
7506 let embedded_sig = sig_.clone();
7507 sig = sig.set_embedded_signature(embedded_sig.clone()).unwrap();
7508 let sig_ =
7509 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7510 assert_eq!(sig_.embedded_signatures().next(), Some(&embedded_sig));
7511
7512 sig = sig.set_issuer_fingerprint(fp.clone()).unwrap();
7513 let sig_ =
7514 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7515 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
7516 vec![ &fp ]);
7517
7518 let pref = vec![(SymmetricAlgorithm::AES128, AEADAlgorithm::EAX),
7519 (SymmetricAlgorithm::AES128, AEADAlgorithm::OCB)];
7520 sig = sig.set_preferred_aead_ciphersuites(pref.clone()).unwrap();
7521 let sig_ =
7522 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7523 assert_eq!(sig_.preferred_aead_ciphersuites(), Some(&pref[..]));
7524
7525 let fps = vec![
7526 Fingerprint::from_bytes(4, b"aaaaaaaaaaaaaaaaaaaa").unwrap(),
7527 Fingerprint::from_bytes(4, b"bbbbbbbbbbbbbbbbbbbb").unwrap(),
7528 ];
7529 sig = sig.set_intended_recipients(fps.clone()).unwrap();
7530 let sig_ =
7531 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7532 assert_eq!(sig_.intended_recipients().collect::<Vec<&Fingerprint>>(),
7533 fps.iter().collect::<Vec<&Fingerprint>>());
7534
7535 sig = sig.set_notation("test@example.org", &[0, 1, 2], None, false)
7536 .unwrap();
7537 let sig_ =
7538 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7539 assert_eq!(sig_.notation("test@example.org").collect::<Vec<&[u8]>>(),
7540 vec![&[0, 1, 2]]);
7541
7542 sig = sig.add_notation("test@example.org", &[3, 4, 5], None, false)
7543 .unwrap();
7544 let sig_ =
7545 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7546 assert_eq!(sig_.notation("test@example.org").collect::<Vec<&[u8]>>(),
7547 vec![&[0, 1, 2], &[3, 4, 5]]);
7548
7549 sig = sig.set_notation("test@example.org", &[6, 7, 8], None, false)
7550 .unwrap();
7551 let sig_ =
7552 sig.clone().sign_hash(&mut keypair, hash.clone()).unwrap();
7553 assert_eq!(sig_.notation("test@example.org").collect::<Vec<&[u8]>>(),
7554 vec![&[6, 7, 8]]);
7555}
7556
7557#[cfg(feature = "compression-deflate")]
7558#[test]
7559fn subpacket_test_1 () {
7560 use crate::Packet;
7561 use crate::PacketPile;
7562 use crate::parse::Parse;
7563
7564 let pile = PacketPile::from_bytes(crate::tests::message("signed.pgp")).unwrap();
7565 eprintln!("PacketPile has {} top-level packets.", pile.children().len());
7566 eprintln!("PacketPile: {:?}", pile);
7567
7568 let mut count = 0;
7569 for p in pile.descendants() {
7570 if let &Packet::Signature(ref sig) = p {
7571 count += 1;
7572
7573 let mut got2 = false;
7574 let mut got16 = false;
7575 let mut got33 = false;
7576
7577 for i in 0..255 {
7578 if let Some(sb) = sig.subpacket(i.into()) {
7579 if i == 2 {
7580 got2 = true;
7581 assert!(!sb.critical);
7582 } else if i == 16 {
7583 got16 = true;
7584 assert!(!sb.critical);
7585 } else if i == 33 {
7586 got33 = true;
7587 assert!(!sb.critical);
7588 } else {
7589 panic!("Unexpectedly found subpacket {}", i);
7590 }
7591 }
7592 }
7593
7594 assert!(got2 && got16 && got33);
7595
7596 let hex = format!("{:X}", sig.issuer_fingerprints().next().unwrap());
7597 assert!(
7598 hex == "7FAF6ED7238143557BDF7ED26863C9AD5B4D22D3"
7599 || hex == "C03FA6411B03AE12576461187223B56678E02528");
7600 }
7601 }
7602 // 2 packets have subpackets.
7603 assert_eq!(count, 2);
7604}
7605
7606#[test]
7607#[allow(deprecated)]
7608fn subpacket_test_2() {
7609 use crate::Packet;
7610 use crate::parse::Parse;
7611 use crate::PacketPile;
7612
7613 // Test # Subpacket
7614 // 1 2 3 4 5 6 SignatureCreationTime
7615 // * SignatureExpirationTime
7616 // 2 ExportableCertification
7617 // 6 TrustSignature
7618 // 6 RegularExpression
7619 // 3 Revocable
7620 // 1 7 KeyExpirationTime
7621 // 1 PreferredSymmetricAlgorithms
7622 // 3 RevocationKey
7623 // 1 3 7 Issuer
7624 // 1 3 5 NotationData
7625 // 1 PreferredHashAlgorithms
7626 // 1 PreferredCompressionAlgorithms
7627 // 1 KeyServerPreferences
7628 // * PreferredKeyServer
7629 // * PrimaryUserID
7630 // * PolicyURI
7631 // 1 KeyFlags
7632 // * SignersUserID
7633 // 4 ReasonForRevocation
7634 // 1 Features
7635 // * SignatureTarget
7636 // 7 EmbeddedSignature
7637 // 1 3 7 IssuerFingerprint
7638 //
7639 // XXX: The subpackets marked with * are not tested.
7640
7641 let pile = PacketPile::from_bytes(
7642 crate::tests::key("subpackets/shaw.pgp")).unwrap();
7643
7644 // Test #1
7645 if let (Some(&Packet::PublicKey(ref key)),
7646 Some(&Packet::Signature(ref sig)))
7647 = (pile.children().next(), pile.children().nth(2))
7648 {
7649 // tag: 2, SignatureCreationTime(1515791508) }
7650 // tag: 9, KeyExpirationTime(63072000) }
7651 // tag: 11, PreferredSymmetricAlgorithms([9, 8, 7, 2]) }
7652 // tag: 16, Issuer(KeyID("F004 B9A4 5C58 6126")) }
7653 // tag: 20, NotationData(NotationData { flags: 2147483648, name: [114, 97, 110, 107, 64, 110, 97, 118, 121, 46, 109, 105, 108], value: [109, 105, 100, 115, 104, 105, 112, 109, 97, 110] }) }
7654 // tag: 21, PreferredHashAlgorithms([8, 9, 10, 11, 2]) }
7655 // tag: 22, PreferredCompressionAlgorithms([2, 3, 1]) }
7656 // tag: 23, KeyServerPreferences([128]) }
7657 // tag: 27, KeyFlags([3]) }
7658 // tag: 30, Features([1]) }
7659 // tag: 33, IssuerFingerprint(Fingerprint("361A 96BD E1A6 5B6D 6C25 AE9F F004 B9A4 5C58 6126")) }
7660 // for i in 0..256 {
7661 // if let Some(sb) = sig.subpacket(i as u8) {
7662 // eprintln!(" {:?}", sb);
7663 // }
7664 // }
7665
7666 assert_eq!(sig.signature_creation_time(),
7667 Some(Timestamp::from(1515791508).into()));
7668 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
7669 Some(&Subpacket {
7670 length: 5.into(),
7671 critical: false,
7672 value: SubpacketValue::SignatureCreationTime(
7673 1515791508.into()),
7674 authenticated: false.into(),
7675 }));
7676
7677 // The signature does not expire.
7678 assert!(sig.signature_alive(None, None).is_ok());
7679
7680 assert_eq!(sig.key_validity_period(),
7681 Some(Duration::from(63072000).into()));
7682 assert_eq!(sig.subpacket(SubpacketTag::KeyExpirationTime),
7683 Some(&Subpacket {
7684 length: 5.into(),
7685 critical: false,
7686 value: SubpacketValue::KeyExpirationTime(
7687 63072000.into()),
7688 authenticated: false.into(),
7689 }));
7690
7691 // Check key expiration.
7692 assert!(sig.key_alive(
7693 key,
7694 key.creation_time() + time::Duration::new(63072000 - 1, 0))
7695 .is_ok());
7696 assert!(! sig.key_alive(
7697 key,
7698 key.creation_time() + time::Duration::new(63072000, 0))
7699 .is_ok());
7700
7701 assert_eq!(sig.preferred_symmetric_algorithms(),
7702 Some(&[SymmetricAlgorithm::AES256,
7703 SymmetricAlgorithm::AES192,
7704 SymmetricAlgorithm::AES128,
7705 SymmetricAlgorithm::TripleDES][..]));
7706 assert_eq!(sig.subpacket(SubpacketTag::PreferredSymmetricAlgorithms),
7707 Some(&Subpacket {
7708 length: 5.into(),
7709 critical: false,
7710 value: SubpacketValue::PreferredSymmetricAlgorithms(
7711 vec![SymmetricAlgorithm::AES256,
7712 SymmetricAlgorithm::AES192,
7713 SymmetricAlgorithm::AES128,
7714 SymmetricAlgorithm::TripleDES]
7715 ),
7716 authenticated: false.into(),
7717 }));
7718
7719 assert_eq!(sig.preferred_hash_algorithms(),
7720 Some(&[HashAlgorithm::SHA256,
7721 HashAlgorithm::SHA384,
7722 HashAlgorithm::SHA512,
7723 HashAlgorithm::SHA224,
7724 HashAlgorithm::SHA1][..]));
7725 assert_eq!(sig.subpacket(SubpacketTag::PreferredHashAlgorithms),
7726 Some(&Subpacket {
7727 length: 6.into(),
7728 critical: false,
7729 value: SubpacketValue::PreferredHashAlgorithms(
7730 vec![HashAlgorithm::SHA256,
7731 HashAlgorithm::SHA384,
7732 HashAlgorithm::SHA512,
7733 HashAlgorithm::SHA224,
7734 HashAlgorithm::SHA1]
7735 ),
7736 authenticated: false.into(),
7737 }));
7738
7739 assert_eq!(sig.preferred_compression_algorithms(),
7740 Some(&[CompressionAlgorithm::Zlib,
7741 CompressionAlgorithm::BZip2,
7742 CompressionAlgorithm::Zip][..]));
7743 assert_eq!(sig.subpacket(SubpacketTag::PreferredCompressionAlgorithms),
7744 Some(&Subpacket {
7745 length: 4.into(),
7746 critical: false,
7747 value: SubpacketValue::PreferredCompressionAlgorithms(
7748 vec![CompressionAlgorithm::Zlib,
7749 CompressionAlgorithm::BZip2,
7750 CompressionAlgorithm::Zip]
7751 ),
7752 authenticated: false.into(),
7753 }));
7754
7755 assert_eq!(sig.key_server_preferences().unwrap(),
7756 KeyServerPreferences::empty().set_no_modify());
7757 assert_eq!(sig.subpacket(SubpacketTag::KeyServerPreferences),
7758 Some(&Subpacket {
7759 length: 2.into(),
7760 critical: false,
7761 value: SubpacketValue::KeyServerPreferences(
7762 KeyServerPreferences::empty().set_no_modify()),
7763 authenticated: false.into(),
7764 }));
7765
7766 assert!(sig.key_flags().unwrap().for_certification());
7767 assert!(sig.key_flags().unwrap().for_signing());
7768 assert_eq!(sig.subpacket(SubpacketTag::KeyFlags),
7769 Some(&Subpacket {
7770 length: 2.into(),
7771 critical: false,
7772 value: SubpacketValue::KeyFlags(
7773 KeyFlags::empty().set_certification().set_signing()),
7774 authenticated: false.into(),
7775 }));
7776
7777 assert_eq!(sig.features().unwrap(), Features::empty().set_seipdv1());
7778 assert_eq!(sig.subpacket(SubpacketTag::Features),
7779 Some(&Subpacket {
7780 length: 2.into(),
7781 critical: false,
7782 value: SubpacketValue::Features(
7783 Features::empty().set_seipdv1()),
7784 authenticated: false.into(),
7785 }));
7786
7787 let keyid = "F004 B9A4 5C58 6126".parse().unwrap();
7788 assert_eq!(sig.issuers().collect::<Vec<_>>(), vec![ &keyid ]);
7789 assert_eq!(sig.subpacket(SubpacketTag::Issuer),
7790 Some(&Subpacket {
7791 length: 9.into(),
7792 critical: false,
7793 value: SubpacketValue::Issuer(keyid),
7794 authenticated: false.into(),
7795 }));
7796
7797 let fp = "361A96BDE1A65B6D6C25AE9FF004B9A45C586126".parse().unwrap();
7798 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(), vec![ &fp ]);
7799 assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint),
7800 Some(&Subpacket {
7801 length: 22.into(),
7802 critical: false,
7803 value: SubpacketValue::IssuerFingerprint(fp),
7804 authenticated: false.into(),
7805 }));
7806
7807 let n = NotationData {
7808 flags: NotationDataFlags::empty().set_human_readable(),
7809 name: "rank@navy.mil".into(),
7810 value: b"midshipman".to_vec()
7811 };
7812 assert_eq!(sig.notation_data().collect::<Vec<&NotationData>>(),
7813 vec![&n]);
7814 assert_eq!(sig.subpacket(SubpacketTag::NotationData),
7815 Some(&Subpacket {
7816 length: 32.into(),
7817 critical: false,
7818 value: SubpacketValue::NotationData(n.clone()),
7819 authenticated: false.into(),
7820 }));
7821 assert_eq!(sig.hashed_area().subpackets(SubpacketTag::NotationData)
7822 .collect::<Vec<_>>(),
7823 vec![&Subpacket {
7824 length: 32.into(),
7825 critical: false,
7826 value: SubpacketValue::NotationData(n.clone()),
7827 authenticated: false.into(),
7828 }]);
7829 } else {
7830 panic!("Expected signature!");
7831 }
7832
7833 // Test #2
7834 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(3) {
7835 // tag: 2, SignatureCreationTime(1515791490)
7836 // tag: 4, ExportableCertification(false)
7837 // tag: 16, Issuer(KeyID("CEAD 0621 0934 7957"))
7838 // tag: 33, IssuerFingerprint(Fingerprint("B59B 8817 F519 DCE1 0AFD 85E4 CEAD 0621 0934 7957"))
7839
7840 // for i in 0..256 {
7841 // if let Some(sb) = sig.subpacket(i as u8) {
7842 // eprintln!(" {:?}", sb);
7843 // }
7844 // }
7845
7846 assert_eq!(sig.signature_creation_time(),
7847 Some(Timestamp::from(1515791490).into()));
7848 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
7849 Some(&Subpacket {
7850 length: 5.into(),
7851 critical: false,
7852 value: SubpacketValue::SignatureCreationTime(
7853 1515791490.into()),
7854 authenticated: false.into(),
7855 }));
7856
7857 assert_eq!(sig.exportable_certification(), Some(false));
7858 assert_eq!(sig.subpacket(SubpacketTag::ExportableCertification),
7859 Some(&Subpacket {
7860 length: 2.into(),
7861 critical: false,
7862 value: SubpacketValue::ExportableCertification(false),
7863 authenticated: false.into(),
7864 }));
7865 }
7866
7867 let pile = PacketPile::from_bytes(
7868 crate::tests::key("subpackets/marven.pgp")).unwrap();
7869
7870 // Test #3
7871 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(1) {
7872 // tag: 2, SignatureCreationTime(1515791376)
7873 // tag: 7, Revocable(false)
7874 // tag: 12, RevocationKey((128, 1, Fingerprint("361A 96BD E1A6 5B6D 6C25 AE9F F004 B9A4 5C58 6126")))
7875 // tag: 16, Issuer(KeyID("CEAD 0621 0934 7957"))
7876 // tag: 33, IssuerFingerprint(Fingerprint("B59B 8817 F519 DCE1 0AFD 85E4 CEAD 0621 0934 7957"))
7877
7878 // for i in 0..256 {
7879 // if let Some(sb) = sig.subpacket(i as u8) {
7880 // eprintln!(" {:?}", sb);
7881 // }
7882 // }
7883
7884 assert_eq!(sig.signature_creation_time(),
7885 Some(Timestamp::from(1515791376).into()));
7886 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
7887 Some(&Subpacket {
7888 length: 5.into(),
7889 critical: false,
7890 value: SubpacketValue::SignatureCreationTime(
7891 1515791376.into()),
7892 authenticated: false.into(),
7893 }));
7894
7895 assert_eq!(sig.revocable(), Some(false));
7896 assert_eq!(sig.subpacket(SubpacketTag::Revocable),
7897 Some(&Subpacket {
7898 length: 2.into(),
7899 critical: false,
7900 value: SubpacketValue::Revocable(false),
7901 authenticated: false.into(),
7902 }));
7903
7904 let fp = "361A96BDE1A65B6D6C25AE9FF004B9A45C586126".parse().unwrap();
7905 let rk = RevocationKey::new(PublicKeyAlgorithm::RSAEncryptSign,
7906 fp, false);
7907 assert_eq!(sig.revocation_keys().next().unwrap(), &rk);
7908 assert_eq!(sig.subpacket(SubpacketTag::RevocationKey),
7909 Some(&Subpacket {
7910 length: 23.into(),
7911 critical: false,
7912 value: SubpacketValue::RevocationKey(rk),
7913 authenticated: false.into(),
7914 }));
7915
7916
7917 let keyid = "CEAD 0621 0934 7957".parse().unwrap();
7918 assert_eq!(sig.issuers().collect::<Vec<_>>(),
7919 vec![ &keyid ]);
7920 assert_eq!(sig.subpacket(SubpacketTag::Issuer),
7921 Some(&Subpacket {
7922 length: 9.into(),
7923 critical: false,
7924 value: SubpacketValue::Issuer(keyid),
7925 authenticated: false.into(),
7926 }));
7927
7928 let fp = "B59B8817F519DCE10AFD85E4CEAD062109347957".parse().unwrap();
7929 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
7930 vec![ &fp ]);
7931 assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint),
7932 Some(&Subpacket {
7933 length: 22.into(),
7934 critical: false,
7935 value: SubpacketValue::IssuerFingerprint(fp),
7936 authenticated: false.into(),
7937 }));
7938
7939 // This signature does not contain any notation data.
7940 assert_eq!(sig.notation_data().count(), 0);
7941 assert_eq!(sig.subpacket(SubpacketTag::NotationData),
7942 None);
7943 assert_eq!(sig.subpackets(SubpacketTag::NotationData).count(), 0);
7944 } else {
7945 panic!("Expected signature!");
7946 }
7947
7948 // Test #4
7949 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(6) {
7950 // for i in 0..256 {
7951 // if let Some(sb) = sig.subpacket(i as u8) {
7952 // eprintln!(" {:?}", sb);
7953 // }
7954 // }
7955
7956 assert_eq!(sig.signature_creation_time(),
7957 Some(Timestamp::from(1515886658).into()));
7958 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
7959 Some(&Subpacket {
7960 length: 5.into(),
7961 critical: false,
7962 value: SubpacketValue::SignatureCreationTime(
7963 1515886658.into()),
7964 authenticated: false.into(),
7965 }));
7966
7967 assert_eq!(sig.reason_for_revocation(),
7968 Some((ReasonForRevocation::Unspecified,
7969 &b"Forgot to set a sig expiration."[..])));
7970 assert_eq!(sig.subpacket(SubpacketTag::ReasonForRevocation),
7971 Some(&Subpacket {
7972 length: 33.into(),
7973 critical: false,
7974 value: SubpacketValue::ReasonForRevocation {
7975 code: ReasonForRevocation::Unspecified,
7976 reason: b"Forgot to set a sig expiration.".to_vec(),
7977 },
7978 authenticated: false.into(),
7979 }));
7980 }
7981
7982
7983 // Test #5
7984 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(7) {
7985 // The only thing interesting about this signature is that it
7986 // has multiple notations.
7987
7988 assert_eq!(sig.signature_creation_time(),
7989 Some(Timestamp::from(1515791467).into()));
7990 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
7991 Some(&Subpacket {
7992 length: 5.into(),
7993 critical: false,
7994 value: SubpacketValue::SignatureCreationTime(
7995 1515791467.into()),
7996 authenticated: false.into(),
7997 }));
7998
7999 let n1 = NotationData {
8000 flags: NotationDataFlags::empty().set_human_readable(),
8001 name: "rank@navy.mil".into(),
8002 value: b"third lieutenant".to_vec()
8003 };
8004 let n2 = NotationData {
8005 flags: NotationDataFlags::empty().set_human_readable(),
8006 name: "foo@navy.mil".into(),
8007 value: b"bar".to_vec()
8008 };
8009 let n3 = NotationData {
8010 flags: NotationDataFlags::empty().set_human_readable(),
8011 name: "whistleblower@navy.mil".into(),
8012 value: b"true".to_vec()
8013 };
8014
8015 // We expect all three notations, in order.
8016 assert_eq!(sig.notation_data().collect::<Vec<&NotationData>>(),
8017 vec![&n1, &n2, &n3]);
8018
8019 // We expect only the last notation.
8020 assert_eq!(sig.subpacket(SubpacketTag::NotationData),
8021 Some(&Subpacket {
8022 length: 35.into(),
8023 critical: false,
8024 value: SubpacketValue::NotationData(n3.clone()),
8025 authenticated: false.into(),
8026 }));
8027
8028 // We expect all three notations, in order.
8029 assert_eq!(sig.subpackets(SubpacketTag::NotationData)
8030 .collect::<Vec<_>>(),
8031 vec![
8032 &Subpacket {
8033 length: 38.into(),
8034 critical: false,
8035 value: SubpacketValue::NotationData(n1),
8036 authenticated: false.into(),
8037 },
8038 &Subpacket {
8039 length: 24.into(),
8040 critical: false,
8041 value: SubpacketValue::NotationData(n2),
8042 authenticated: false.into(),
8043 },
8044 &Subpacket {
8045 length: 35.into(),
8046 critical: false,
8047 value: SubpacketValue::NotationData(n3),
8048 authenticated: false.into(),
8049 },
8050 ]);
8051 }
8052
8053 // # Test 6
8054 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(8) {
8055 // A trusted signature.
8056
8057 // tag: 2, SignatureCreationTime(1515791223)
8058 // tag: 5, TrustSignature((2, 120))
8059 // tag: 6, RegularExpression([60, 91, 94, 62, 93, 43, 91, 64, 46, 93, 110, 97, 118, 121, 92, 46, 109, 105, 108, 62, 36])
8060 // tag: 16, Issuer(KeyID("F004 B9A4 5C58 6126"))
8061 // tag: 33, IssuerFingerprint(Fingerprint("361A 96BD E1A6 5B6D 6C25 AE9F F004 B9A4 5C58 6126"))
8062
8063 // for i in 0..256 {
8064 // if let Some(sb) = sig.subpacket(i as u8) {
8065 // eprintln!(" {:?}", sb);
8066 // }
8067 // }
8068
8069 assert_eq!(sig.signature_creation_time(),
8070 Some(Timestamp::from(1515791223).into()));
8071 assert_eq!(sig.subpacket(SubpacketTag::SignatureCreationTime),
8072 Some(&Subpacket {
8073 length: 5.into(),
8074 critical: false,
8075 value: SubpacketValue::SignatureCreationTime(
8076 1515791223.into()),
8077 authenticated: false.into(),
8078 }));
8079
8080 assert_eq!(sig.trust_signature(), Some((2, 120)));
8081 assert_eq!(sig.subpacket(SubpacketTag::TrustSignature),
8082 Some(&Subpacket {
8083 length: 3.into(),
8084 critical: false,
8085 value: SubpacketValue::TrustSignature {
8086 level: 2,
8087 trust: 120,
8088 },
8089 authenticated: false.into(),
8090 }));
8091
8092 // Note: our parser strips the trailing NUL.
8093 let regex = &b"<[^>]+[@.]navy\\.mil>$"[..];
8094 assert_eq!(sig.regular_expressions().collect::<Vec<&[u8]>>(),
8095 vec![ regex ]);
8096 assert_eq!(sig.subpacket(SubpacketTag::RegularExpression),
8097 Some(&Subpacket {
8098 length: 23.into(),
8099 critical: true,
8100 value: SubpacketValue::RegularExpression(regex.to_vec()),
8101 authenticated: false.into(),
8102 }));
8103 }
8104
8105 // Test #7
8106 if let Some(&Packet::Signature(ref sig)) = pile.children().nth(11) {
8107 // A subkey self-sig, which contains an embedded signature.
8108 // tag: 2, SignatureCreationTime(1515798986)
8109 // tag: 9, KeyExpirationTime(63072000)
8110 // tag: 16, Issuer(KeyID("CEAD 0621 0934 7957"))
8111 // tag: 27, KeyFlags([2])
8112 // tag: 32, EmbeddedSignature(Signature(Signature {
8113 // version: 4, sigtype: 25, timestamp: Some(1515798986),
8114 // issuer: "F682 42EA 9847 7034 5DEC 5F08 4688 10D3 D67F 6CA9",
8115 // pk_algo: 1, hash_algo: 8, hashed_area: "29 bytes",
8116 // unhashed_area: "10 bytes", hash_prefix: [162, 209],
8117 // mpis: "258 bytes"))
8118 // tag: 33, IssuerFingerprint(Fingerprint("B59B 8817 F519 DCE1 0AFD 85E4 CEAD 0621 0934 7957"))
8119
8120 // for i in 0..256 {
8121 // if let Some(sb) = sig.subpacket(i as u8) {
8122 // eprintln!(" {:?}", sb);
8123 // }
8124 // }
8125
8126 assert_eq!(sig.key_validity_period(),
8127 Some(Duration::from(63072000).into()));
8128 assert_eq!(sig.subpacket(SubpacketTag::KeyExpirationTime),
8129 Some(&Subpacket {
8130 length: 5.into(),
8131 critical: false,
8132 value: SubpacketValue::KeyExpirationTime(
8133 63072000.into()),
8134 authenticated: false.into(),
8135 }));
8136
8137 let keyid = "CEAD 0621 0934 7957".parse().unwrap();
8138 assert_eq!(sig.issuers().collect::<Vec<_>>(), vec! [&keyid ]);
8139 assert_eq!(sig.subpacket(SubpacketTag::Issuer),
8140 Some(&Subpacket {
8141 length: 9.into(),
8142 critical: false,
8143 value: SubpacketValue::Issuer(keyid),
8144 authenticated: false.into(),
8145 }));
8146
8147 let fp = "B59B8817F519DCE10AFD85E4CEAD062109347957".parse().unwrap();
8148 assert_eq!(sig.issuer_fingerprints().collect::<Vec<_>>(),
8149 vec![ &fp ]);
8150 assert_eq!(sig.subpacket(SubpacketTag::IssuerFingerprint),
8151 Some(&Subpacket {
8152 length: 22.into(),
8153 critical: false,
8154 value: SubpacketValue::IssuerFingerprint(fp),
8155 authenticated: false.into(),
8156 }));
8157
8158 assert_eq!(sig.embedded_signatures().count(), 1);
8159 assert!(sig.subpacket(SubpacketTag::EmbeddedSignature)
8160 .is_some());
8161 }
8162
8163// for (i, p) in pile.children().enumerate() {
8164// if let &Packet::Signature(ref sig) = p {
8165// eprintln!("{:?}: {:?}", i, sig);
8166// for j in 0..256 {
8167// if let Some(sb) = sig.subpacket(j as u8) {
8168// eprintln!(" {:?}", sb);
8169// }
8170// }
8171// }
8172 // }
8173 ()
8174}
8175
8176#[test]
8177fn issuer_default_v4() -> Result<()> {
8178 use crate::types::Curve;
8179
8180 let hash_algo = HashAlgorithm::SHA512;
8181 let sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8182 let key: crate::packet::key::SecretKey =
8183 crate::packet::key::Key4::generate_ecc(true, Curve::Ed25519)?.into();
8184 let mut keypair = key.into_keypair()?;
8185 let hash = hash_algo.context()?.for_signature(keypair.public().version());
8186
8187 // no issuer or issuer_fingerprint present, use default
8188 let sig_ = sig.sign_hash(&mut keypair, hash.clone())?;
8189
8190 assert_eq!(sig_.issuers().collect::<Vec<_>>(),
8191 vec![ &keypair.public().keyid() ]);
8192 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
8193 vec![ &keypair.public().fingerprint() ]);
8194
8195 let fp = Fingerprint::from_bytes(4, b"bbbbbbbbbbbbbbbbbbbb")?;
8196
8197 // issuer subpacket present, do not override
8198 let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8199
8200 sig = sig.set_issuer(fp.clone().into())?;
8201 let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?;
8202
8203 assert_eq!(sig_.issuers().collect::<Vec<_>>(),
8204 vec![ &fp.clone().into() ]);
8205 assert_eq!(sig_.issuer_fingerprints().count(), 0);
8206
8207 // issuer_fingerprint subpacket present, do not override
8208 let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8209
8210 sig = sig.set_issuer_fingerprint(fp.clone())?;
8211 let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?;
8212
8213 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
8214 vec![ &fp ]);
8215 assert_eq!(sig_.issuers().count(), 0);
8216 Ok(())
8217}
8218
8219#[test]
8220fn issuer_default_v6() -> Result<()> {
8221 use crate::types::Curve;
8222
8223 let hash_algo = HashAlgorithm::SHA512;
8224 let sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8225 let key: crate::packet::key::SecretKey =
8226 crate::packet::key::Key6::generate_ecc(true, Curve::Ed25519)?.into();
8227 let mut keypair = key.into_keypair()?;
8228 let hash = hash_algo.context()?.for_signature(keypair.public().version());
8229
8230 // no issuer or issuer_fingerprint present, use default
8231 let sig_ = sig.sign_hash(&mut keypair, hash.clone())?;
8232
8233 assert_eq!(sig_.issuers().collect::<Vec<_>>(),
8234 Vec::<&KeyID>::new());
8235 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
8236 vec![ &keypair.public().fingerprint() ]);
8237
8238 let fp = Fingerprint::from_bytes(4, b"bbbbbbbbbbbbbbbbbbbb")?;
8239
8240 // issuer subpacket present, ignore, subpacket is not used with v6
8241 let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8242
8243 sig = sig.set_issuer(fp.clone().into())?;
8244 let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?;
8245
8246 assert_eq!(sig_.issuers().collect::<Vec<_>>(),
8247 vec![ &fp.clone().into() ]);
8248 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
8249 vec![ &keypair.public().fingerprint() ]);
8250
8251 // issuer_fingerprint subpacket present, do not override
8252 let mut sig = signature::SignatureBuilder::new(crate::types::SignatureType::Binary);
8253
8254 sig = sig.set_issuer_fingerprint(fp.clone())?;
8255 let sig_ = sig.clone().sign_hash(&mut keypair, hash.clone())?;
8256
8257 assert_eq!(sig_.issuer_fingerprints().collect::<Vec<_>>(),
8258 vec![ &fp ]);
8259 assert_eq!(sig_.issuers().count(), 0);
8260 Ok(())
8261}