use crate::RsaPublicKey;
use alloc::boxed::Box;
use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};
use signature::SignatureEncoding;
#[cfg(feature = "serde")]
use serdect::serde::{Deserialize, Serialize, de};
#[cfg(feature = "encoding")]
use spki::{
SignatureBitStringEncoding,
der::{
Result as DerResult,
asn1::{BitString, BitStringRef},
},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Signature {
pub(super) inner: Box<[u8]>,
}
impl Signature {
pub const MAX_LEN: usize = RsaPublicKey::MAX_SIZE.div_ceil(8);
pub fn from_bytes_with_max_len(bytes: &[u8], max_len: usize) -> signature::Result<Self> {
if bytes.len() > max_len {
return Err(signature::Error::new());
}
Ok(Self {
inner: bytes.into(),
})
}
}
impl SignatureEncoding for Signature {
type Repr = Box<[u8]>;
}
#[cfg(feature = "encoding")]
impl SignatureBitStringEncoding for Signature {
fn to_bitstring(&self) -> DerResult<BitString> {
BitString::new(0, self.to_vec())
}
}
impl TryFrom<&[u8]> for Signature {
type Error = signature::Error;
fn try_from(bytes: &[u8]) -> signature::Result<Self> {
Self::from_bytes_with_max_len(bytes, Self::MAX_LEN)
}
}
#[cfg(feature = "encoding")]
impl TryFrom<BitStringRef<'_>> for Signature {
type Error = signature::Error;
fn try_from(bit_string: BitStringRef<'_>) -> signature::Result<Self> {
Self::try_from(bit_string.as_bytes().ok_or_else(signature::Error::new)?)
}
}
impl From<Signature> for Box<[u8]> {
fn from(signature: Signature) -> Box<[u8]> {
signature.inner
}
}
impl LowerHex for Signature {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
for byte in self.inner.iter() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl UpperHex for Signature {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
for byte in self.inner.iter() {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}
impl Display for Signature {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
write!(f, "{:X}", self)
}
}
#[cfg(feature = "serde")]
impl Serialize for Signature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serdect::slice::serialize_hex_lower_or_bin(&self.to_bytes(), serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Signature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut buffer = [0u8; Self::MAX_LEN];
serdect::slice::deserialize_hex_or_bin(&mut buffer, deserializer)?
.try_into()
.map_err(de::Error::custom)
}
}
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
fn test_serde() {
use super::*;
use serde_test::{Configure, Token, assert_tokens};
let signature = Signature {
inner: Box::new([0, 0, 0, 0, 0, 0, 0, 42]),
};
let tokens = [Token::Str("000000000000002a")];
assert_tokens(&signature.readable(), &tokens);
}
}