cmail_rpgp/packet/
padding.rs

1use std::io;
2
3use rand::{CryptoRng, RngCore};
4
5use crate::errors::Result;
6use crate::packet::PacketTrait;
7use crate::ser::Serialize;
8use crate::types::{Tag, Version};
9
10/// Padding Packet
11///
12/// <https://www.rfc-editor.org/rfc/rfc9580.html#name-padding-packet-type-id-21>
13#[derive(derive_more::Debug, Clone, PartialEq, Eq)]
14pub struct Padding {
15    packet_version: Version,
16    /// Random data.
17    #[debug("{}", hex::encode(data))]
18    data: Vec<u8>,
19}
20
21impl Padding {
22    /// Parses a `Padding` packet from the given slice.
23    pub fn from_slice(packet_version: Version, input: &[u8]) -> Result<Self> {
24        Ok(Padding {
25            packet_version,
26            data: input.to_vec(),
27        })
28    }
29
30    /// Create a new padding packet of `size` in bytes.
31    pub fn new<R: CryptoRng + RngCore>(mut rng: R, packet_version: Version, size: usize) -> Self {
32        let mut data = vec![0u8; size];
33        rng.fill_bytes(&mut data);
34        Padding {
35            packet_version,
36            data,
37        }
38    }
39
40    pub fn packet_version(&self) -> Version {
41        self.packet_version
42    }
43}
44
45impl Serialize for Padding {
46    fn to_writer<W: io::Write>(&self, writer: &mut W) -> Result<()> {
47        writer.write_all(&self.data)?;
48
49        Ok(())
50    }
51}
52
53impl PacketTrait for Padding {
54    fn packet_version(&self) -> Version {
55        self.packet_version
56    }
57
58    fn tag(&self) -> Tag {
59        Tag::Padding
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use rand::SeedableRng;
66    use rand_chacha::ChaCha20Rng;
67
68    use super::super::single;
69    use super::*;
70    use crate::packet::Packet;
71    use crate::types::PacketLength;
72
73    #[test]
74    fn test_padding_roundtrip() {
75        let packet_raw = hex::decode("d50ec5a293072991628147d72c8f86b7").expect("valid hex");
76        let (rest, (version, tag, plen)) = single::parser(&packet_raw).expect("parse");
77
78        let PacketLength::Fixed(len) = plen else {
79            panic!("invalid parse result");
80        };
81        assert_eq!(rest.len(), len);
82
83        let full_packet = single::body_parser(version, tag, &rest[..len]).expect("body parse");
84
85        let Packet::Padding(ref packet) = full_packet else {
86            panic!("invalid packet: {:?}", full_packet);
87        };
88        assert_eq!(
89            packet.data,
90            hex::decode("c5a293072991628147d72c8f86b7").expect("valid hex")
91        );
92
93        // encode
94        let encoded = full_packet.to_bytes().expect("encode");
95        assert_eq!(encoded, packet_raw);
96    }
97
98    #[test]
99    fn test_padding_new() {
100        let mut rng = ChaCha20Rng::seed_from_u64(1);
101        let packet = Padding::new(&mut rng, Version::New, 20);
102        assert_eq!(packet.data.len(), 20);
103
104        let encoded = packet.to_bytes().expect("encode");
105        assert_eq!(encoded, packet.data);
106    }
107}