Skip to main content

luct_core/
signature.rs

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/// See RFC 5246 4.7
18#[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        // let _digest: Box<dyn DynDigest> = match &self.algorithm.hash {
79        //     HashAlgorithm::Sha224 => Box::new(Sha224::new()),
80        //     HashAlgorithm::Sha256 => Box::new(Sha256::new()),
81        //     HashAlgorithm::Sha384 => Box::new(Sha384::new()),
82        //     HashAlgorithm::Sha512 => Box::new(Sha512::new()),
83        //     alg => {
84        //         return Err(SignatureValidationError::UnsupportedHashAlgorithm(
85        //             alg.clone(),
86        //         ));
87        //     }
88        // };
89
90        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/// See RFC 5246 7.4.1.4.1
121#[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/// See RFC 5246 7.4.1.4.1
145#[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/// See RFC 5246 7.4.1.4.1
204#[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}