1use std::{
2 cmp::Ordering,
3 io::{BufRead, Read},
4};
5
6use bitfields::bitfield;
7use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
8use bytes::Bytes;
9use digest::DynDigest;
10use log::debug;
11use num_enum::{FromPrimitive, IntoPrimitive};
12
13use crate::{
14 crypto::{
15 aead::AeadAlgorithm,
16 hash::{HashAlgorithm, WriteHasher},
17 public_key::PublicKeyAlgorithm,
18 sym::SymmetricKeyAlgorithm,
19 },
20 errors::{bail, ensure, ensure_eq, unimplemented_err, unsupported_err, Result},
21 line_writer::LineBreak,
22 normalize_lines::NormalizedReader,
23 packet::{
24 signature::SignatureConfig, PacketHeader, PacketTrait, SignatureVersionSpecific, Subpacket,
25 SubpacketData,
26 },
27 parsing::BufParsing,
28 parsing_reader::BufReadParsing,
29 ser::Serialize,
30 types::{
31 self, CompressionAlgorithm, Duration, Fingerprint, KeyDetails, KeyId, KeyVersion,
32 PacketLength, SignatureBytes, Tag, Timestamp, VerifyingKey,
33 },
34};
35
36#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
65pub struct Signature {
66 packet_header: PacketHeader,
67 pub(crate) inner: InnerSignature,
68}
69
70#[derive(Clone, PartialEq, Eq, derive_more::Debug)]
71pub(crate) enum InnerSignature {
72 Known {
74 config: SignatureConfig,
75 #[debug("{}", hex::encode(signed_hash_value))]
76 signed_hash_value: [u8; 2],
77 signature: SignatureBytes,
78 },
79 Unknown {
80 version: SignatureVersion,
81 #[debug("{}", hex::encode(data))]
82 data: Bytes,
83 },
84}
85
86impl Signature {
87 #[allow(clippy::too_many_arguments)]
90 pub fn v2(
91 packet_header: PacketHeader,
92 typ: SignatureType,
93 pub_alg: PublicKeyAlgorithm,
94 hash_alg: HashAlgorithm,
95 created: Timestamp,
96 issuer_key_id: KeyId,
97 signed_hash_value: [u8; 2],
98 signature: SignatureBytes,
99 ) -> Self {
100 Signature {
101 packet_header,
102 inner: InnerSignature::Known {
103 config: SignatureConfig {
104 typ,
105 pub_alg,
106 hash_alg,
107 hashed_subpackets: vec![],
108 unhashed_subpackets: vec![],
109 version_specific: SignatureVersionSpecific::V2 {
110 created,
111 issuer_key_id,
112 },
113 },
114 signed_hash_value,
115 signature,
116 },
117 }
118 }
119
120 #[allow(clippy::too_many_arguments)]
123 pub fn v3(
124 packet_header: PacketHeader,
125 typ: SignatureType,
126 pub_alg: PublicKeyAlgorithm,
127 hash_alg: HashAlgorithm,
128 created: Timestamp,
129 issuer_key_id: KeyId,
130 signed_hash_value: [u8; 2],
131 signature: SignatureBytes,
132 ) -> Self {
133 Signature {
134 packet_header,
135 inner: InnerSignature::Known {
136 config: SignatureConfig {
137 typ,
138 pub_alg,
139 hash_alg,
140 hashed_subpackets: vec![],
141 unhashed_subpackets: vec![],
142 version_specific: SignatureVersionSpecific::V3 {
143 created,
144 issuer_key_id,
145 },
146 },
147 signed_hash_value,
148 signature,
149 },
150 }
151 }
152
153 #[allow(clippy::too_many_arguments)]
158 pub fn v4(
159 packet_header: PacketHeader,
160 typ: SignatureType,
161 pub_alg: PublicKeyAlgorithm,
162 hash_alg: HashAlgorithm,
163 signed_hash_value: [u8; 2],
164 signature: SignatureBytes,
165 hashed_subpackets: Vec<Subpacket>,
166 unhashed_subpackets: Vec<Subpacket>,
167 ) -> Self {
168 Signature {
169 packet_header,
170 inner: InnerSignature::Known {
171 config: SignatureConfig {
172 typ,
173 pub_alg,
174 hash_alg,
175 hashed_subpackets,
176 unhashed_subpackets,
177 version_specific: SignatureVersionSpecific::V4,
178 },
179 signed_hash_value,
180 signature,
181 },
182 }
183 }
184
185 #[allow(clippy::too_many_arguments)]
189 pub fn v6(
190 packet_header: PacketHeader,
191 typ: SignatureType,
192 pub_alg: PublicKeyAlgorithm,
193 hash_alg: HashAlgorithm,
194 signed_hash_value: [u8; 2],
195 signature: SignatureBytes,
196 hashed_subpackets: Vec<Subpacket>,
197 unhashed_subpackets: Vec<Subpacket>,
198 salt: Vec<u8>,
199 ) -> Self {
200 Signature {
201 packet_header,
202 inner: InnerSignature::Known {
203 config: SignatureConfig {
204 typ,
205 pub_alg,
206 hash_alg,
207 hashed_subpackets,
208 unhashed_subpackets,
209 version_specific: SignatureVersionSpecific::V6 { salt },
210 },
211 signed_hash_value,
212 signature,
213 },
214 }
215 }
216
217 pub fn unknown(packet_header: PacketHeader, version: SignatureVersion, data: Bytes) -> Self {
219 Self {
220 packet_header,
221 inner: InnerSignature::Unknown { version, data },
222 }
223 }
224
225 pub fn from_config(
226 config: SignatureConfig,
227 signed_hash_value: [u8; 2],
228 signature: SignatureBytes,
229 ) -> Result<Self> {
230 let len = match config.version() {
231 SignatureVersion::V2 | SignatureVersion::V3 => {
232 let mut sum = 1;
233 sum += config.write_len_v3();
234 sum += 2; sum += signature.write_len();
236 sum
237 }
238 SignatureVersion::V4 | SignatureVersion::V6 => {
239 let mut sum = 1;
240 sum += config.write_len_v4_v6();
241 sum += 2; if let SignatureVersionSpecific::V6 { ref salt } = config.version_specific {
243 sum += 1;
244 sum += salt.len();
245 }
246 sum += signature.write_len();
247 sum
248 }
249 SignatureVersion::V5 => {
250 unsupported_err!("crate V5 signature")
251 }
252 SignatureVersion::Other(version) => unsupported_err!("signature version {}", version),
253 };
254 let packet_header = PacketHeader::new_fixed(Tag::Signature, len.try_into()?);
255
256 Ok(Signature {
257 packet_header,
258 inner: InnerSignature::Known {
259 config,
260 signed_hash_value,
261 signature,
262 },
263 })
264 }
265
266 pub fn config(&self) -> Option<&SignatureConfig> {
268 match self.inner {
269 InnerSignature::Known { ref config, .. } => Some(config),
270 InnerSignature::Unknown { .. } => None,
271 }
272 }
273
274 pub fn unhashed_subpacket_push(&mut self, subpacket: Subpacket) -> Result<()> {
276 if let InnerSignature::Known { ref config, .. } = self.inner {
277 self.unhashed_subpacket_insert(config.unhashed_subpackets.len(), subpacket)
278 } else {
279 bail!("Unknown Signature type, can't add Subpacket");
280 }
281 }
282
283 pub fn unhashed_subpacket_insert(&mut self, index: usize, subpacket: Subpacket) -> Result<()> {
286 if let InnerSignature::Known { ref mut config, .. } = self.inner {
287 if let PacketLength::Fixed(packetlen) = self.packet_header.packet_length_mut() {
288 ensure!(
289 index <= config.unhashed_subpackets.len(),
291 "Index {} is larger than the unhashed subpacket area",
292 index
293 );
294
295 let len = u32::try_from(subpacket.write_len())?;
296
297 config.unhashed_subpackets.insert(index, subpacket);
298 *packetlen += len;
299 } else {
300 bail!(
301 "Unexpected PacketLength encoding {:?}, can't modify the unhashed area",
302 self.packet_header.packet_length()
303 );
304 }
305
306 Ok(())
307 } else {
308 bail!("Unknown Signature type, can't add Subpacket");
309 }
310 }
311
312 pub fn unhashed_subpacket_remove(&mut self, index: usize) -> Result<Subpacket> {
315 if let InnerSignature::Known { ref mut config, .. } = self.inner {
316 ensure!(
317 index < config.unhashed_subpackets.len(),
319 "Index {} is not contained in the unhashed subpacket area",
320 index
321 );
322
323 if let PacketLength::Fixed(packetlen) = self.packet_header.packet_length_mut() {
324 let sp = config.unhashed_subpackets.remove(index);
325 *packetlen -= u32::try_from(sp.write_len())?;
326 Ok(sp)
327 } else {
328 bail!(
329 "Unexpected PacketLength encoding {:?}, can't modify the unhashed area",
330 self.packet_header.packet_length()
331 );
332 }
333 } else {
334 bail!("Unknown Signature type, can't remove Subpacket");
335 }
336 }
337
338 pub fn unhashed_subpackets_sort_by<F>(&mut self, compare: F)
341 where
342 F: FnMut(&Subpacket, &Subpacket) -> Ordering,
343 {
344 if let InnerSignature::Known { ref mut config, .. } = self.inner {
345 config.unhashed_subpackets.sort_by(compare);
346 }
347 }
348
349 pub fn version(&self) -> SignatureVersion {
351 match self.inner {
352 InnerSignature::Known { ref config, .. } => config.version(),
353 InnerSignature::Unknown { version, .. } => version,
354 }
355 }
356
357 pub fn typ(&self) -> Option<SignatureType> {
359 self.config().map(|c| c.typ())
360 }
361
362 pub fn hash_alg(&self) -> Option<HashAlgorithm> {
364 self.config().map(|c| c.hash_alg)
365 }
366
367 pub fn signature(&self) -> Option<&SignatureBytes> {
369 match self.inner {
370 InnerSignature::Known { ref signature, .. } => Some(signature),
371 InnerSignature::Unknown { .. } => None,
372 }
373 }
374
375 pub fn signed_hash_value(&self) -> Option<[u8; 2]> {
376 match self.inner {
377 InnerSignature::Known {
378 signed_hash_value, ..
379 } => Some(signed_hash_value),
380 InnerSignature::Unknown { .. } => None,
381 }
382 }
383
384 fn match_identity(sig: &Signature, key: &impl KeyDetails) -> bool {
390 let issuer_key_ids = sig.issuer_key_id();
391 let issuer_fps = sig.issuer_fingerprint();
392
393 if issuer_key_ids.is_empty() && issuer_fps.is_empty() {
396 return true;
397 }
398
399 issuer_key_ids
401 .iter()
402 .any(|&key_id| key_id == &key.legacy_key_id())
403 || issuer_fps.iter().any(|&fp| fp == &key.fingerprint())
404 }
405
406 fn check_signature_key_version_alignment(
412 key: &impl KeyDetails,
413 config: &SignatureConfig,
414 ) -> Result<()> {
415 if key.version() == KeyVersion::V6 {
417 ensure_eq!(
418 config.version(),
419 SignatureVersion::V6,
420 "Non v6 signature by a v6 key is not allowed"
421 );
422 }
423
424 if config.version() == SignatureVersion::V6 {
425 ensure_eq!(
426 key.version(),
427 KeyVersion::V6,
428 "v6 signature by a non-v6 key is not allowed"
429 );
430 }
431
432 Ok(())
433 }
434
435 pub(crate) fn check_signature_hash_strength(config: &SignatureConfig) -> Result<()> {
438 if config.pub_alg.is_pqc() {
439 let Some(digest_size) = config.hash_alg.digest_size() else {
446 bail!("Illegal hash_alg setting {}", config.hash_alg);
447 };
448
449 ensure!(
450 digest_size * 8 >= 256,
451 "PQC signatures must use hash algorithms with digest size >= 256 bits, {} is insufficient",
452 config.hash_alg
453 );
454 }
455
456 Ok(())
457 }
458
459 pub fn verify<R>(&self, key: &impl VerifyingKey, data: R) -> Result<()>
461 where
462 R: Read,
463 {
464 let InnerSignature::Known {
465 ref config,
466 ref signed_hash_value,
467 ref signature,
468 } = self.inner
469 else {
470 unsupported_err!("signature version {:?}", self.version());
471 };
472
473 Self::check_signature_key_version_alignment(&key, config)?;
474 Self::check_signature_hash_strength(config)?;
475
476 ensure!(
477 Self::match_identity(self, key),
478 "verify: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
479 &key.legacy_key_id(),
480 );
481
482 let mut hasher = config.hash_alg.new_hasher()?;
483
484 if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
485 ensure_eq!(
489 config.hash_alg.salt_len(),
490 Some(salt.len()),
491 "Illegal salt length {} for a V6 Signature using {:?}",
492 salt.len(),
493 config.hash_alg
494 );
495
496 hasher.update(salt.as_ref())
497 }
498
499 if matches!(self.typ(), Some(SignatureType::Text)) {
500 let normalized = NormalizedReader::new(data, LineBreak::Crlf);
501
502 config.hash_data_to_sign(&mut hasher, normalized)?;
503 } else {
504 config.hash_data_to_sign(&mut hasher, data)?;
505 }
506 let len = config.hash_signature_data(&mut hasher)?;
507 hasher.update(&config.trailer(len)?);
508
509 let hash = &hasher.finalize()[..];
510
511 ensure_eq!(
522 signed_hash_value,
523 &hash[0..2],
524 "signature: invalid signed hash value"
525 );
526
527 key.verify(config.hash_alg, hash, signature)
528 }
529
530 pub fn verify_certification<V>(&self, key: &V, tag: Tag, id: &impl Serialize) -> Result<()>
532 where
533 V: VerifyingKey + Serialize,
534 {
535 self.verify_third_party_certification(&key, &key, tag, id)
536 }
537
538 pub fn verify_third_party_certification<V, K>(
540 &self,
541 signee: &K,
542 signer: &V,
543 tag: Tag,
544 id: &impl Serialize,
545 ) -> Result<()>
546 where
547 V: VerifyingKey + Serialize,
548 K: KeyDetails + Serialize,
549 {
550 let InnerSignature::Known {
551 ref config,
552 ref signed_hash_value,
553 ref signature,
554 } = self.inner
555 else {
556 unsupported_err!("signature version {:?}", self.version());
557 };
558 let key_id = signee.legacy_key_id();
559 debug!("verifying certification {key_id:?} {self:#?}");
560
561 Self::check_signature_key_version_alignment(&signer, config)?;
562 Self::check_signature_hash_strength(config)?;
563
564 ensure!(
565 Self::match_identity(self, signer),
566 "verify_certification: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
567 key_id,
568 );
569
570 let mut hasher = config.hash_alg.new_hasher()?;
571
572 if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
573 hasher.update(salt.as_ref())
574 }
575
576 {
578 serialize_for_hashing(signee, &mut hasher)?;
580 }
581
582 {
584 let packet_len = id.write_len();
585
586 match config.version() {
587 SignatureVersion::V2 | SignatureVersion::V3 => {
588 }
590 SignatureVersion::V4 | SignatureVersion::V6 => {
591 let prefix = match tag {
592 Tag::UserId => 0xB4,
593 Tag::UserAttribute => 0xD1,
594 _ => bail!("invalid tag for certification validation: {:?}", tag),
595 };
596
597 let mut prefix_buf = [prefix, 0u8, 0u8, 0u8, 0u8];
598 BigEndian::write_u32(&mut prefix_buf[1..], packet_len.try_into()?);
599
600 hasher.update(&prefix_buf);
602 }
603 SignatureVersion::V5 => {
604 bail!("v5 signature unsupported tpc")
605 }
606 SignatureVersion::Other(version) => {
607 bail!("unsupported signature version: {:?}", version)
608 }
609 }
610
611 id.to_writer(&mut WriteHasher(&mut hasher))?;
612 }
613
614 let len = config.hash_signature_data(&mut hasher)?;
615 hasher.update(&config.trailer(len)?);
616
617 let hash = &hasher.finalize()[..];
618 ensure_eq!(
619 signed_hash_value,
620 &hash[0..2],
621 "certification: invalid signed hash value"
622 );
623
624 signer.verify(config.hash_alg, hash, signature)
625 }
626
627 pub fn verify_subkey_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
633 where
634 V: VerifyingKey + Serialize,
635 K: KeyDetails + Serialize,
636 {
637 debug!("verifying subkey binding: {self:#?} - {signer:#?} - {signee:#?}",);
638
639 let InnerSignature::Known {
640 ref config,
641 ref signed_hash_value,
642 ref signature,
643 } = self.inner
644 else {
645 unsupported_err!("signature version {:?}", self.version());
646 };
647
648 Self::check_signature_key_version_alignment(&signer, config)?;
649 Self::check_signature_hash_strength(config)?;
650
651 let mut hasher = config.hash_alg.new_hasher()?;
652
653 if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
654 hasher.update(salt.as_ref())
655 }
656
657 serialize_for_hashing(signer, &mut hasher)?; serialize_for_hashing(signee, &mut hasher)?; let len = config.hash_signature_data(&mut hasher)?;
661 hasher.update(&config.trailer(len)?);
662
663 let hash = &hasher.finalize()[..];
664 ensure_eq!(
665 signed_hash_value,
666 &hash[0..2],
667 "subkey binding: invalid signed hash value"
668 );
669
670 signer.verify(config.hash_alg, hash, signature)
671 }
672
673 pub fn verify_primary_key_binding<V, K>(&self, signer: &V, signee: &K) -> Result<()>
679 where
680 V: VerifyingKey + Serialize,
681 K: KeyDetails + Serialize,
682 {
683 debug!("verifying primary key binding: {self:#?} - {signer:#?} - {signee:#?}");
684
685 let InnerSignature::Known {
686 ref config,
687 ref signed_hash_value,
688 ref signature,
689 } = self.inner
690 else {
691 unsupported_err!("signature version {:?}", self.version());
692 };
693
694 Self::check_signature_key_version_alignment(&signer, config)?;
695 Self::check_signature_hash_strength(config)?;
696
697 let mut hasher = config.hash_alg.new_hasher()?;
698
699 if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
700 hasher.update(salt.as_ref())
701 }
702
703 serialize_for_hashing(signee, &mut hasher)?; serialize_for_hashing(signer, &mut hasher)?; let len = config.hash_signature_data(&mut hasher)?;
707 hasher.update(&config.trailer(len)?);
708
709 let hash = &hasher.finalize()[..];
710 ensure_eq!(
711 signed_hash_value,
712 &hash[0..2],
713 "key binding: invalid signed hash value"
714 );
715
716 signer.verify(config.hash_alg, hash, signature)
717 }
718
719 pub fn verify_key<V>(&self, key: &V) -> Result<()>
721 where
722 V: VerifyingKey + Serialize,
723 {
724 self.verify_key_third_party(key, key)
725 }
726
727 pub fn verify_key_third_party<V, K>(&self, signee: &K, signer: &V) -> Result<()>
729 where
730 V: VerifyingKey + Serialize,
731 K: KeyDetails + Serialize,
732 {
733 debug!("verifying direct signature: {self:#?} - signer {signer:#?}, signee {signee:#?}");
734
735 let InnerSignature::Known {
736 ref config,
737 ref signed_hash_value,
738 ref signature,
739 } = self.inner
740 else {
741 unsupported_err!("signature version {:?}", self.version());
742 };
743 Self::check_signature_key_version_alignment(&signer, config)?;
744 Self::check_signature_hash_strength(config)?;
745
746 ensure!(
747 Self::match_identity(self, signer),
748 "verify_key: No matching issuer_key_id or issuer_fingerprint for Key ID: {:?}",
749 &signer.legacy_key_id(),
750 );
751
752 let mut hasher = config.hash_alg.new_hasher()?;
753
754 if let SignatureVersionSpecific::V6 { salt } = &config.version_specific {
755 hasher.update(salt.as_ref())
756 }
757
758 serialize_for_hashing(signee, &mut hasher)?;
759
760 let len = config.hash_signature_data(&mut hasher)?;
761 hasher.update(&config.trailer(len)?);
762
763 let hash = &hasher.finalize()[..];
764 ensure_eq!(
765 signed_hash_value,
766 &hash[0..2],
767 "key: invalid signed hash value"
768 );
769
770 signer.verify(config.hash_alg, hash, signature)
771 }
772
773 pub fn is_certification(&self) -> bool {
775 self.config()
776 .map(|c| c.is_certification())
777 .unwrap_or_default()
778 }
779
780 pub fn key_expiration_time(&self) -> Option<Duration> {
789 self.config().and_then(|h| {
790 h.hashed_subpackets().find_map(|p| match &p.data {
791 SubpacketData::KeyExpirationTime(d) => Some(*d),
792 _ => None,
793 })
794 })
795 }
796
797 pub fn signature_expiration_time(&self) -> Option<Duration> {
798 self.config().and_then(|h| {
799 h.hashed_subpackets().find_map(|p| match &p.data {
800 SubpacketData::SignatureExpirationTime(d) => Some(*d),
801 _ => None,
802 })
803 })
804 }
805
806 pub fn created(&self) -> Option<Timestamp> {
807 self.config().and_then(|c| c.created())
808 }
809
810 pub fn issuer_key_id(&self) -> Vec<&KeyId> {
811 self.config().map(|c| c.issuer_key_id()).unwrap_or_default()
812 }
813
814 pub fn issuer_fingerprint(&self) -> Vec<&Fingerprint> {
815 self.config()
816 .map(|c| c.issuer_fingerprint())
817 .unwrap_or_default()
818 }
819
820 pub fn preferred_symmetric_algs(&self) -> &[SymmetricKeyAlgorithm] {
821 self.config()
822 .and_then(|c| {
823 c.hashed_subpackets().find_map(|p| match &p.data {
824 SubpacketData::PreferredSymmetricAlgorithms(d) => Some(&d[..]),
825 _ => None,
826 })
827 })
828 .unwrap_or_else(|| &[][..])
829 }
830
831 pub fn preferred_aead_algs(&self) -> &[(SymmetricKeyAlgorithm, AeadAlgorithm)] {
832 self.config()
833 .and_then(|c| {
834 c.hashed_subpackets().find_map(|p| match &p.data {
835 SubpacketData::PreferredAeadAlgorithms(d) => Some(&d[..]),
836 _ => None,
837 })
838 })
839 .unwrap_or_else(|| &[][..])
840 }
841
842 pub fn preferred_hash_algs(&self) -> &[HashAlgorithm] {
843 self.config()
844 .and_then(|c| {
845 c.hashed_subpackets().find_map(|p| match &p.data {
846 SubpacketData::PreferredHashAlgorithms(d) => Some(&d[..]),
847 _ => None,
848 })
849 })
850 .unwrap_or_else(|| &[][..])
851 }
852
853 pub fn preferred_compression_algs(&self) -> &[CompressionAlgorithm] {
854 self.config()
855 .and_then(|c| {
856 c.hashed_subpackets().find_map(|p| match &p.data {
857 SubpacketData::PreferredCompressionAlgorithms(d) => Some(&d[..]),
858 _ => None,
859 })
860 })
861 .unwrap_or_else(|| &[][..])
862 }
863
864 pub fn key_server_prefs(&self) -> &[u8] {
865 self.config()
866 .and_then(|c| {
867 c.hashed_subpackets().find_map(|p| match &p.data {
868 SubpacketData::KeyServerPreferences(d) => Some(&d[..]),
869 _ => None,
870 })
871 })
872 .unwrap_or_else(|| &[][..])
873 }
874
875 pub fn key_flags(&self) -> KeyFlags {
876 self.config()
877 .and_then(|c| {
878 c.hashed_subpackets().find_map(|p| match &p.data {
879 SubpacketData::KeyFlags(flags) => Some(flags.clone()),
880 _ => None,
881 })
882 })
883 .unwrap_or_default()
884 }
885
886 pub fn features(&self) -> Option<&Features> {
887 self.config().and_then(|c| {
888 c.hashed_subpackets().find_map(|p| match &p.data {
889 SubpacketData::Features(feat) => Some(feat),
890 _ => None,
891 })
892 })
893 }
894
895 pub fn revocation_reason_code(&self) -> Option<&RevocationCode> {
896 self.config().and_then(|c| {
897 c.hashed_subpackets().find_map(|p| match &p.data {
898 SubpacketData::RevocationReason(code, _) => Some(code),
899 _ => None,
900 })
901 })
902 }
903
904 pub fn revocation_reason_string(&self) -> Option<&Bytes> {
905 self.config().and_then(|c| {
906 c.hashed_subpackets().find_map(|p| match &p.data {
907 SubpacketData::RevocationReason(_, reason) => Some(reason),
908 _ => None,
909 })
910 })
911 }
912
913 pub fn is_primary(&self) -> bool {
914 self.config()
915 .and_then(|c| {
916 c.hashed_subpackets().find_map(|p| match &p.data {
917 SubpacketData::IsPrimary(d) => Some(*d),
918 _ => None,
919 })
920 })
921 .unwrap_or(false)
922 }
923
924 pub fn is_revocable(&self) -> bool {
925 self.config()
926 .and_then(|c| {
927 c.hashed_subpackets().find_map(|p| match &p.data {
928 SubpacketData::Revocable(d) => Some(*d),
929 _ => None,
930 })
931 })
932 .unwrap_or(true)
933 }
934
935 pub fn embedded_signature(&self) -> Option<&Signature> {
936 if let Some(sub) = self.config().and_then(|c| {
941 c.hashed_subpackets().find_map(|p| match &p.data {
942 SubpacketData::EmbeddedSignature(d) => Some(&**d),
943 _ => None,
944 })
945 }) {
946 return Some(sub);
947 }
948 if let Some(sub) = self.config().and_then(|c| {
949 c.unhashed_subpackets().find_map(|p| match &p.data {
950 SubpacketData::EmbeddedSignature(d) => Some(&**d),
951 _ => None,
952 })
953 }) {
954 return Some(sub);
955 }
956
957 None
958 }
959
960 pub fn preferred_key_server(&self) -> Option<&str> {
961 self.config().and_then(|c| {
962 c.hashed_subpackets().find_map(|p| match &p.data {
963 SubpacketData::PreferredKeyServer(d) => Some(d.as_str()),
964 _ => None,
965 })
966 })
967 }
968
969 pub fn notations(&self) -> Vec<&Notation> {
970 self.config()
971 .map(|c| {
972 c.hashed_subpackets()
973 .filter_map(|p| match &p.data {
974 SubpacketData::Notation(d) => Some(d),
975 _ => None,
976 })
977 .collect::<Vec<_>>()
978 })
979 .unwrap_or_default()
980 }
981
982 pub fn revocation_key(&self) -> Option<&types::RevocationKey> {
983 self.config().and_then(|c| {
984 c.hashed_subpackets().find_map(|p| match &p.data {
985 SubpacketData::RevocationKey(d) => Some(d),
986 _ => None,
987 })
988 })
989 }
990
991 pub fn signers_userid(&self) -> Option<&Bytes> {
997 self.config().and_then(|c| {
998 c.hashed_subpackets().find_map(|p| match &p.data {
999 SubpacketData::SignersUserID(d) => Some(d),
1000 _ => None,
1001 })
1002 })
1003 }
1004
1005 pub fn policy_uri(&self) -> Option<&str> {
1006 self.config().and_then(|c| {
1007 c.hashed_subpackets().find_map(|p| match &p.data {
1008 SubpacketData::PolicyURI(d) => Some(d.as_ref()),
1009 _ => None,
1010 })
1011 })
1012 }
1013
1014 pub fn trust_signature(&self) -> Option<(u8, u8)> {
1015 self.config().and_then(|c| {
1016 c.hashed_subpackets().find_map(|p| match &p.data {
1017 SubpacketData::TrustSignature(depth, value) => Some((*depth, *value)),
1018 _ => None,
1019 })
1020 })
1021 }
1022
1023 pub fn regular_expression(&self) -> Option<&Bytes> {
1024 self.config().and_then(|c| {
1025 c.hashed_subpackets().find_map(|p| match &p.data {
1026 SubpacketData::RegularExpression(d) => Some(d),
1027 _ => None,
1028 })
1029 })
1030 }
1031
1032 pub fn exportable_certification(&self) -> bool {
1033 self.config()
1034 .and_then(|c| {
1035 c.hashed_subpackets().find_map(|p| match &p.data {
1036 SubpacketData::ExportableCertification(d) => Some(*d),
1037 _ => None,
1038 })
1039 })
1040 .unwrap_or(true)
1041 }
1042}
1043
1044#[derive(derive_more::Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, IntoPrimitive)]
1046#[repr(u8)]
1047pub enum SignatureVersion {
1048 V2 = 2,
1050 V3 = 3,
1051 V4 = 4,
1052 V5 = 5,
1053 V6 = 6,
1054
1055 #[num_enum(catch_all)]
1056 Other(#[debug("0x{:x}", _0)] u8),
1057}
1058
1059#[allow(clippy::derivable_impls)]
1060impl Default for SignatureVersion {
1061 fn default() -> Self {
1062 Self::V4
1063 }
1064}
1065
1066#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1078#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
1079#[repr(u8)]
1080pub enum SignatureType {
1081 Binary = 0x00,
1084 Text = 0x01,
1089 Standalone = 0x02,
1094 CertGeneric = 0x10,
1099 CertPersona = 0x11,
1103 CertCasual = 0x12,
1107 CertPositive = 0x13,
1115 SubkeyBinding = 0x18,
1124 KeyBinding = 0x19,
1130 Key = 0x1F,
1138 KeyRevocation = 0x20,
1144 SubkeyRevocation = 0x28,
1151 CertRevocation = 0x30,
1160 Timestamp = 0x40,
1164 ThirdParty = 0x50,
1173
1174 #[num_enum(catch_all)]
1175 Other(#[cfg_attr(test, proptest(strategy = "0x51u8.."))] u8),
1176}
1177
1178pub const CERTIFICATION_SIGNATURE_TYPES: &[SignatureType] = &[
1179 SignatureType::CertPositive,
1180 SignatureType::CertGeneric,
1181 SignatureType::CertCasual,
1182 SignatureType::CertPersona,
1183];
1184
1185#[derive(Clone, PartialEq, Eq, Debug)]
1196pub struct KeyFlags {
1197 known: KnownKeyFlags,
1199 rest: Option<Bytes>,
1201 original_len: usize,
1203}
1204
1205impl Default for KeyFlags {
1206 fn default() -> Self {
1207 Self {
1208 known: KnownKeyFlags::default(),
1209 rest: None,
1210 original_len: 1,
1211 }
1212 }
1213}
1214
1215impl KeyFlags {
1216 pub fn try_from_reader<B: BufRead>(mut reader: B) -> Result<Self> {
1218 let mut buf = reader.rest()?.freeze();
1219 let remaining = buf.len();
1220
1221 if remaining == 0 {
1222 return Ok(Self {
1223 known: KnownKeyFlags::default(),
1224 rest: None,
1225 original_len: remaining,
1226 });
1227 }
1228 if remaining == 1 {
1229 let known = KnownKeyFlags::from_bits(buf.read_u8()? as u16);
1230 return Ok(Self {
1231 known,
1232 rest: None,
1233 original_len: remaining,
1234 });
1235 }
1236 if remaining == 2 {
1237 let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1238 return Ok(Self {
1239 known,
1240 rest: None,
1241 original_len: remaining,
1242 });
1243 }
1244 let known = KnownKeyFlags::from_bits(buf.read_le_u16()?);
1245 let rest = Some(buf.rest());
1246 Ok(Self {
1247 known,
1248 rest,
1249 original_len: remaining,
1250 })
1251 }
1252
1253 pub fn set_certify(&mut self, val: bool) {
1254 self.known.set_certify(val);
1255 }
1256 pub fn set_encrypt_comms(&mut self, val: bool) {
1257 self.known.set_encrypt_comms(val);
1258 }
1259 pub fn set_encrypt_storage(&mut self, val: bool) {
1260 self.known.set_encrypt_storage(val);
1261 }
1262 pub fn set_sign(&mut self, val: bool) {
1263 self.known.set_sign(val);
1264 }
1265 pub fn set_shared(&mut self, val: bool) {
1266 self.known.set_shared(val);
1267 }
1268 pub fn set_authentication(&mut self, val: bool) {
1269 self.known.set_authentication(val);
1270 }
1271 pub fn set_group(&mut self, val: bool) {
1272 self.known.set_group(val);
1273 }
1274
1275 pub fn set_adsk(&mut self, val: bool) {
1276 self.known.set_adsk(val);
1277 }
1278
1279 pub fn set_timestamping(&mut self, val: bool) {
1280 self.known.set_timestamping(val);
1281 }
1282
1283 pub fn certify(&self) -> bool {
1284 self.known.certify()
1285 }
1286
1287 pub fn encrypt_comms(&self) -> bool {
1288 self.known.encrypt_comms()
1289 }
1290
1291 pub fn encrypt_storage(&self) -> bool {
1292 self.known.encrypt_storage()
1293 }
1294
1295 pub fn sign(&self) -> bool {
1296 self.known.sign()
1297 }
1298
1299 pub fn shared(&self) -> bool {
1300 self.known.shared()
1301 }
1302
1303 pub fn authentication(&self) -> bool {
1304 self.known.authentication()
1305 }
1306
1307 pub fn draft_decrypt_forwarded(&self) -> bool {
1311 self.known.draft_decrypt_forwarded()
1312 }
1313
1314 pub fn group(&self) -> bool {
1315 self.known.group()
1316 }
1317
1318 pub fn adsk(&self) -> bool {
1319 self.known.adsk()
1320 }
1321
1322 pub fn timestamping(&self) -> bool {
1323 self.known.timestamping()
1324 }
1325}
1326
1327impl Serialize for KeyFlags {
1328 fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1329 if self.original_len == 0 {
1330 return Ok(());
1331 }
1332
1333 let [a, b] = self.known.into_bits().to_le_bytes();
1334 writer.write_u8(a)?;
1335
1336 if self.original_len > 1 || b != 0 {
1337 writer.write_u8(b)?;
1338 }
1339
1340 if let Some(ref rest) = self.rest {
1341 writer.write_all(rest)?;
1342 }
1343 Ok(())
1344 }
1345
1346 fn write_len(&self) -> usize {
1347 if self.original_len == 0 {
1348 return 0;
1349 }
1350 let mut sum = 0;
1351 let [_, b] = self.known.into_bits().to_le_bytes();
1352 if self.original_len > 1 || b > 0 {
1353 sum += 2;
1354 } else {
1355 sum += 1;
1356 }
1357
1358 if let Some(ref rest) = self.rest {
1359 sum += rest.len();
1360 }
1361 sum
1362 }
1363}
1364
1365#[bitfield(u16, order = lsb)]
1369#[derive(PartialEq, Eq, Copy, Clone)]
1370pub struct KnownKeyFlags {
1371 #[bits(1)]
1372 certify: bool,
1373 #[bits(1)]
1374 sign: bool,
1375 #[bits(1)]
1376 encrypt_comms: bool,
1377 #[bits(1)]
1378 encrypt_storage: bool,
1379 #[bits(1)]
1380 shared: bool,
1381 #[bits(1)]
1382 authentication: bool,
1383 #[bits(1)]
1384 draft_decrypt_forwarded: bool,
1385 #[bits(1)]
1386 group: bool,
1387 #[bits(2)]
1388 _padding1: u8,
1389 #[bits(1)]
1390 adsk: bool,
1391 #[bits(1)]
1392 timestamping: bool,
1393 #[bits(4)]
1394 _padding2: u8,
1395}
1396
1397#[derive(Clone, PartialEq, Eq, Debug)]
1407pub struct Features {
1408 first: Option<KnownFeatures>,
1411
1412 rest: Vec<u8>,
1415}
1416
1417impl Default for Features {
1418 fn default() -> Self {
1419 Self {
1420 first: Some(KnownFeatures::default()),
1421 rest: vec![],
1422 }
1423 }
1424}
1425
1426impl From<&[u8]> for Features {
1427 fn from(value: &[u8]) -> Self {
1428 match value.len() {
1429 0 => Self {
1430 first: None,
1431 rest: vec![],
1432 },
1433 _ => Self {
1434 first: Some(KnownFeatures(value[0])),
1435 rest: value[1..].to_vec(),
1436 },
1437 }
1438 }
1439}
1440
1441impl From<&Features> for Vec<u8> {
1442 fn from(value: &Features) -> Self {
1443 let mut v = vec![];
1444 value.to_writer(&mut v).expect("vec");
1445 v
1446 }
1447}
1448
1449impl From<KnownFeatures> for Features {
1450 fn from(value: KnownFeatures) -> Self {
1451 Self {
1452 first: Some(value),
1453 rest: vec![],
1454 }
1455 }
1456}
1457
1458impl Features {
1459 pub fn new() -> Self {
1460 Self::default()
1461 }
1462
1463 pub fn seipd_v1(&self) -> bool {
1464 match self.first {
1465 Some(k) => k.seipd_v1(),
1466 None => false,
1467 }
1468 }
1469
1470 pub fn set_seipd_v1(&mut self, val: bool) {
1471 if self.first.is_none() {
1472 self.first = Some(KnownFeatures::default());
1473 }
1474
1475 if let Some(k) = self.first.as_mut() {
1477 k.set_seipd_v1(val);
1478 }
1479 }
1480
1481 pub fn seipd_v2(&self) -> bool {
1482 match self.first {
1483 Some(k) => k.seipd_v2(),
1484 None => false,
1485 }
1486 }
1487
1488 pub fn set_seipd_v2(&mut self, val: bool) {
1489 if self.first.is_none() {
1490 self.first = Some(KnownFeatures::default());
1491 }
1492
1493 if let Some(k) = self.first.as_mut() {
1495 k.set_seipd_v2(val);
1496 }
1497 }
1498}
1499
1500impl Serialize for Features {
1501 fn to_writer<W: std::io::Write>(&self, writer: &mut W) -> Result<()> {
1502 if let Some(k) = self.first {
1503 writer.write_u8(k.0)?;
1504 writer.write_all(&self.rest)?;
1505 }
1506
1507 Ok(())
1508 }
1509
1510 fn write_len(&self) -> usize {
1511 if self.first.is_none() {
1512 0
1513 } else {
1514 1 + self.rest.len()
1515 }
1516 }
1517}
1518
1519#[bitfield(u8)]
1523#[derive(PartialEq, Eq, Copy, Clone)]
1524pub struct KnownFeatures {
1525 #[bits(1)]
1527 seipd_v1: bool,
1528
1529 #[bits(1)]
1532 _libre_ocb: u8,
1533
1534 #[bits(1)]
1537 _libre_v5_keys: u8,
1538
1539 #[bits(1)]
1541 seipd_v2: bool,
1542
1543 #[bits(4)]
1544 _padding: u8,
1545}
1546
1547#[derive(Debug, PartialEq, Eq, Clone)]
1558pub struct Notation {
1559 pub readable: bool,
1560 pub name: Bytes,
1561 pub value: Bytes,
1562}
1563
1564#[derive(Debug, PartialEq, Eq, Copy, Clone, FromPrimitive, IntoPrimitive)]
1568#[repr(u8)]
1569pub enum RevocationCode {
1570 NoReason = 0,
1572 KeySuperseded = 1,
1574 KeyCompromised = 2,
1576 KeyRetired = 3,
1578 CertUserIdInvalid = 32,
1580
1581 Private100 = 100,
1583 Private101 = 101,
1584 Private102 = 102,
1585 Private103 = 103,
1586 Private104 = 104,
1587 Private105 = 105,
1588 Private106 = 106,
1589 Private107 = 107,
1590 Private108 = 108,
1591 Private109 = 109,
1592 Private110 = 110,
1593
1594 #[num_enum(catch_all)]
1596 Other(u8),
1597}
1598
1599impl PacketTrait for Signature {
1600 fn packet_header(&self) -> &PacketHeader {
1601 &self.packet_header
1602 }
1603}
1604
1605pub(super) fn serialize_for_hashing<K: KeyDetails + Serialize>(
1606 key: &K,
1607 hasher: &mut Box<dyn DynDigest + Send>,
1608) -> Result<()> {
1609 let key_len = key.write_len();
1610
1611 let mut writer = WriteHasher(hasher);
1612
1613 match key.version() {
1615 KeyVersion::V2 | KeyVersion::V3 | KeyVersion::V4 => {
1616 writer.write_u8(0x99)?;
1619 writer.write_u16::<BigEndian>(key_len.try_into()?)?;
1620 }
1621
1622 KeyVersion::V6 => {
1623 writer.write_u8(0x9b)?;
1629 writer.write_u32::<BigEndian>(key_len.try_into()?)?;
1630 }
1631
1632 v => unimplemented_err!("key version {:?}", v),
1633 }
1634
1635 key.to_writer(&mut writer)?;
1636
1637 Ok(())
1638}
1639
1640#[cfg(test)]
1641mod tests {
1642 use std::io::Cursor;
1643
1644 use bytes::BytesMut;
1645
1646 use super::*;
1647 use crate::packet::SubpacketType;
1648
1649 #[test]
1651 fn test_keyflags_crazy_versions() {
1652 for i in 0..1024 {
1653 println!("size {i}");
1654 let source = BytesMut::zeroed(i).freeze();
1656 let flags = KeyFlags::try_from_reader(&source[..]).unwrap();
1657 assert_eq!(&flags.to_bytes().unwrap(), &source);
1658 }
1659 }
1660
1661 #[test]
1662 fn test_keyflags_1_byte() {
1663 let flags: KeyFlags = Default::default();
1664 assert_eq!(flags.to_bytes().unwrap(), vec![0x00]);
1665
1666 let mut flags = KeyFlags::default();
1667 flags.set_certify(true);
1668 assert!(flags.certify());
1669 assert_eq!(flags.to_bytes().unwrap(), vec![0x01]);
1670
1671 let mut flags = KeyFlags::default();
1672 flags.set_sign(true);
1673 assert_eq!(flags.to_bytes().unwrap(), vec![0x02]);
1674
1675 let mut flags = KeyFlags::default();
1676 flags.set_encrypt_comms(true);
1677 assert_eq!(flags.to_bytes().unwrap(), vec![0x04]);
1678
1679 let mut flags = KeyFlags::default();
1680 flags.set_encrypt_storage(true);
1681 assert_eq!(flags.to_bytes().unwrap(), vec![0x08]);
1682
1683 let mut flags = KeyFlags::default();
1684 flags.set_shared(true);
1685 assert_eq!(flags.to_bytes().unwrap(), vec![0x10]);
1686
1687 let mut flags = KeyFlags::default();
1688 flags.set_authentication(true);
1689 assert_eq!(flags.to_bytes().unwrap(), vec![0x20]);
1690
1691 let mut flags = KeyFlags::default();
1692 flags.set_group(true);
1693 assert_eq!(flags.to_bytes().unwrap(), vec![0x80]);
1694
1695 let mut flags = KeyFlags::default();
1696 flags.set_certify(true);
1697 flags.set_sign(true);
1698 assert_eq!(flags.to_bytes().unwrap(), vec![0x03]);
1699 }
1700
1701 #[test]
1702 fn test_keyflags_2_bytes() {
1703 let mut flags: KeyFlags = Default::default();
1704 flags.set_adsk(true);
1705 assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x04]);
1706
1707 let mut flags: KeyFlags = Default::default();
1708 flags.set_timestamping(true);
1709 assert_eq!(flags.to_bytes().unwrap(), vec![0x00, 0x08]);
1710
1711 let mut flags: KeyFlags = Default::default();
1712 flags.set_timestamping(true);
1713 flags.set_certify(true);
1714 flags.set_sign(true);
1715
1716 assert_eq!(flags.to_bytes().unwrap(), vec![0x03, 0x08]);
1717 }
1718
1719 #[test]
1720 fn test_features() {
1721 use crate::packet::Features;
1722
1723 {
1725 let empty: Features = (&[][..]).into();
1726 assert_eq!(empty.seipd_v1(), false);
1727 assert_eq!(empty.seipd_v2(), false);
1728
1729 assert_eq!(empty.write_len(), 0);
1730 let mut out = vec![];
1731 empty.to_writer(&mut out).expect("write");
1732 assert!(out.is_empty());
1733 }
1734 {
1735 let seipdv1: Features = (&[0x01][..]).into();
1736 assert_eq!(seipdv1.seipd_v1(), true);
1737 assert_eq!(seipdv1.seipd_v2(), false);
1738
1739 assert_eq!(seipdv1.write_len(), 1);
1740 let mut out = vec![];
1741 seipdv1.to_writer(&mut out).expect("write");
1742 assert_eq!(out, vec![0x01]);
1743 }
1744 {
1745 let allbits: Features = (&[0xff][..]).into();
1746 assert_eq!(allbits.seipd_v1(), true);
1747 assert_eq!(allbits.seipd_v2(), true);
1748
1749 assert_eq!(allbits.write_len(), 1);
1750 let mut out = vec![];
1751 allbits.to_writer(&mut out).expect("write");
1752 assert_eq!(out, vec![0xff]);
1753 }
1754 {
1755 let three_bytes: Features = (&[0x09, 0xaa, 0xbb][..]).into();
1756 assert_eq!(three_bytes.seipd_v1(), true);
1757 assert_eq!(three_bytes.seipd_v2(), true);
1758
1759 assert_eq!(three_bytes.write_len(), 3);
1760 let mut out = vec![];
1761 three_bytes.to_writer(&mut out).expect("write");
1762 assert_eq!(out, vec![0x09, 0xaa, 0xbb]);
1763 }
1764
1765 {
1767 let mut empty: Features = (&[][..]).into();
1768 assert!(Vec::<u8>::from(&empty).is_empty());
1769
1770 empty.set_seipd_v1(true);
1771 assert_eq!(Vec::<u8>::from(&empty), vec![0x01]);
1772 }
1773 {
1774 let mut default = Features::default();
1775 assert_eq!(Vec::<u8>::from(&default), vec![0x00]);
1776
1777 default.set_seipd_v1(true);
1778 assert_eq!(Vec::<u8>::from(&default), vec![0x01]);
1779
1780 default.set_seipd_v2(true);
1781 assert_eq!(Vec::<u8>::from(&default), vec![0x09]);
1782 }
1783 {
1784 let mut allbits: Features = (&[0xff][..]).into();
1785
1786 allbits.set_seipd_v1(false);
1787 assert_eq!(Vec::<u8>::from(&allbits), vec![0xfe]);
1788
1789 allbits.set_seipd_v2(false);
1790 assert_eq!(Vec::<u8>::from(&allbits), vec![0xf6]);
1791 }
1792 {
1793 let mut three_bytes: Features = (&[0x00, 0xaa, 0xbb][..]).into();
1794 three_bytes.set_seipd_v2(true);
1795 assert_eq!(Vec::<u8>::from(&three_bytes), vec![0x08, 0xaa, 0xbb]);
1796 }
1797 }
1798
1799 #[test]
1800 fn test_critical() {
1801 use SubpacketType::*;
1802 let cases = [
1803 SignatureCreationTime,
1804 SignatureExpirationTime,
1805 ExportableCertification,
1806 TrustSignature,
1807 RegularExpression,
1808 Revocable,
1809 KeyExpirationTime,
1810 PreferredSymmetricAlgorithms,
1811 RevocationKey,
1812 IssuerKeyId,
1813 Notation,
1814 PreferredHashAlgorithms,
1815 PreferredCompressionAlgorithms,
1816 KeyServerPreferences,
1817 PreferredKeyServer,
1818 PrimaryUserId,
1819 PolicyURI,
1820 KeyFlags,
1821 SignersUserID,
1822 RevocationReason,
1823 Features,
1824 SignatureTarget,
1825 EmbeddedSignature,
1826 IssuerFingerprint,
1827 PreferredAead,
1828 Experimental(101),
1829 Other(95),
1830 ];
1831 for case in cases {
1832 assert_eq!(SubpacketType::from_u8(case.as_u8(false)), (case, false));
1833 assert_eq!(SubpacketType::from_u8(case.as_u8(true)), (case, true));
1834 }
1835 }
1836
1837 use proptest::prelude::*;
1838
1839 use crate::composed::DetachedSignature;
1840
1841 impl Arbitrary for KeyFlags {
1842 type Parameters = ();
1843 type Strategy = BoxedStrategy<Self>;
1844
1845 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
1846 proptest::collection::vec(0u8..255, 1..500)
1847 .prop_map(|v| KeyFlags::try_from_reader(&mut &v[..]).unwrap())
1848 .boxed()
1849 }
1850 }
1851
1852 #[test]
1853 fn unhashed_area_modification() {
1854 fn subpacket_type_list(sig: &Signature) -> Vec<SubpacketType> {
1855 sig.config()
1856 .unwrap()
1857 .unhashed_subpackets
1858 .iter()
1859 .map(Subpacket::typ)
1860 .collect()
1861 }
1862
1863 use crate::composed::Deserializable;
1864
1865 let mut sig = DetachedSignature::from_armor_single(Cursor::new(
1866 "-----BEGIN PGP SIGNATURE-----
1867
1868wpoEEBYIAEIFAmheZZEWIQT8Y2QNsPXIvVyHlK1LkdWvyoDDywIbAwIeAQQLCQgH
1869BhUOCgkMCAEWDScJAggCBwIJAQgBBwECGQEACgkQS5HVr8qAw8swhAD/RFBBueDN
1870ClWUWHgCj+FmHElqrUO4YVePdt2KRkniPJ4A/jtOCzD7vZJZs0yP4xQ78PEsUST0
1871pwsJtT3sJB2q5NoA
1872=XphF
1873-----END PGP SIGNATURE-----",
1874 ))
1875 .unwrap()
1876 .0
1877 .signature;
1878
1879 assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(154));
1880
1881 sig.unhashed_subpacket_push(
1882 Subpacket::regular(SubpacketData::Notation(Notation {
1883 readable: true,
1884 name: "foo".into(),
1885 value: "bar".into(),
1886 }))
1887 .unwrap(),
1888 )
1889 .unwrap();
1890 assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(170));
1891 assert_eq!(
1892 &subpacket_type_list(&sig),
1893 &[SubpacketType::IssuerKeyId, SubpacketType::Notation]
1894 );
1895
1896 sig.unhashed_subpacket_insert(
1897 0,
1898 Subpacket::regular(SubpacketData::Notation(Notation {
1899 readable: true,
1900 name: "hello".into(),
1901 value: "world".into(),
1902 }))
1903 .unwrap(),
1904 )
1905 .unwrap();
1906 assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
1907 assert_eq!(
1908 &subpacket_type_list(&sig),
1909 &[
1910 SubpacketType::Notation,
1911 SubpacketType::IssuerKeyId,
1912 SubpacketType::Notation
1913 ]
1914 );
1915
1916 sig.unhashed_subpackets_sort_by(|a, b| {
1917 a.typ()
1918 .as_u8(a.is_critical)
1919 .cmp(&b.typ().as_u8(b.is_critical))
1920 });
1921 assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(190));
1922 assert_eq!(
1923 &subpacket_type_list(&sig),
1924 &[
1925 SubpacketType::IssuerKeyId,
1926 SubpacketType::Notation,
1927 SubpacketType::Notation
1928 ]
1929 );
1930
1931 sig.unhashed_subpacket_remove(0).unwrap();
1932 assert_eq!(sig.packet_header.packet_length(), PacketLength::Fixed(180));
1933 assert_eq!(
1934 &subpacket_type_list(&sig),
1935 &[SubpacketType::Notation, SubpacketType::Notation]
1936 );
1937 }
1938
1939 proptest! {
1940 #[test]
1941 fn keyflags_write_len(flags: KeyFlags) {
1942 let mut buf = Vec::new();
1943 flags.to_writer(&mut buf).unwrap();
1944 prop_assert_eq!(buf.len(), flags.write_len());
1945 }
1946
1947 #[test]
1948 fn keyflags_packet_roundtrip(flags: KeyFlags) {
1949 let mut buf = Vec::new();
1950 flags.to_writer(&mut buf).unwrap();
1951 let new_flags = KeyFlags::try_from_reader(&mut &buf[..]).unwrap();
1952 prop_assert_eq!(flags, new_flags);
1953 }
1954 }
1955}