1use crate::{
7 error::CryptoError,
8 hash::{BLAKE3_HASHER, DigestIdentifier, Hash as HashTrait},
9 keys::{DSA, PublicKey, SignatureIdentifier},
10 timestamp::TimeStamp,
11};
12
13use borsh::{BorshDeserialize, BorshSerialize};
14use serde::{Deserialize, Serialize};
15use std::hash::Hash;
16use subtle::ConstantTimeEq;
17
18#[derive(
20 Debug,
21 Clone,
22 Serialize,
23 Deserialize,
24 Eq,
25 BorshSerialize,
26 BorshDeserialize,
27 PartialEq,
28 Hash,
29 Ord,
30 PartialOrd,
31)]
32pub struct Signature {
33 pub signer: PublicKey,
35 pub timestamp: TimeStamp,
37 pub content_hash: DigestIdentifier,
39 pub value: SignatureIdentifier,
41}
42
43impl Signature {
44 pub fn new<T: BorshSerialize>(
49 content: &T,
50 signer: &dyn DSA,
51 ) -> Result<Self, CryptoError> {
52 let timestamp = TimeStamp::now();
53
54 let signing_payload = (content, ×tamp);
57 let payload_bytes = borsh::to_vec(&signing_payload)
58 .map_err(|e| CryptoError::SerializationError(e.to_string()))?;
59
60 let content_hash = BLAKE3_HASHER.hash(&payload_bytes);
62
63 let signature_bytes =
65 signer.sign(content_hash.hash_bytes()).map_err(|_| {
66 CryptoError::SigningError(
67 "Failed to create signature".to_string(),
68 )
69 })?;
70
71 let public_key =
73 PublicKey::new(signer.algorithm(), signer.public_key_bytes())?;
74
75 Ok(Self {
76 signer: public_key,
77 timestamp,
78 content_hash,
79 value: signature_bytes,
80 })
81 }
82
83 pub fn verify<T: BorshSerialize>(
85 &self,
86 content: &T,
87 ) -> Result<(), CryptoError> {
88 let signing_payload = (content, &self.timestamp);
90 let payload_bytes = borsh::to_vec(&signing_payload)
91 .map_err(|e| CryptoError::SerializationError(e.to_string()))?;
92
93 let computed_hash = BLAKE3_HASHER.hash(&payload_bytes);
95
96 let hash_matches = computed_hash
98 .hash_bytes()
99 .ct_eq(self.content_hash.hash_bytes());
100 if hash_matches.unwrap_u8() != 1 {
101 return Err(CryptoError::HashError(
102 "Content hash mismatch".to_string(),
103 ));
104 }
105
106 self.signer
108 .verify(self.content_hash.hash_bytes(), &self.value)
109 }
110}
111
112#[derive(
114 Debug,
115 Clone,
116 Serialize,
117 Deserialize,
118 Eq,
119 PartialEq,
120 BorshSerialize,
121 BorshDeserialize,
122 Hash,
123)]
124pub struct Signed<T>
125where
126 T: BorshSerialize + BorshDeserialize + Clone,
127{
128 content: T,
130 signature: Signature,
132}
133
134impl<T: BorshSerialize + BorshDeserialize + Clone> Signed<T> {
135 pub fn new(content: T, signer: &dyn DSA) -> Result<Self, CryptoError> {
137 let signature = Signature::new(&content, signer)?;
138 Ok(Self { content, signature })
139 }
140
141 pub const fn from_parts(content: T, signature: Signature) -> Self {
143 Self { content, signature }
144 }
145
146 pub fn verify(&self) -> Result<(), CryptoError> {
148 self.signature.verify(&self.content)
149 }
150
151 pub const fn signature(&self) -> &Signature {
153 &self.signature
154 }
155
156 pub const fn content(&self) -> &T {
158 &self.content
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165 use crate::keys::Ed25519Signer;
166
167 #[derive(
168 Debug,
169 Clone,
170 PartialEq,
171 Eq,
172 BorshSerialize,
173 BorshDeserialize,
174 Serialize,
175 Deserialize,
176 )]
177 struct TestData {
178 value: String,
179 number: u64,
180 }
181
182 #[test]
183 fn test_signature_creation_and_verification() {
184 let signer = Ed25519Signer::generate().unwrap();
185 let data = TestData {
186 value: "test message".to_string(),
187 number: 42,
188 };
189
190 let signature = Signature::new(&data, &signer).unwrap();
191 assert!(signature.verify(&data).is_ok());
192 }
193
194 #[test]
195 fn test_signature_fails_with_wrong_content() {
196 let signer = Ed25519Signer::generate().unwrap();
197 let data1 = TestData {
198 value: "message 1".to_string(),
199 number: 1,
200 };
201 let data2 = TestData {
202 value: "message 2".to_string(),
203 number: 2,
204 };
205
206 let signature = Signature::new(&data1, &signer).unwrap();
207 assert!(signature.verify(&data2).is_err());
208 }
209
210 #[test]
211 fn test_signed_creation() {
212 let signer = Ed25519Signer::generate().unwrap();
213 let data = TestData {
214 value: "signed data".to_string(),
215 number: 123,
216 };
217
218 let signed = Signed::new(data.clone(), &signer).unwrap();
219 assert_eq!(signed.content, data);
220 assert!(signed.verify().is_ok());
221 }
222
223 #[test]
224 fn test_signed_verification() {
225 let signer = Ed25519Signer::generate().unwrap();
226 let data = TestData {
227 value: "verify me".to_string(),
228 number: 999,
229 };
230
231 let signed = Signed::new(data, &signer).unwrap();
232 assert!(signed.verify().is_ok());
233 }
234
235 #[test]
236 fn test_signed_from_parts() {
237 let signer = Ed25519Signer::generate().unwrap();
238 let data = TestData {
239 value: "test".to_string(),
240 number: 1,
241 };
242
243 let signature = Signature::new(&data, &signer).unwrap();
244 let signed = Signed::from_parts(data.clone(), signature);
245
246 assert_eq!(signed.content().value, "test");
247 assert!(signed.verify().is_ok());
248 }
249
250 #[test]
251 fn test_signer_accessor() {
252 let signer = Ed25519Signer::generate().unwrap();
253 let data = TestData {
254 value: "test".to_string(),
255 number: 1,
256 };
257
258 let signed = Signed::new(data, &signer).unwrap();
259 let public_key = signed.signature().signer.clone();
260
261 let expected_pubkey = PublicKey::new(
263 crate::keys::DSAlgorithm::Ed25519,
264 signer.public_key_bytes(),
265 )
266 .unwrap();
267
268 assert_eq!(public_key, expected_pubkey);
269 }
270
271 #[test]
272 fn test_timestamp_is_set() {
273 let signer = Ed25519Signer::generate().unwrap();
274 let data = TestData {
275 value: "test".to_string(),
276 number: 1,
277 };
278
279 let before = TimeStamp::now();
280 let signed = Signed::new(data, &signer).unwrap();
281 let after = TimeStamp::now();
282
283 let ts = signed.signature().timestamp;
284 assert!(ts >= before);
285 assert!(ts <= after);
286 }
287
288 #[test]
289 fn test_signature_serialization() {
290 let signer = Ed25519Signer::generate().unwrap();
291 let data = TestData {
292 value: "serialize me".to_string(),
293 number: 456,
294 };
295
296 let signature = Signature::new(&data, &signer).unwrap();
297
298 let json = serde_json::to_string(&signature).unwrap();
300
301 let deserialized: Signature = serde_json::from_str(&json).unwrap();
303
304 assert!(deserialized.verify(&data).is_ok());
306 }
307
308 #[test]
309 fn test_signed_serialization() {
310 let signer = Ed25519Signer::generate().unwrap();
311 let data = TestData {
312 value: "roundtrip".to_string(),
313 number: 789,
314 };
315
316 let signed = Signed::new(data, &signer).unwrap();
317
318 let json = serde_json::to_string(&signed).unwrap();
320
321 let deserialized: Signed<TestData> =
323 serde_json::from_str(&json).unwrap();
324
325 assert!(deserialized.verify().is_ok());
327 assert_eq!(deserialized.content().value, "roundtrip");
328 }
329}