Skip to main content

ds_rom/crypto/
rsa.rs

1use std::fmt::Display;
2
3use bytemuck::{Pod, Zeroable};
4use serde::{de::Visitor, Deserialize, Serialize};
5
6/// Represents an RSA signature.
7#[repr(C)]
8#[derive(Zeroable, Pod, Clone, Copy)]
9pub struct RsaSignature(pub [u8; 0x80]);
10
11impl Serialize for RsaSignature {
12    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
13    where
14        S: serde::Serializer,
15    {
16        serializer.serialize_bytes(&self.0)
17    }
18}
19
20impl<'de> Deserialize<'de> for RsaSignature {
21    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22    where
23        D: serde::Deserializer<'de>,
24    {
25        deserializer.deserialize_bytes(RsaSignatureBytesVisitor)
26    }
27}
28
29struct RsaSignatureBytesVisitor;
30
31impl<'de> Visitor<'de> for RsaSignatureBytesVisitor {
32    type Value = RsaSignature;
33
34    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
35        formatter.write_str("an array of 128 (0x80) bytes")
36    }
37
38    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
39    where
40        E: serde::de::Error,
41    {
42        if v.len() != 0x80 {
43            Err(serde::de::Error::custom("RSA signature must be 128 bytes"))
44        } else {
45            let mut buf = [0u8; 0x80];
46            buf.copy_from_slice(v);
47            Ok(RsaSignature(buf))
48        }
49    }
50}
51
52impl RsaSignature {
53    /// Returns a [`DisplayRsaSignature`] which implements [`Display`].
54    pub fn display(&self, indent: usize) -> DisplayRsaSignature<'_> {
55        DisplayRsaSignature { rsa_signature: self, indent }
56    }
57}
58
59/// Can be used to display values inside [`RsaSignature`].
60pub struct DisplayRsaSignature<'a> {
61    rsa_signature: &'a RsaSignature,
62    indent: usize,
63}
64
65impl Display for DisplayRsaSignature<'_> {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        let i = " ".repeat(self.indent);
68        let bytes = &self.rsa_signature.0;
69        for row in 0..8 {
70            write!(f, "{i}")?;
71            for col in 0..16 {
72                write!(f, "{:02x} ", bytes[row * 16 + col])?;
73            }
74            writeln!(f)?;
75        }
76        Ok(())
77    }
78}