sequoia_openpgp/packet/one_pass_sig/
v3.rs

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