1use crate::utils::{
2 codec::{CodecError, Decode, Encode},
3 codec_vec::CodecVec,
4};
5use p256::{
6 ecdsa::{Signature as EcdsaSignature, VerifyingKey, signature::Verifier},
7 pkcs8::DecodePublicKey,
8};
9use serde::{Deserialize, Serialize};
10use std::{
11 fmt::Display,
12 io::{Cursor, Read, Write},
13 marker::PhantomData,
14};
15use thiserror::Error;
16
17#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
19pub(crate) struct Signature<T> {
20 algorithm: SignatureAndHashAlgorithm,
21 signature: CodecVec<u16>,
22 inner: PhantomData<T>,
23}
24
25impl<T: std::fmt::Debug> std::fmt::Debug for Signature<T> {
26 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 f.debug_struct("Signature")
28 .field("algorithm", &self.algorithm)
29 .field("signature", &hex::encode(&self.signature))
30 .finish()
31 }
32}
33
34impl<T> Encode for Signature<T> {
35 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
36 self.algorithm.encode(&mut writer)?;
37 self.signature.encode(&mut writer)?;
38 Ok(())
39 }
40}
41
42impl<T> Decode for Signature<T> {
43 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
44 Ok(Self {
45 algorithm: SignatureAndHashAlgorithm::decode(&mut reader)?,
46 signature: CodecVec::decode(&mut reader)?,
47 inner: PhantomData,
48 })
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Error)]
53pub enum SignatureValidationError {
54 #[error("Hash algorithm {0} is not supported by the implementation")]
55 UnsupportedHashAlgorithm(HashAlgorithm),
56
57 #[error("Signature algorithm {0} is not supported by the implementation")]
58 UnsupportedSignatureAlgorithm(SignatureAlgorithm),
59
60 #[error("Key could not be parsed for the specified signature algorithm")]
61 MalformedKey,
62
63 #[error("Signature could not be parsed for the specified signature algorithm")]
64 MalformedSignature,
65
66 #[error("Signature verification failed")]
67 InvalidSignature,
68
69 #[error("Error decoding a value: {0}")]
70 CodecError(#[from] CodecError),
71}
72
73impl<T: Encode> Signature<T> {
74 pub fn validate(&self, val: &T, key: &[u8]) -> Result<(), SignatureValidationError> {
75 let mut data = Cursor::new(vec![]);
76 val.encode(&mut data)?;
77
78 match &self.algorithm.signature {
91 SignatureAlgorithm::Ecdsa => {
92 match &self.algorithm.hash {
93 HashAlgorithm::Sha256 => (),
94 alg => {
95 return Err(SignatureValidationError::UnsupportedHashAlgorithm(
96 alg.clone(),
97 ));
98 }
99 }
100
101 let verifying_key = VerifyingKey::from_public_key_der(key)
102 .map_err(|_| SignatureValidationError::MalformedKey)?;
103
104 let signature = EcdsaSignature::from_der(self.signature.as_ref())
105 .map_err(|_| SignatureValidationError::MalformedSignature)?;
106
107 verifying_key
108 .verify(&data.into_inner(), &signature)
109 .map_err(|_| SignatureValidationError::InvalidSignature)?;
110
111 Ok(())
112 }
113 alg => Err(SignatureValidationError::UnsupportedSignatureAlgorithm(
114 alg.clone(),
115 )),
116 }
117 }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
122pub(crate) struct SignatureAndHashAlgorithm {
123 pub hash: HashAlgorithm,
124 pub signature: SignatureAlgorithm,
125}
126
127impl Encode for SignatureAndHashAlgorithm {
128 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
129 self.hash.encode(&mut writer)?;
130 self.signature.encode(&mut writer)?;
131 Ok(())
132 }
133}
134
135impl Decode for SignatureAndHashAlgorithm {
136 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
137 Ok(Self {
138 hash: HashAlgorithm::decode(&mut reader)?,
139 signature: SignatureAlgorithm::decode(&mut reader)?,
140 })
141 }
142}
143
144#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
146pub enum HashAlgorithm {
147 None,
148 Md5,
149 Sha1,
150 Sha224,
151 Sha256,
152 Sha384,
153 Sha512,
154}
155
156impl Encode for HashAlgorithm {
157 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
158 let discriminant = match self {
159 HashAlgorithm::None => 0,
160 HashAlgorithm::Md5 => 1,
161 HashAlgorithm::Sha1 => 2,
162 HashAlgorithm::Sha224 => 3,
163 HashAlgorithm::Sha256 => 4,
164 HashAlgorithm::Sha384 => 5,
165 HashAlgorithm::Sha512 => 6,
166 };
167 Ok(writer.write_all(&[discriminant])?)
168 }
169}
170
171impl Decode for HashAlgorithm {
172 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
173 let mut buf = vec![0u8];
174 reader.read_exact(&mut buf)?;
175
176 match buf[0] {
177 0 => Ok(HashAlgorithm::None),
178 1 => Ok(HashAlgorithm::Md5),
179 2 => Ok(HashAlgorithm::Sha1),
180 3 => Ok(HashAlgorithm::Sha224),
181 4 => Ok(HashAlgorithm::Sha256),
182 5 => Ok(HashAlgorithm::Sha384),
183 6 => Ok(HashAlgorithm::Sha512),
184 x => Err(CodecError::UnknownVariant("HashAlgorithm", x as u64)),
185 }
186 }
187}
188
189impl Display for HashAlgorithm {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 match self {
192 HashAlgorithm::None => write!(f, "None"),
193 HashAlgorithm::Md5 => write!(f, "Md5"),
194 HashAlgorithm::Sha1 => write!(f, "Sha1"),
195 HashAlgorithm::Sha224 => write!(f, "Sha224"),
196 HashAlgorithm::Sha256 => write!(f, "Sha256"),
197 HashAlgorithm::Sha384 => write!(f, "Sha384"),
198 HashAlgorithm::Sha512 => write!(f, "Sha512"),
199 }
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
205pub enum SignatureAlgorithm {
206 Anonymous,
207 Rsa,
208 Dsa,
209 Ecdsa,
210}
211
212impl Encode for SignatureAlgorithm {
213 fn encode(&self, mut writer: impl Write) -> Result<(), CodecError> {
214 let discriminant = match self {
215 SignatureAlgorithm::Anonymous => 0,
216 SignatureAlgorithm::Rsa => 1,
217 SignatureAlgorithm::Dsa => 2,
218 SignatureAlgorithm::Ecdsa => 3,
219 };
220 Ok(writer.write_all(&[discriminant])?)
221 }
222}
223
224impl Decode for SignatureAlgorithm {
225 fn decode(mut reader: impl Read) -> Result<Self, CodecError> {
226 let mut buf = vec![0u8];
227 reader.read_exact(&mut buf)?;
228
229 match buf[0] {
230 0 => Ok(SignatureAlgorithm::Anonymous),
231 1 => Ok(SignatureAlgorithm::Rsa),
232 2 => Ok(SignatureAlgorithm::Dsa),
233 3 => Ok(SignatureAlgorithm::Ecdsa),
234 x => Err(CodecError::UnknownVariant("SignatureAlgorithm", x as u64)),
235 }
236 }
237}
238
239impl Display for SignatureAlgorithm {
240 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241 match self {
242 SignatureAlgorithm::Anonymous => write!(f, "Anonymous"),
243 SignatureAlgorithm::Rsa => write!(f, "Rsa"),
244 SignatureAlgorithm::Dsa => write!(f, "Dsa"),
245 SignatureAlgorithm::Ecdsa => write!(f, "Ecdsa"),
246 }
247 }
248}