sequoia_openpgp/packet/
one_pass_sig.rs

1//! One-pass signature packets.
2//!
3//! See [Section 5.4 of RFC 4880] for details.
4//!
5//!   [Section 5.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.4
6
7use std::fmt;
8
9#[cfg(test)]
10use quickcheck::{Arbitrary, Gen};
11
12use crate::Error;
13use crate::Packet;
14use crate::packet;
15use crate::packet::Signature;
16use crate::Result;
17use crate::KeyID;
18use crate::HashAlgorithm;
19use crate::PublicKeyAlgorithm;
20use crate::SignatureType;
21
22/// Holds a one-pass signature packet.
23///
24/// See [Section 5.4 of RFC 4880] for details.
25///
26///   [Section 5.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.4
27///
28/// # A note on equality
29///
30/// The `last` flag is represented as a `u8` and is compared
31/// literally, not semantically.
32// IMPORTANT: If you add fields to this struct, you need to explicitly
33// IMPORTANT: implement PartialEq, Eq, and Hash.
34#[derive(Clone, PartialEq, Eq, Hash)]
35pub struct OnePassSig3 {
36    /// CTB packet header fields.
37    pub(crate) common: packet::Common,
38    /// Type of the signature.
39    typ: SignatureType,
40    /// Hash algorithm used to compute the signature.
41    hash_algo: HashAlgorithm,
42    /// Public key algorithm of this signature.
43    pk_algo: PublicKeyAlgorithm,
44    /// Key ID of the signing key.
45    issuer: KeyID,
46    /// A one-octet number holding a flag showing whether the signature
47    /// is nested.
48    last: u8,
49}
50assert_send_and_sync!(OnePassSig3);
51
52impl fmt::Debug for OnePassSig3 {
53    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54        f.debug_struct("OnePassSig3")
55            .field("typ", &self.typ)
56            .field("hash_algo", &self.hash_algo)
57            .field("pk_algo", &self.pk_algo)
58            .field("issuer", &self.issuer)
59            .field("last", &self.last)
60            .finish()
61    }
62}
63
64impl OnePassSig3 {
65    /// Returns a new One-Pass Signature packet.
66    pub fn new(typ: SignatureType) ->  Self {
67        OnePassSig3 {
68            common: Default::default(),
69            typ,
70            hash_algo: HashAlgorithm::Unknown(0),
71            pk_algo: PublicKeyAlgorithm::Unknown(0),
72            issuer: KeyID::new(0),
73            last: 1,
74        }
75    }
76
77    /// Gets the signature type.
78    pub fn typ(&self) -> SignatureType {
79        self.typ
80    }
81
82    /// Sets the signature type.
83    pub fn set_type(&mut self, t: SignatureType) -> SignatureType {
84        ::std::mem::replace(&mut self.typ, t)
85    }
86
87    /// Gets the public key algorithm.
88    pub fn pk_algo(&self) -> PublicKeyAlgorithm {
89        self.pk_algo
90    }
91
92    /// Sets the public key algorithm.
93    pub fn set_pk_algo(&mut self, algo: PublicKeyAlgorithm) -> PublicKeyAlgorithm {
94        ::std::mem::replace(&mut self.pk_algo, algo)
95    }
96
97    /// Gets the hash algorithm.
98    pub fn hash_algo(&self) -> HashAlgorithm {
99        self.hash_algo
100    }
101
102    /// Sets the hash algorithm.
103    pub fn set_hash_algo(&mut self, algo: HashAlgorithm) -> HashAlgorithm {
104        ::std::mem::replace(&mut self.hash_algo, algo)
105    }
106
107    /// Gets the issuer.
108    pub fn issuer(&self) -> &KeyID {
109        &self.issuer
110    }
111
112    /// Sets the issuer.
113    pub fn set_issuer(&mut self, issuer: KeyID) -> KeyID {
114        ::std::mem::replace(&mut self.issuer, issuer)
115    }
116
117    /// Gets the last flag.
118    pub fn last(&self) -> bool {
119        self.last > 0
120    }
121
122    /// Sets the last flag.
123    pub fn set_last(&mut self, last: bool) -> bool {
124        ::std::mem::replace(&mut self.last, if last { 1 } else { 0 }) > 0
125    }
126
127    /// Gets the raw value of the last flag.
128    pub fn last_raw(&self) -> u8 {
129        self.last
130    }
131
132    /// Sets the raw value of the last flag.
133    pub fn set_last_raw(&mut self, last: u8) -> u8 {
134        ::std::mem::replace(&mut self.last, last)
135    }
136}
137
138impl From<OnePassSig3> for super::OnePassSig {
139    fn from(s: OnePassSig3) -> Self {
140        super::OnePassSig::V3(s)
141    }
142}
143
144impl From<OnePassSig3> for Packet {
145    fn from(p: OnePassSig3) -> Self {
146        super::OnePassSig::from(p).into()
147    }
148}
149
150impl<'a> std::convert::TryFrom<&'a Signature> for OnePassSig3 {
151    type Error = anyhow::Error;
152
153    fn try_from(s: &'a Signature) -> Result<Self> {
154        let issuer = match s.issuers().next() {
155            Some(i) => i.clone(),
156            None =>
157                return Err(Error::InvalidArgument(
158                    "Signature has no issuer".into()).into()),
159        };
160
161        Ok(OnePassSig3 {
162            common: Default::default(),
163            typ: s.typ(),
164            hash_algo: s.hash_algo(),
165            pk_algo: s.pk_algo(),
166            issuer,
167            last: 0,
168        })
169    }
170}
171
172#[cfg(test)]
173impl Arbitrary for super::OnePassSig {
174    fn arbitrary(g: &mut Gen) -> Self {
175        OnePassSig3::arbitrary(g).into()
176    }
177}
178
179#[cfg(test)]
180impl Arbitrary for OnePassSig3 {
181    fn arbitrary(g: &mut Gen) -> Self {
182        let mut ops = OnePassSig3::new(SignatureType::arbitrary(g));
183        ops.set_hash_algo(HashAlgorithm::arbitrary(g));
184        ops.set_pk_algo(PublicKeyAlgorithm::arbitrary(g));
185        ops.set_issuer(KeyID::arbitrary(g));
186        ops.set_last_raw(u8::arbitrary(g));
187        ops
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194    use crate::parse::Parse;
195    use crate::serialize::MarshalInto;
196
197    quickcheck! {
198        fn roundtrip(p: OnePassSig3) -> bool {
199            let q = OnePassSig3::from_bytes(&p.to_vec().unwrap()).unwrap();
200            assert_eq!(p, q);
201            true
202        }
203    }
204}