1use crate::errors::*;
2use sequoia_openpgp::cert::prelude::*;
3use sequoia_openpgp::parse::{PacketParser, Parse};
4use sequoia_openpgp::policy::NullPolicy;
5use sequoia_openpgp::{Cert, Fingerprint, KeyHandle, KeyID};
6
7#[derive(Debug, Clone)]
8pub struct Subkey {
9 pub fingerprint: sequoia_openpgp::Fingerprint,
10 pub is_primary: bool,
11 pub for_authentication: bool,
12 pub for_certification: bool,
13 pub for_signing: bool,
14 pub for_storage_encryption: bool,
15 pub for_transport_encryption: bool,
16}
17
18#[derive(Debug, Clone)]
19pub struct SigningKey {
20 pub fingerprint: sequoia_openpgp::Fingerprint,
21 pub cert: Cert,
22 pub uids: Vec<String>,
23 pub key_handles: Vec<(KeyHandle, Fingerprint)>,
24 pub subkeys: Vec<Subkey>,
25}
26
27impl SigningKey {
28 pub fn hex_fingerprint(&self) -> String {
29 format!("{:X}", self.fingerprint)
30 }
31
32 pub fn register_keyhandles(&mut self, fp: Fingerprint) {
33 let keyid = KeyID::from(&fp);
34 self.key_handles.push((KeyHandle::KeyID(keyid), fp.clone()));
35 self.key_handles
36 .push((KeyHandle::Fingerprint(fp.clone()), fp));
37 }
38}
39
40pub fn load(keyring: &[u8]) -> Result<Vec<SigningKey>> {
41 let ppr = PacketParser::from_bytes(&keyring)?;
42
43 let mut out = Vec::new();
44 for certo in CertParser::from(ppr) {
45 let cert = certo.context("Error reading pgp key")?;
46
47 let fingerprint = cert.fingerprint();
48
49 let mut signing_key = SigningKey {
50 fingerprint,
51 cert: cert.clone(),
52 uids: Vec::new(),
53 key_handles: Vec::new(),
54 subkeys: Vec::new(),
55 };
56
57 let p = &NullPolicy::new();
58 for key in cert.keys().with_policy(p, None) {
59 if key.for_signing() {
61 signing_key.register_keyhandles(key.fingerprint());
62 }
63
64 signing_key.subkeys.push(Subkey {
65 fingerprint: key.fingerprint(),
66 is_primary: key.primary(),
67 for_authentication: key.for_authentication(),
68 for_certification: key.for_certification(),
69 for_signing: key.for_signing(),
70 for_storage_encryption: key.for_storage_encryption(),
71 for_transport_encryption: key.for_transport_encryption(),
72 });
73 }
74
75 for ua in cert.userids() {
76 signing_key.uids.push(ua.userid().to_string());
77 }
78
79 out.push(signing_key);
80 }
81
82 Ok(out)
83}