cmail_rpgp/packet/
mod_detection_code.rs

1use std::io;
2
3use crate::errors::Result;
4use crate::packet::PacketTrait;
5use crate::ser::Serialize;
6use crate::types::{Tag, Version};
7
8/// Modification Detection Code Packet
9/// <https://www.rfc-editor.org/rfc/rfc9580.html#version-one-seipd>
10///
11/// Also see <https://www.rfc-editor.org/rfc/rfc9580.html#name-terminology-changes>:
12///
13/// "Modification Detection Code" or "MDC" was originally described as a distinct packet
14/// (Packet Type ID 19), and its corresponding flag in the Features signature subpacket
15/// (Section 5.2.3.32) was known as "Modification Detection".
16/// It is now described as an intrinsic part of v1 SEIPD (Section 5.13.1), and the same
17/// corresponding flag is known as "Version 1 Symmetrically Encrypted and Integrity Protected
18/// Data packet".
19#[derive(derive_more::Debug, Clone, PartialEq, Eq)]
20pub struct ModDetectionCode {
21    packet_version: Version,
22    /// 20 byte SHA1 hash of the preceding plaintext data.
23    #[debug("{}", hex::encode(hash))]
24    hash: [u8; 20],
25}
26
27impl ModDetectionCode {
28    /// Parses a `ModDetectionCode` packet from the given slice.
29    pub fn from_slice(packet_version: Version, input: &[u8]) -> Result<Self> {
30        ensure_eq!(input.len(), 20, "invalid input len");
31
32        let mut hash = [0u8; 20];
33        hash.copy_from_slice(input);
34
35        Ok(ModDetectionCode {
36            packet_version,
37            hash,
38        })
39    }
40}
41
42impl Serialize for ModDetectionCode {
43    fn to_writer<W: io::Write>(&self, writer: &mut W) -> Result<()> {
44        writer.write_all(&self.hash[..])?;
45        Ok(())
46    }
47}
48
49impl PacketTrait for ModDetectionCode {
50    fn packet_version(&self) -> Version {
51        self.packet_version
52    }
53
54    fn tag(&self) -> Tag {
55        Tag::ModDetectionCode
56    }
57}