sequoia_openpgp/packet/one_pass_sig/
v6.rs

1//! A version 6 one-pass signature packet.
2
3use std::convert::TryFrom;
4use std::fmt;
5use std::mem;
6
7#[cfg(test)]
8use quickcheck::{Arbitrary, Gen};
9
10use crate::{
11    Error,
12    Fingerprint,
13    HashAlgorithm,
14    Packet,
15    PublicKeyAlgorithm,
16    Result,
17    SignatureType,
18    packet::{
19        Signature,
20        OnePassSig,
21        one_pass_sig::{
22            OnePassSig3,
23        },
24    },
25};
26
27/// Holds a version 6 one-pass signature packet.
28///
29/// This holds a [version 6 One-Pass Signature Packet].  Normally, you won't
30/// directly work with this data structure, but with the [`OnePassSig`]
31/// enum, which is version agnostic.  An exception is when you need to
32/// do version-specific operations.
33///
34/// [version 6 One-Pass Signature Packet]: https://www.rfc-editor.org/rfc/rfc9580.html#name-one-pass-signature-packet-t
35/// [`OnePassSig`]: crate::packet::OnePassSig
36///
37/// # A note on equality
38///
39/// The `last` flag is represented as a `u8` and is compared
40/// literally, not semantically.
41#[derive(PartialEq, Eq, Hash, Clone)]
42pub struct OnePassSig6 {
43    pub(crate) common: OnePassSig3,
44    salt: Vec<u8>,
45    issuer: Fingerprint,
46}
47assert_send_and_sync!(OnePassSig6);
48
49impl TryFrom<OnePassSig> for OnePassSig6 {
50    type Error = anyhow::Error;
51
52    fn try_from(ops: OnePassSig) -> Result<Self> {
53        match ops {
54            OnePassSig::V6(ops) => Ok(ops),
55            ops => Err(
56                Error::InvalidArgument(
57                    format!(
58                        "Got a v{}, require a v6 one-pass signature",
59                        ops.version()))
60                    .into()),
61        }
62    }
63}
64
65impl fmt::Debug for OnePassSig6 {
66    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67        f.debug_struct("OnePassSig6")
68            .field("typ", &self.typ())
69            .field("hash_algo", &self.hash_algo())
70            .field("pk_algo", &self.pk_algo())
71            .field("salt", &crate::fmt::hex::encode(self.salt()))
72            .field("issuer", &self.issuer())
73            .field("last", &self.last())
74            .finish()
75    }
76}
77
78impl OnePassSig6 {
79    /// Returns a new One-Pass Signature packet.
80    pub fn new(typ: SignatureType, issuer: Fingerprint) ->  Self {
81        OnePassSig6 {
82            common: OnePassSig3::new(typ),
83            salt: vec![],
84            issuer,
85        }
86    }
87
88    /// Gets the signature type.
89    pub fn typ(&self) -> SignatureType {
90        self.common.typ()
91    }
92
93    /// Sets the signature type.
94    pub fn set_type(&mut self, t: SignatureType) -> SignatureType {
95        self.common.set_type(t)
96    }
97
98    /// Gets the public key algorithm.
99    pub fn pk_algo(&self) -> PublicKeyAlgorithm {
100        self.common.pk_algo()
101    }
102
103    /// Sets the public key algorithm.
104    pub fn set_pk_algo(&mut self, algo: PublicKeyAlgorithm) -> PublicKeyAlgorithm {
105        self.common.set_pk_algo(algo)
106    }
107
108    /// Gets the hash algorithm.
109    pub fn hash_algo(&self) -> HashAlgorithm {
110        self.common.hash_algo()
111    }
112
113    /// Sets the hash algorithm.
114    pub fn set_hash_algo(&mut self, algo: HashAlgorithm) -> HashAlgorithm {
115        self.common.set_hash_algo(algo)
116    }
117
118    /// Gets the salt.
119    pub fn salt(&self) -> &[u8] {
120        &self.salt
121    }
122
123    /// Sets the salt.
124    pub fn set_salt(&mut self, salt: Vec<u8>) -> Vec<u8> {
125        mem::replace(&mut self.salt, salt)
126    }
127
128    /// Gets the issuer.
129    pub fn issuer(&self) -> &Fingerprint {
130        &self.issuer
131    }
132
133    /// Sets the issuer.
134    pub fn set_issuer(&mut self, issuer: Fingerprint) -> Fingerprint {
135        mem::replace(&mut self.issuer, issuer)
136    }
137
138    /// Gets the last flag.
139    pub fn last(&self) -> bool {
140        self.common.last()
141    }
142
143    /// Sets the last flag.
144    pub fn set_last(&mut self, last: bool) -> bool {
145        self.common.set_last(last)
146    }
147
148    /// Gets the raw value of the last flag.
149    pub fn last_raw(&self) -> u8 {
150        self.common.last_raw()
151    }
152
153    /// Sets the raw value of the last flag.
154    pub fn set_last_raw(&mut self, last: u8) -> u8 {
155        self.common.set_last_raw(last)
156    }
157}
158
159impl From<OnePassSig6> for OnePassSig {
160    fn from(s: OnePassSig6) -> Self {
161        OnePassSig::V6(s)
162    }
163}
164
165impl From<OnePassSig6> for Packet {
166    fn from(p: OnePassSig6) -> Self {
167        OnePassSig::from(p).into()
168    }
169}
170
171impl<'a> std::convert::TryFrom<&'a Signature> for OnePassSig6 {
172    type Error = anyhow::Error;
173
174    fn try_from(s: &'a Signature) -> Result<Self> {
175        let s = if let Signature::V6(s) = s {
176            s
177        } else {
178            return Err(Error::InvalidArgument(format!(
179                "Can not derive a v6 OnePassSig from a v{} Signature",
180                s.version())).into());
181        };
182
183        let issuer = match s.issuer_fingerprints().next() {
184            Some(i) => i.clone(),
185            None =>
186                return Err(Error::InvalidArgument(
187                    "Signature has no issuer fingerprints".into()).into()),
188        };
189        let mut common = OnePassSig3::new(s.typ());
190        common.set_hash_algo(s.hash_algo());
191        common.set_pk_algo(s.pk_algo());
192        Ok(OnePassSig6 {
193            common,
194            salt: s.salt().to_vec(),
195            issuer,
196        })
197    }
198}
199
200#[cfg(test)]
201mod tests {
202    use super::*;
203    use crate::arbitrary_helper::arbitrary_bounded_vec;
204    use crate::parse::Parse;
205    use crate::serialize::MarshalInto;
206
207    impl Arbitrary for OnePassSig6 {
208        fn arbitrary(g: &mut Gen) -> Self {
209            let mut ops = OnePassSig6::new(SignatureType::arbitrary(g),
210                                           Fingerprint::arbitrary_v6(g));
211            ops.set_hash_algo(HashAlgorithm::arbitrary(g));
212            ops.set_pk_algo(PublicKeyAlgorithm::arbitrary(g));
213            ops.set_last_raw(u8::arbitrary(g));
214            ops.set_salt(arbitrary_bounded_vec(g, 256));
215            ops
216        }
217    }
218
219    quickcheck! {
220        fn roundtrip(p: OnePassSig6) -> bool {
221            let q = OnePassSig6::from_bytes(&p.to_vec().unwrap()).unwrap();
222            assert_eq!(p, q);
223            true
224        }
225    }
226}