1use std::cell::RefCell;
2use std::time::{Duration, SystemTime, UNIX_EPOCH};
3
4use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
5use failure::Error;
6use nom::{rest, be_u16, be_u32, be_u64, be_u8};
7use nom::{ErrorKind, IResult};
8use nom::Err as NomErr;
9use num::BigUint;
10
11use types::*;
12use util::parse_time_subpacket;
13
14#[cfg_attr(rustfmt, rustfmt_skip)]
15named!(
16 v3_sig<SignaturePacket>,
17 do_parse!(
18 tag!(b"\x03") >>
19 tag!(b"\x05") >>
20 signature_type: be_u8 >>
21 creation_time: be_u32 >>
22 signer: be_u64 >>
23 pubkey_algo: be_u8 >>
24 hash_algo: be_u8 >>
25 payload_hash: take!(2) >>
26 signature: call!(rest) >>
27 (SignaturePacket {
28 sig_type: SignatureType::from(signature_type),
29 timestamp: Some(Duration::from_secs(u64::from(creation_time))),
30 signer: Some(signer),
31 pubkey_algo: PublicKeyAlgorithm::from(pubkey_algo),
32 hash_algo: HashAlgorithm::from(hash_algo),
33 hashed_subpackets: Vec::new(),
34 unhashed_subpackets: Vec::new(),
35 signature_contents: Vec::from(signature),
36 payload_hash: RefCell::new(Some([payload_hash[0], payload_hash[1]])),
37 })
38 )
39);
40
41fn subpacket_length(inp: &[u8]) -> IResult<&[u8], u32> {
42 let (remaining, first_octet) = match be_u8(inp) {
43 IResult::Done(remaining, first_octet) => (remaining, first_octet),
44 IResult::Error(e) => return IResult::Error(e),
45 IResult::Incomplete(i) => return IResult::Incomplete(i),
46 };
47
48 if first_octet < 192 {
49 IResult::Done(remaining, u32::from(first_octet))
50 } else if first_octet < 255 {
51 let (remaining, second_octet) = match be_u8(remaining) {
52 IResult::Done(remaining, second_octet) => (remaining, second_octet),
53 IResult::Error(e) => return IResult::Error(e),
54 IResult::Incomplete(i) => return IResult::Incomplete(i),
55 };
56
57 let length = ((u16::from(first_octet) - 192) << 8) + u16::from(second_octet) + 192;
58
59 IResult::Done(remaining, u32::from(length))
60 } else {
61 be_u32(remaining)
62 }
63}
64
65fn parse_keyid_subpacket<T>(mut inp: &[u8]) -> Result<u64, NomErr<T>> {
66 inp.read_u64::<BigEndian>()
67 .map_err(|_| NomErr::Code(ErrorKind::Custom(NomError::IntegerReadError as u32)))
68}
69
70fn parse_hash_algorithms(inp: &[u8]) -> Vec<HashAlgorithm> {
71 inp.into_iter()
72 .map(|val| HashAlgorithm::from(*val))
73 .collect::<Vec<_>>()
74}
75
76fn parse_bool(inp: &[u8]) -> bool {
77 inp[0] != 0
78}
79
80fn parse_subpacket(inp: &[u8]) -> IResult<&[u8], Subpacket> {
81 let (remaining, length) = match subpacket_length(inp) {
82 IResult::Done(remaining, length) => (remaining, length),
83 IResult::Error(e) => return IResult::Error(e),
84 IResult::Incomplete(i) => return IResult::Incomplete(i),
85 };
86
87 let (remaining, subpacket_type) = match be_u8(remaining) {
88 IResult::Done(remaining, subpacket_type) => (remaining, subpacket_type),
89 IResult::Error(e) => return IResult::Error(e),
90 IResult::Incomplete(i) => return IResult::Incomplete(i),
91 };
92
93 let (remaining, packet_contents) = match take!(remaining, length - 1) {
94 IResult::Done(remaining, contents) => (remaining, contents),
95 IResult::Error(e) => return IResult::Error(e),
96 IResult::Incomplete(i) => return IResult::Incomplete(i),
97 };
98
99 match SubpacketType::from(subpacket_type) {
100 SubpacketType::Reserved => IResult::Error(NomErr::Code(ErrorKind::Custom(
101 NomError::UseOfReservedValue as u32,
102 ))),
103 SubpacketType::SignatureCreationTime => parse_time_subpacket(packet_contents)
104 .map(|time| IResult::Done(remaining, Subpacket::SignatureCreationTime(time)))
105 .unwrap_or_else(IResult::Error),
106 SubpacketType::SignatureExpirationTime => parse_time_subpacket(packet_contents)
107 .map(|time| IResult::Done(remaining, Subpacket::SignatureExpirationTime(time)))
108 .unwrap_or_else(IResult::Error),
109 SubpacketType::ExportableCertification => IResult::Done(
110 remaining,
111 Subpacket::ExportableCertification(parse_bool(packet_contents))
112 ),
113 SubpacketType::Revocable => IResult::Done(
114 remaining,
115 Subpacket::Revocable(parse_bool(packet_contents))
116 ),
117 SubpacketType::KeyExpirationTime => parse_time_subpacket(packet_contents)
118 .map(|time| IResult::Done(remaining, Subpacket::KeyExpirationTime(time)))
119 .unwrap_or_else(IResult::Error),
120 SubpacketType::Issuer => parse_keyid_subpacket(packet_contents)
121 .map(|key_id| IResult::Done(remaining, Subpacket::Issuer(key_id)))
122 .unwrap_or_else(IResult::Error),
123 SubpacketType::PreferredHashAlgorithms => IResult::Done(
124 remaining,
125 Subpacket::PreferredHashAlgorithms(parse_hash_algorithms(packet_contents)),
126 ),
127 SubpacketType::PrimaryUserId => IResult::Done(
128 remaining,
129 Subpacket::PrimaryUserId(parse_bool(packet_contents)),
130 ),
131 _ => IResult::Done(remaining, Subpacket::Unknown(subpacket_type, Vec::from(packet_contents))),
132 }
133}
134
135named!(subpackets<Vec<Subpacket>>, many0!(parse_subpacket));
136
137fn find_timestamp(subpackets: &[Subpacket]) -> Option<Duration> {
138 for subpacket in subpackets {
139 if let Subpacket::SignatureCreationTime(out) = *subpacket {
140 return Some(out);
141 }
142 }
143
144 None
145}
146
147fn find_signer(subpackets: &[Subpacket]) -> Option<u64> {
148 for subpacket in subpackets {
149 if let Subpacket::Issuer(out) = *subpacket {
150 return Some(out);
151 }
152 }
153
154 None
155}
156
157#[cfg_attr(rustfmt, rustfmt_skip)]
158named!(
159 v4_sig<SignaturePacket>,
160 do_parse!(
161 tag!(b"\x04") >>
162 signature_type: be_u8 >>
163 pubkey_algo: be_u8 >>
164 hash_algo: be_u8 >>
165 hashed_subs: length_value!(be_u16, subpackets) >>
166 unhashed_subs: length_value!(be_u16, subpackets) >>
167 payload_hash: take!(2) >>
168 signature: call!(rest) >>
169 (SignaturePacket {
170 sig_type: SignatureType::from(signature_type),
171 timestamp: find_timestamp(&hashed_subs).or_else(|| find_timestamp(&unhashed_subs)),
172 signer: find_signer(&hashed_subs).or_else(|| find_signer(&unhashed_subs)),
173 pubkey_algo: PublicKeyAlgorithm::from(pubkey_algo),
174 hash_algo: HashAlgorithm::from(hash_algo),
175 hashed_subpackets: hashed_subs,
176 unhashed_subpackets: unhashed_subs,
177 signature_contents: Vec::from(signature),
178 payload_hash: RefCell::new(Some([payload_hash[0], payload_hash[1]])),
179 })
180 )
181);
182
183named!(signature<SignaturePacket>, alt!(v3_sig | v4_sig));
184
185#[derive(Clone, Debug)]
187pub struct SignaturePacket {
188 pub sig_type: SignatureType,
189 timestamp: Option<Duration>,
190 signer: Option<u64>,
191 pub pubkey_algo: PublicKeyAlgorithm,
192 pub hash_algo: HashAlgorithm,
193 pub hashed_subpackets: Vec<Subpacket>,
194 pub unhashed_subpackets: Vec<Subpacket>,
195 signature_contents: Vec<u8>,
196 payload_hash: RefCell<Option<[u8; 2]>>,
197}
198
199impl SignaturePacket {
200 pub fn new(
203 sig_type: SignatureType,
204 pubkey_algo: PublicKeyAlgorithm,
205 hash_algo: HashAlgorithm,
206 ) -> Result<SignaturePacket, Error> {
207 let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?;
208
209 Ok(SignaturePacket {
210 sig_type: sig_type,
211 timestamp: Some(timestamp),
212 signer: None,
213 pubkey_algo: pubkey_algo,
214 hash_algo: hash_algo,
215 hashed_subpackets: Vec::new(),
216 unhashed_subpackets: Vec::new(),
217 signature_contents: Vec::new(),
218 payload_hash: RefCell::new(None),
219 })
220 }
221
222 pub fn contents(&self) -> Result<Signature, Error> {
226 match self.pubkey_algo {
227 PublicKeyAlgorithm::Rsa
228 | PublicKeyAlgorithm::RsaEncryptOnly
229 | PublicKeyAlgorithm::RsaSignOnly => {
230 let (mut header_slice, mpi_slice) = self.signature_contents.split_at(2);
231 let header = header_slice.read_u16::<BigEndian>()?;
232 let header = (header as f64 / 8.0).ceil() as usize;
235
236 if mpi_slice.len() < header {
237 bail!(SignatureError::MalformedMpi);
238 }
239 let (mpi_slice, _) = mpi_slice.split_at(header);
240
241 let mpi = BigUint::from_bytes_be(mpi_slice);
242 Ok(Signature::Rsa(mpi))
243 }
244 PublicKeyAlgorithm::Dsa => {
245 let (mut header_r_slice, remaining) = self.signature_contents.split_at(2);
246 let header_r = header_r_slice.read_u16::<BigEndian>()?;
247 let header_r = (header_r as f64 / 8.0).ceil() as usize;
250
251 if remaining.len() < header_r {
252 bail!(SignatureError::MalformedMpi);
253 }
254
255 let (mpi_r_slice, remaining) = remaining.split_at(header_r);
256
257 let (mut header_s_slice, mpi_s_slice) = remaining.split_at(2);
258 let header_s = header_s_slice.read_u16::<BigEndian>()?;
259 let header_s = (header_s as f64 / 8.0).ceil() as usize;
260
261 if mpi_s_slice.len() < header_s {
262 bail!(SignatureError::MalformedMpi);
263 }
264
265 let mpi_r = BigUint::from_bytes_be(mpi_r_slice);
266 let mpi_s = BigUint::from_bytes_be(mpi_s_slice);
267
268 Ok(Signature::Dsa(mpi_r, mpi_s))
269 }
270 _ => Ok(Signature::Unknown(self.signature_contents.clone())),
271 }
272 }
273
274 pub fn set_contents(&mut self, sig: Signature) -> Result<(), Error> {
276 match sig {
277 Signature::Rsa(mpi) => {
278 let mut mpi_header = Vec::new();
279
280 mpi_header.write_u16::<BigEndian>(mpi.bits() as u16)?;
281 mpi_header.extend(&mpi.to_bytes_be());
282
283 self.signature_contents = mpi_header;
284 }
285 Signature::Dsa(r, s) => {
286 let mut mpis = Vec::new();
287
288 mpis.write_u16::<BigEndian>(r.bits() as u16)?;
289 mpis.extend(&r.to_bytes_be());
290
291 mpis.write_u16::<BigEndian>(s.bits() as u16)?;
292 mpis.extend(&s.to_bytes_be());
293
294 self.signature_contents = mpis;
295 }
296 Signature::Unknown(payload) => self.signature_contents = payload.clone(),
297 }
298
299 Ok(())
300 }
301
302 pub fn timestamp(&self) -> Option<Duration> {
304 find_timestamp(&self.hashed_subpackets)
305 .or_else(|| find_timestamp(&self.unhashed_subpackets))
306 .or(self.timestamp)
307 }
308
309 pub fn set_timestamp(&mut self, timestamp: Duration) {
311 self.hashed_subpackets.retain(|subpacket| {
312 if let Subpacket::SignatureCreationTime(_) = *subpacket {
313 false
314 } else {
315 true
316 }
317 });
318 self.unhashed_subpackets.retain(|subpacket| {
319 if let Subpacket::SignatureCreationTime(_) = *subpacket {
320 false
321 } else {
322 true
323 }
324 });
325
326 self.hashed_subpackets
327 .push(Subpacket::SignatureCreationTime(timestamp));
328 self.timestamp = Some(timestamp);
329 }
330
331 pub fn signer(&self) -> Option<u64> {
333 find_signer(&self.hashed_subpackets)
334 .or_else(|| find_signer(&self.unhashed_subpackets))
335 .or(self.signer)
336 }
337
338 pub fn set_signer(&mut self, signer: u64) {
340 self.hashed_subpackets.retain(|subpacket| {
341 if let Subpacket::Issuer(_) = *subpacket {
342 false
343 } else {
344 true
345 }
346 });
347 self.unhashed_subpackets.retain(|subpacket| {
348 if let Subpacket::Issuer(_) = *subpacket {
349 false
350 } else {
351 true
352 }
353 });
354
355 self.unhashed_subpackets.push(Subpacket::Issuer(signer));
356 self.signer = Some(signer);
357 }
358
359 pub fn preferred_hash_algorithms(&self) -> Option<Vec<HashAlgorithm>> {
361 for subpacket in &self.hashed_subpackets {
362 if let Subpacket::PreferredHashAlgorithms(ref algos) = *subpacket {
363 return Some(algos.clone());
364 }
365 }
366
367 for subpacket in &self.unhashed_subpackets {
368 if let Subpacket::PreferredHashAlgorithms(ref algos) = *subpacket {
369 return Some(algos.clone());
370 }
371 }
372
373 None
374 }
375
376 pub fn set_preferred_hash_algorithms<T: AsRef<[HashAlgorithm]>>(&mut self, algos: T, hashed: bool) {
379 self.hashed_subpackets.retain(|subpacket| {
380 if let Subpacket::PreferredHashAlgorithms(_) = *subpacket {
381 false
382 } else {
383 true
384 }
385 });
386 self.unhashed_subpackets.retain(|subpacket| {
387 if let Subpacket::PreferredHashAlgorithms(_) = *subpacket {
388 false
389 } else {
390 true
391 }
392 });
393
394 let algos = Subpacket::PreferredHashAlgorithms(Vec::from(algos.as_ref()));
395 if hashed {
396 self.hashed_subpackets.push(algos);
397 } else {
398 self.unhashed_subpackets.push(algos);
399 }
400 }
401
402 fn common_header(&self) -> Result<Vec<u8>, Error> {
403 let mut header = Vec::new();
404
405 header.push(4);
407 header.push(self.sig_type.into());
408 header.push(self.pubkey_algo.into());
409 header.push(self.hash_algo.into());
410
411 let mut hashed_subpackets = self.hashed_subpackets.clone();
417 match find_timestamp(&self.hashed_subpackets) {
418 Some(_) => {}
419 None => match self.timestamp {
420 Some(timestamp) => {
421 hashed_subpackets.push(Subpacket::SignatureCreationTime(timestamp))
422 }
423 None => bail!(SignatureError::Unusable {
424 reason: "no SignatureCreationTime".to_string(),
425 }),
426 },
427 }
428
429 let mut hashed_subpackets_bytes: Vec<u8> = Vec::new();
430 for packet in &hashed_subpackets {
431 let packet_bytes = packet.to_bytes()?;
432 hashed_subpackets_bytes.extend(&packet_bytes);
433 }
434 header.write_u16::<BigEndian>(hashed_subpackets_bytes.len() as u16)?;
437 header.extend(&hashed_subpackets_bytes);
438
439 Ok(header)
440 }
441
442 pub fn signable_payload<T: AsRef<[u8]>>(&self, payload: T) -> Result<Vec<u8>, Error> {
447 let mut signing_payload = Vec::from(payload.as_ref());
448
449 let common_header = self.common_header()?;
450 signing_payload.extend(&common_header);
451
452 let mut suffix = Vec::new();
459 suffix.push(0x04);
460 suffix.push(0xFF);
461 suffix.write_u32::<BigEndian>(common_header.len() as u32)?;
462 signing_payload.extend(&suffix);
463
464 let hash = self.hash_algo.hash(signing_payload)?;
465 if hash.len() >= 2 {
466 self.payload_hash.replace(Some([hash[0], hash[1]]));
467 }
468
469 Ok(hash)
470 }
471
472 pub fn header(&self) -> Result<Vec<u8>, Error> {
475 let mut header = self.common_header()?;
476
477 let mut unhashed_subpackets_bytes: Vec<u8> = Vec::new();
478 for packet in &self.unhashed_subpackets {
479 let packet_bytes = packet.to_bytes()?;
480 unhashed_subpackets_bytes.extend(&packet_bytes);
481 }
482 header.write_u16::<BigEndian>(unhashed_subpackets_bytes.len() as u16)?;
485 header.extend(&unhashed_subpackets_bytes);
486
487 match *self.payload_hash.borrow() {
488 Some(hash) => {
489 header.push(hash[0]);
490 header.push(hash[1]);
491 }
492 None => {
493 header.push(0);
494 header.push(0);
495 }
496 }
497
498 Ok(header)
499 }
500
501 pub fn to_bytes(&self) -> Result<Vec<u8>, Error> {
503 let mut out = self.header()?;
504 out.extend(&self.signature_contents);
505
506 Ok(out)
507 }
508
509 pub fn from_bytes(bytes: &[u8]) -> Result<SignaturePacket, Error> {
511 match signature(bytes) {
512 IResult::Done(_, sig) => Ok(sig),
513 IResult::Error(NomErr::Code(ErrorKind::Custom(e))) => {
514 let e = NomError::from(e);
515
516 bail!(SignatureError::InvalidFormat {
517 reason: format!("{:?}", e),
518 })
519 }
520 IResult::Error(e) => bail!(SignatureError::InvalidFormat {
521 reason: format!("{}", e),
522 }),
523 IResult::Incomplete(i) => bail!(SignatureError::InvalidFormat {
524 reason: format!("{:?}", i),
525 }),
526 }
527 }
528}
529
530#[derive(Clone, Copy, Debug, PartialEq, Eq)]
534#[repr(u8)]
535pub enum SignatureType {
536 BinaryDocument = 0x00,
537 TextDocument = 0x01,
538 Standalone = 0x02,
539 GenericCertification = 0x10,
540 PersonaCertification = 0x11,
541 CasualCertification = 0x12,
542 PositiveCertification = 0x13,
543 SubkeyBinding = 0x18,
544 PrimaryKeyBinding = 0x19,
545 DirectKey = 0x1F,
546 KeyRevocation = 0x20,
547 SubkeyRevocation = 0x28,
548 CertificationRevocation = 0x30,
549 Timestamp = 0x40,
550 ThirdPartyConfirmation = 0x50,
551 Unknown = 255,
552}
553
554impl From<u8> for SignatureType {
555 fn from(val: u8) -> SignatureType {
556 match val {
557 0x00 => SignatureType::BinaryDocument,
558 0x01 => SignatureType::TextDocument,
559 0x02 => SignatureType::Standalone,
560 0x10 => SignatureType::GenericCertification,
561 0x11 => SignatureType::PersonaCertification,
562 0x12 => SignatureType::CasualCertification,
563 0x13 => SignatureType::PositiveCertification,
564 0x18 => SignatureType::SubkeyBinding,
565 0x19 => SignatureType::PrimaryKeyBinding,
566 0x1F => SignatureType::DirectKey,
567 0x20 => SignatureType::KeyRevocation,
568 0x28 => SignatureType::SubkeyRevocation,
569 0x30 => SignatureType::CertificationRevocation,
570 0x40 => SignatureType::Timestamp,
571 0x50 => SignatureType::ThirdPartyConfirmation,
572 _ => SignatureType::Unknown,
573 }
574 }
575}
576
577impl From<SignatureType> for u8 {
578 fn from(val: SignatureType) -> u8 {
579 match val {
580 SignatureType::BinaryDocument => 0x00,
581 SignatureType::TextDocument => 0x01,
582 SignatureType::Standalone => 0x02,
583 SignatureType::GenericCertification => 0x10,
584 SignatureType::PersonaCertification => 0x11,
585 SignatureType::CasualCertification => 0x12,
586 SignatureType::PositiveCertification => 0x13,
587 SignatureType::SubkeyBinding => 0x18,
588 SignatureType::PrimaryKeyBinding => 0x19,
589 SignatureType::DirectKey => 0x1F,
590 SignatureType::KeyRevocation => 0x20,
591 SignatureType::SubkeyRevocation => 0x28,
592 SignatureType::CertificationRevocation => 0x30,
593 SignatureType::Timestamp => 0x40,
594 SignatureType::ThirdPartyConfirmation => 0x50,
595 SignatureType::Unknown => 0xFF,
596 }
597 }
598}
599
600#[derive(Clone, Debug)]
605pub enum Subpacket {
606 SignatureCreationTime(Duration),
607 SignatureExpirationTime(Duration),
608 ExportableCertification(bool),
609 TrustSignature,
610 RegularExpression,
611 Revocable(bool),
612 KeyExpirationTime(Duration),
613 PreferredSymmetricAlgorithms,
614 RevocationKey,
615 Issuer(u64),
616 NotationData,
617 PreferredHashAlgorithms(Vec<HashAlgorithm>),
618 PreferredCompressionAlgorithms,
619 KeyServerPreferences,
620 PreferredKeyServer,
621 PrimaryUserId(bool),
622 PolicyUri,
623 KeyFlags,
624 SignerUserId,
625 RevocationReason,
626 Features,
627 SignatureTarget,
628 EmbeddedSignature,
629 Unknown(u8, Vec<u8>),
630}
631
632impl Subpacket {
633 fn to_bytes(&self) -> Result<Vec<u8>, Error> {
634 let mut out: Vec<u8> = Vec::new();
635
636 match *self {
637 Subpacket::SignatureCreationTime(time) => {
638 out.push(SubpacketType::SignatureCreationTime as u8);
639 out.write_u32::<BigEndian>(time.as_secs() as u32)?;
640 }
641 Subpacket::SignatureExpirationTime(time) => {
642 out.push(SubpacketType::SignatureExpirationTime as u8);
643 out.write_u32::<BigEndian>(time.as_secs() as u32)?;
644 }
645 Subpacket::ExportableCertification(exportable) => {
646 out.push(SubpacketType::ExportableCertification as u8);
647 out.push(exportable as u8);
648 }
649 Subpacket::Revocable(revocable) => {
650 out.push(SubpacketType::Revocable as u8);
651 out.push(revocable as u8);
652 }
653 Subpacket::KeyExpirationTime(time) => {
654 out.push(SubpacketType::KeyExpirationTime as u8);
655 out.write_u32::<BigEndian>(time.as_secs() as u32)?;
656 }
657 Subpacket::Issuer(issuer) => {
658 out.push(SubpacketType::Issuer as u8);
659 out.write_u64::<BigEndian>(issuer)?;
660 }
661 Subpacket::PreferredHashAlgorithms(ref algos) => {
662 out.push(SubpacketType::PreferredHashAlgorithms as u8);
663 for algo in algos {
664 out.push(*algo as u8);
665 }
666 }
667 Subpacket::PrimaryUserId(primary) => {
668 out.push(SubpacketType::PrimaryUserId as u8);
669 out.push(primary as u8);
670 }
671 Subpacket::Unknown(tag, ref contents) => {
672 out.push(tag);
673 out.extend(contents);
674 }
675 _ => {}
676 }
677
678 let mut packet_len = if out.len() < 192 {
679 vec![out.len() as u8]
680 } else {
681 let mut packet_len = vec![255u8];
682 packet_len.write_u32::<BigEndian>(out.len() as u32)?;
683 packet_len
684 };
685
686 packet_len.extend(&out);
687 Ok(packet_len)
688 }
689}
690
691#[derive(Clone, Debug, PartialEq, Eq)]
696pub enum Signature {
697 Rsa(BigUint),
698 Dsa(BigUint, BigUint),
699 Unknown(Vec<u8>),
700}
701
702#[derive(Debug, Fail)]
706pub enum SignatureError {
707 #[fail(display = "Invalid signature format: {}", reason)]
708 InvalidFormat { reason: String },
709 #[fail(display = "Unusable signature: {}", reason)]
710 Unusable { reason: String },
711 #[fail(display = "Malformed MPI payload")]
712 MalformedMpi,
713}
714
715#[derive(Clone, Copy, Debug, PartialEq, Eq)]
716#[repr(u8)]
717enum SubpacketType {
718 SignatureCreationTime = 2,
719 SignatureExpirationTime = 3,
720 ExportableCertification = 4,
721 TrustSignature = 5,
722 RegularExpression = 6,
723 Revocable = 7,
724 KeyExpirationTime = 9,
725 PreferredSymmetricAlgorithms = 11,
726 RevocationKey = 12,
727 Issuer = 16,
728 NotationData = 20,
729 PreferredHashAlgorithms = 21,
730 PreferredCompressionAlgorithms = 22,
731 KeyServerPreferences = 23,
732 PreferredKeyServer = 24,
733 PrimaryUserId = 25,
734 PolicyUri = 26,
735 KeyFlags = 27,
736 SignerUserId = 28,
737 RevocationReason = 29,
738 Features = 30,
739 SignatureTarget = 31,
740 EmbeddedSignature = 32,
741 Reserved,
742 Unknown,
743}
744
745impl From<u8> for SubpacketType {
746 fn from(t: u8) -> SubpacketType {
747 match t {
748 0 | 1 | 8 | 13 | 14 | 15 | 17 | 18 | 19 => SubpacketType::Reserved,
749 2 => SubpacketType::SignatureCreationTime,
750 3 => SubpacketType::SignatureExpirationTime,
751 4 => SubpacketType::ExportableCertification,
752 5 => SubpacketType::TrustSignature,
753 6 => SubpacketType::RegularExpression,
754 7 => SubpacketType::Revocable,
755 9 => SubpacketType::KeyExpirationTime,
756 11 => SubpacketType::PreferredSymmetricAlgorithms,
757 12 => SubpacketType::RevocationKey,
758 16 => SubpacketType::Issuer,
759 20 => SubpacketType::NotationData,
760 21 => SubpacketType::PreferredHashAlgorithms,
761 22 => SubpacketType::PreferredCompressionAlgorithms,
762 23 => SubpacketType::KeyServerPreferences,
763 24 => SubpacketType::PreferredKeyServer,
764 25 => SubpacketType::PrimaryUserId,
765 26 => SubpacketType::PolicyUri,
766 27 => SubpacketType::KeyFlags,
767 28 => SubpacketType::SignerUserId,
768 29 => SubpacketType::RevocationReason,
769 30 => SubpacketType::Features,
770 31 => SubpacketType::SignatureTarget,
771 32 => SubpacketType::EmbeddedSignature,
772 _ => SubpacketType::Unknown,
773 }
774 }
775}