1const MAX_LEN: usize = 120;
16
17#[derive(Clone, PartialEq)]
30pub struct Signature {
31 data: [u8; MAX_LEN],
32 len: u8,
33}
34
35impl std::fmt::Display for Signature {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 self.as_hex_str(f)
38 }
39}
40
41impl std::fmt::Debug for Signature {
42 fn fmt(&self, mut f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f, "Signature(")?;
44 self.as_hex_str(&mut f)?;
45 write!(f, ")")
46 }
47}
48
49impl Signature {
50 pub fn as_hex_str<W>(&self, mut buf: W) -> Result<(), std::fmt::Error>
52 where
53 W: std::fmt::Write,
54 {
55 for b in self.as_ref() {
56 write!(&mut buf, "{b:02x}")?;
57 }
58 Ok(())
59 }
60}
61
62impl From<aws_lc_rs::signature::Signature> for Signature {
63 fn from(value: aws_lc_rs::signature::Signature) -> Self {
64 let sig = value.as_ref();
65
66 Self::try_from(sig).unwrap()
71 }
72}
73
74impl TryFrom<&[u8]> for Signature {
75 type Error = &'static str;
76
77 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
78 if value.len() > MAX_LEN {
79 return Err("invalid signature: too long");
80 }
81
82 let mut data = [0; MAX_LEN];
83
84 let sig = value;
85 let dst = &mut data[..sig.len()];
86 dst.clone_from_slice(sig);
87
88 let len = u8::try_from(sig.len()).expect("signature is too large");
89
90 Ok(Self { data, len })
91 }
92}
93
94impl AsRef<[u8]> for Signature {
95 fn as_ref(&self) -> &[u8] {
96 &self.data[..self.len as usize]
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use crate::{keys::PrivateKey, signer::Signer};
103
104 use proptest::prelude::*;
105
106 proptest! {
107 #[test]
108 fn prop_repr(
109 payload in prop::collection::vec(any::<u8>(), 64),
110 ) {
111 let key = PrivateKey::new();
112 let sig = key.sign(&payload);
113
114 let mut hex = String::new();
115 sig.as_hex_str(&mut hex).unwrap();
116
117 let got = format!("{sig:?}");
119 assert_eq!(got, format!("Signature({hex})"));
120
121 assert_eq!(sig.to_string(), hex);
123 }
124 }
125}