cmail_rpgp/types/
user.rs

1use std::io;
2
3use log::{debug, warn};
4
5use crate::errors::Result;
6use crate::packet::{write_packet, Signature, UserAttribute, UserId};
7use crate::ser::Serialize;
8use crate::types::{PublicKeyTrait, Tag};
9
10#[derive(Debug, PartialEq, Eq, Clone)]
11pub struct SignedUser {
12    pub id: UserId,
13    pub signatures: Vec<Signature>,
14}
15
16impl SignedUser {
17    pub fn new(id: UserId, signatures: Vec<Signature>) -> Self {
18        let signatures = signatures
19            .into_iter()
20            .filter(|sig| {
21                if !sig.is_certification() {
22                    warn!(
23                        "ignoring unexpected signature {:?} after User ID packet",
24                        sig.typ()
25                    );
26                    false
27                } else {
28                    true
29                }
30            })
31            .collect();
32
33        SignedUser { id, signatures }
34    }
35
36    /// Verify all signatures (for self-signatures). If signatures is empty, this fails.
37    pub fn verify(&self, key: &impl PublicKeyTrait) -> Result<()> {
38        debug!("verify signed user {:#?}", self);
39        ensure!(!self.signatures.is_empty(), "no signatures found");
40
41        for signature in &self.signatures {
42            signature.verify_certification(key, Tag::UserId, &self.id)?;
43        }
44
45        Ok(())
46    }
47
48    /// Verify all signatures (for third-party signatures). If signatures is empty, this fails.
49    pub fn verify_third_party(
50        &self,
51        signee: &impl PublicKeyTrait,
52        signer: &impl PublicKeyTrait,
53    ) -> Result<()> {
54        debug!("verify signed user {:#?} with signer {:#?}", self, signer);
55        ensure!(!self.signatures.is_empty(), "no signatures found");
56
57        for signature in &self.signatures {
58            signature.verify_third_party_certification(signee, signer, Tag::UserId, &self.id)?;
59        }
60
61        Ok(())
62    }
63
64    pub fn is_primary(&self) -> bool {
65        self.signatures.iter().any(Signature::is_primary)
66    }
67}
68
69impl Serialize for SignedUser {
70    fn to_writer<W: io::Write>(&self, writer: &mut W) -> Result<()> {
71        write_packet(writer, &self.id)?;
72        for sig in &self.signatures {
73            write_packet(writer, sig)?;
74        }
75
76        Ok(())
77    }
78}
79
80#[derive(Debug, PartialEq, Eq, Clone)]
81pub struct SignedUserAttribute {
82    pub attr: UserAttribute,
83    pub signatures: Vec<Signature>,
84}
85
86impl SignedUserAttribute {
87    pub fn new(attr: UserAttribute, signatures: Vec<Signature>) -> Self {
88        let signatures = signatures
89            .into_iter()
90            .filter(|sig| {
91                if !sig.is_certification() {
92                    warn!(
93                        "ignoring unexpected signature {:?} after User Attribute packet",
94                        sig.typ()
95                    );
96                    false
97                } else {
98                    true
99                }
100            })
101            .collect();
102
103        SignedUserAttribute { attr, signatures }
104    }
105
106    /// Verify all signatures (for self-signatures). If signatures is empty, this fails.
107    pub fn verify(&self, key: &impl PublicKeyTrait) -> Result<()> {
108        debug!("verify signed attribute {:?}", self);
109        ensure!(!self.signatures.is_empty(), "no signatures found");
110
111        for signature in &self.signatures {
112            signature.verify_certification(key, Tag::UserAttribute, &self.attr)?;
113        }
114
115        Ok(())
116    }
117
118    /// Verify all signatures (for third-party signatures). If signatures is empty, this fails.
119    pub fn verify_third_party(
120        &self,
121        signee: &impl PublicKeyTrait,
122        signer: &impl PublicKeyTrait,
123    ) -> Result<()> {
124        debug!(
125            "verify signed attribute {:#?} with signer {:#?}",
126            self, signer
127        );
128        ensure!(!self.signatures.is_empty(), "no signatures found");
129
130        for signature in &self.signatures {
131            signature.verify_third_party_certification(
132                signee,
133                signer,
134                Tag::UserAttribute,
135                &self.attr,
136            )?;
137        }
138
139        Ok(())
140    }
141}
142
143impl Serialize for SignedUserAttribute {
144    fn to_writer<W: io::Write>(&self, writer: &mut W) -> Result<()> {
145        write_packet(writer, &self.attr)?;
146        for sig in &self.signatures {
147            write_packet(writer, sig)?;
148        }
149
150        Ok(())
151    }
152}