Skip to main content

rsa/pkcs1v15/
signature.rs

1//! `RSASSA-PKCS1-v1_5` signatures.
2
3use alloc::boxed::Box;
4use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};
5use crypto_bigint::BoxedUint;
6use signature::SignatureEncoding;
7
8#[cfg(feature = "serde")]
9use serdect::serde::{de, Deserialize, Serialize};
10#[cfg(feature = "encoding")]
11use spki::{
12    der::{asn1::BitString, Result as DerResult},
13    SignatureBitStringEncoding,
14};
15
16/// `RSASSA-PKCS1-v1_5` signatures as described in [RFC8017 § 8.2].
17///
18/// [RFC8017 § 8.2]: https://datatracker.ietf.org/doc/html/rfc8017#section-8.2
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct Signature {
21    pub(super) inner: BoxedUint,
22}
23
24impl SignatureEncoding for Signature {
25    type Repr = Box<[u8]>;
26}
27
28#[cfg(feature = "encoding")]
29impl SignatureBitStringEncoding for Signature {
30    fn to_bitstring(&self) -> DerResult<BitString> {
31        BitString::new(0, self.to_vec())
32    }
33}
34
35impl TryFrom<&[u8]> for Signature {
36    type Error = signature::Error;
37
38    fn try_from(bytes: &[u8]) -> signature::Result<Self> {
39        // TODO(tarcieri): max length restriction? (#350)
40        let inner = BoxedUint::from_be_slice_vartime(bytes);
41        Ok(Self { inner })
42    }
43}
44
45impl From<Signature> for Box<[u8]> {
46    fn from(signature: Signature) -> Box<[u8]> {
47        signature.inner.to_be_bytes()
48    }
49}
50
51impl LowerHex for Signature {
52    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
53        for byte in self.to_bytes().iter() {
54            write!(f, "{:02x}", byte)?;
55        }
56        Ok(())
57    }
58}
59
60impl UpperHex for Signature {
61    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
62        for byte in self.to_bytes().iter() {
63            write!(f, "{:02X}", byte)?;
64        }
65        Ok(())
66    }
67}
68
69impl Display for Signature {
70    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
71        write!(f, "{:X}", self)
72    }
73}
74
75#[cfg(feature = "serde")]
76impl Serialize for Signature {
77    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
78    where
79        S: serdect::serde::Serializer,
80    {
81        serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer)
82    }
83}
84
85#[cfg(feature = "serde")]
86impl<'de> Deserialize<'de> for Signature {
87    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
88    where
89        D: serdect::serde::Deserializer<'de>,
90    {
91        serdect::slice::deserialize_hex_or_bin_vec(deserializer)?
92            .as_slice()
93            .try_into()
94            .map_err(de::Error::custom)
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    #[test]
101    #[cfg(feature = "serde")]
102    fn test_serde() {
103        use super::*;
104        use serde_test::{assert_tokens, Configure, Token};
105        let signature = Signature {
106            inner: BoxedUint::from(42u32),
107        };
108
109        let tokens = [Token::Str("000000000000002a")];
110        assert_tokens(&signature.readable(), &tokens);
111    }
112}