1use crate::certificate::CertificateError::{
18 CertificateLengthError, DecodeError, DecodeTrustError, ExpirationError,
19 IncorrectCertificateFormat, KeyInCertificateError, MalformedRoot, NoTrustedRoot,
20 VerificationError,
21};
22use crate::trust::{Trust, TrustError};
23use fluence_keypair::key_pair::KeyPair;
24use fluence_keypair::public_key::PublicKey;
25use std::str::FromStr;
26use std::time::Duration;
27use thiserror::Error as ThisError;
28
29const FORMAT: &[u8; 2] = &[0, 0];
32const VERSION: &[u8; 4] = &[0, 0, 0, 0];
35const TRUST_NUMBER_LEN: usize = 1;
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct Certificate {
40 pub chain: Vec<Trust>,
41}
42
43#[derive(ThisError, Debug)]
44pub enum CertificateError {
45 #[error("Incorrect format of the certificate: {0}")]
46 IncorrectCertificateFormat(String),
47 #[error("Incorrect length of an array. Should be 2 bytes of a format, 4 bytes of a version and 104 bytes for each trust")]
48 IncorrectByteLength,
49 #[error("Error while decoding a trust in a certificate: {0}")]
50 DecodeError(#[source] TrustError),
51 #[error("Certificate is expired. Issued at {issued_at} and expired at {expires_at}")]
52 ExpirationError {
53 expires_at: String,
54 issued_at: String,
55 },
56 #[error("Certificate does not contain a trusted root.")]
57 NoTrustedRoot,
58 #[error("Root trust did not pass verification: {0}")]
59 MalformedRoot(#[source] TrustError),
60 #[error("There is no `issued_by` public key in a certificate")]
61 KeyInCertificateError,
62 #[error("The certificate must have at least 1 trust")]
63 CertificateLengthError,
64 #[error("Cannot convert trust number {0} from string: {1}")]
65 DecodeTrustError(usize, #[source] TrustError),
66 #[error("Trust {0} in chain did not pass verification: {1}")]
67 VerificationError(usize, #[source] TrustError),
68 #[error("there cannot be paths without any nodes after adding verified certificates")]
69 Unexpected,
70}
71
72impl Certificate {
73 pub fn new_unverified(chain: Vec<Trust>) -> Self {
74 Self { chain }
75 }
76
77 pub fn new_from_root_trust(
78 root_trust: Trust,
79 issued_trust: Trust,
80 cur_time: Duration,
81 ) -> Result<Self, CertificateError> {
82 Trust::verify(&root_trust, &root_trust.issued_for, cur_time).map_err(MalformedRoot)?;
83 Trust::verify(&issued_trust, &root_trust.issued_for, cur_time)
84 .map_err(|e| VerificationError(1, e))?;
85
86 Ok(Self {
87 chain: vec![root_trust, issued_trust],
88 })
89 }
90
91 pub fn issue_with_trust(
92 issued_by: PublicKey,
93 trust: Trust,
94 extend_cert: &Certificate,
95 cur_time: Duration,
96 ) -> Result<Self, CertificateError> {
97 if trust.expires_at.lt(&trust.issued_at) {
98 return Err(ExpirationError {
99 expires_at: format!("{:?}", trust.expires_at),
100 issued_at: format!("{:?}", trust.issued_at),
101 });
102 }
103
104 Certificate::verify(
105 extend_cert,
106 &[extend_cert.chain[0].issued_for.clone()],
107 cur_time,
108 )?;
109 let mut previous_trust_num: i32 = -1;
111 for pk_id in 0..extend_cert.chain.len() {
112 if extend_cert.chain[pk_id].issued_for == issued_by {
113 previous_trust_num = pk_id as i32;
114 }
115 }
116
117 if previous_trust_num == -1 {
118 return Err(KeyInCertificateError);
119 };
120
121 let mut new_chain = extend_cert
123 .chain
124 .split_at((previous_trust_num + 1) as usize)
125 .0
126 .to_vec();
127
128 new_chain.push(trust);
129
130 Ok(Self { chain: new_chain })
131 }
132
133 #[allow(dead_code)]
135 pub fn issue_root(
136 root_kp: &KeyPair,
137 for_pk: PublicKey,
138 expires_at: Duration,
139 issued_at: Duration,
140 ) -> Self {
141 let root_expiration = Duration::from_secs(u64::max_value());
142
143 let root_trust = Trust::create(root_kp, root_kp.public(), root_expiration, issued_at);
144
145 let trust = Trust::create(root_kp, for_pk, expires_at, issued_at);
146
147 let chain = vec![root_trust, trust];
148 Self { chain }
149 }
150
151 #[allow(dead_code)]
153 pub fn issue(
154 issued_by: &KeyPair,
155 for_pk: PublicKey,
156 extend_cert: &Certificate,
157 expires_at: Duration,
158 issued_at: Duration,
159 cur_time: Duration,
160 ) -> Result<Self, CertificateError> {
161 if expires_at.lt(&issued_at) {
162 return Err(ExpirationError {
163 expires_at: format!("{expires_at:?}"),
164 issued_at: format!("{issued_at:?}"),
165 });
166 }
167
168 Certificate::verify(
170 extend_cert,
171 &[extend_cert.chain[0].issued_for.clone()],
172 cur_time,
173 )?;
174
175 let issued_by_pk = issued_by.public();
176
177 let mut previous_trust_num: i32 = -1;
179 for pk_id in 0..extend_cert.chain.len() {
180 if extend_cert.chain[pk_id].issued_for == issued_by_pk {
181 previous_trust_num = pk_id as i32;
182 }
183 }
184
185 if previous_trust_num == -1 {
186 return Err(KeyInCertificateError);
187 };
188
189 let mut new_chain = extend_cert
191 .chain
192 .split_at((previous_trust_num + 1) as usize)
193 .0
194 .to_vec();
195
196 let trust = Trust::create(issued_by, for_pk, expires_at, issued_at);
197
198 new_chain.push(trust);
199
200 Ok(Self { chain: new_chain })
201 }
202
203 pub fn verify(
205 cert: &Certificate,
206 trusted_roots: &[PublicKey],
207 cur_time: Duration,
208 ) -> Result<(), CertificateError> {
209 let chain = &cert.chain;
210
211 if chain.is_empty() {
212 return Err(CertificateLengthError);
213 }
214
215 let root = &chain[0];
217 Trust::verify(root, &root.issued_for, cur_time).map_err(MalformedRoot)?;
218 if !trusted_roots.contains(&root.issued_for) {
219 return Err(NoTrustedRoot);
220 }
221
222 for trust_id in (1..chain.len()).rev() {
224 let trust = &chain[trust_id];
225
226 let trust_giver = &chain[trust_id - 1];
227
228 Trust::verify(trust, &trust_giver.issued_for, cur_time)
229 .map_err(|e| VerificationError(trust_id, e))?;
230 }
231
232 Ok(())
233 }
234
235 #[allow(dead_code)]
238 pub fn encode(&self) -> Vec<u8> {
239 let mut encoded = Vec::new();
240 encoded.extend_from_slice(FORMAT);
241 encoded.extend_from_slice(VERSION);
242 encoded.push(self.chain.len() as u8);
243
244 for t in &self.chain {
245 let trust = t.encode();
246 encoded.push(trust.len() as u8);
247 encoded.extend(trust);
248 }
249
250 encoded
251 }
252
253 fn check_arr_len(arr: &[u8], check_len: usize) -> Result<(), CertificateError> {
254 if arr.len() < check_len {
255 Err(CertificateLengthError)
256 } else {
257 Ok(())
258 }
259 }
260
261 #[allow(dead_code)]
262 pub fn decode(arr: &[u8]) -> Result<Self, CertificateError> {
263 Self::check_arr_len(arr, FORMAT.len() + VERSION.len() + TRUST_NUMBER_LEN)?;
265 let mut offset = 0;
266 let _format = &arr[offset..offset + FORMAT.len()];
267 offset += FORMAT.len();
268
269 let _version = &arr[offset..offset + VERSION.len()];
270 offset += VERSION.len();
271
272 let number_of_trusts = arr[offset] as usize;
273 offset += TRUST_NUMBER_LEN;
274
275 if number_of_trusts < 2 {
276 return Err(CertificateLengthError);
277 }
278 let mut chain = Vec::with_capacity(number_of_trusts);
279
280 for _ in 0..number_of_trusts {
281 Self::check_arr_len(arr, offset + 1)?;
282 let trust_len = arr[offset] as usize;
283 let from = offset + 1;
284 let to = from + trust_len;
285 Self::check_arr_len(arr, to)?;
286 let slice = &arr[from..to];
287 let t = Trust::decode(slice).map_err(DecodeError)?;
288 chain.push(t);
289 offset += 1 + trust_len;
290 }
291
292 Ok(Self { chain })
293 }
294}
295
296impl std::fmt::Display for Certificate {
297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298 writeln!(f, "{}", bs58::encode(FORMAT).into_string())?;
299 writeln!(f, "{}", bs58::encode(VERSION).into_string())?;
300 for trust in self.chain.iter() {
301 writeln!(f, "{}", trust.to_string())?;
302 }
303 Ok(())
304 }
305}
306
307impl FromStr for Certificate {
308 type Err = CertificateError;
309
310 fn from_str(s: &str) -> Result<Self, Self::Err> {
311 let str_lines: Vec<&str> = s.lines().collect();
312
313 let _format = str_lines[0];
315 let _version = str_lines[1];
316
317 if (str_lines.len() - 2) % 4 != 0 {
318 return Err(IncorrectCertificateFormat(s.to_string()));
319 }
320
321 let num_of_trusts = (str_lines.len() - 2) / 4;
322 let mut trusts = Vec::with_capacity(num_of_trusts);
323
324 for i in (2..str_lines.len()).step_by(4) {
325 let trust = Trust::convert_from_strings(
326 str_lines[i],
327 str_lines[i + 1],
328 str_lines[i + 2],
329 str_lines[i + 3],
330 )
331 .map_err(|e| DecodeTrustError(i, e))?;
332
333 trusts.push(trust);
334 }
335
336 Ok(Self::new_unverified(trusts))
337 }
338}
339
340#[cfg(test)]
341mod tests {
342 use super::*;
343 use crate::misc::current_time;
344 use fluence_keypair::KeyPair;
345 use std::time::{Duration, SystemTime, UNIX_EPOCH};
346
347 pub fn one_second() -> Duration {
348 Duration::from_secs(1)
349 }
350
351 pub fn one_minute() -> Duration {
352 Duration::from_secs(60)
353 }
354
355 pub fn one_year() -> Duration {
356 Duration::from_secs(31_557_600)
357 }
358
359 #[test]
360 pub fn test_string_encoding_decoding_ed25519() {
361 let (_root_kp, second_kp, cert) = generate_root_cert();
362
363 let cur_time = current_time();
364
365 let third_kp = KeyPair::generate_ed25519();
366
367 let new_cert = Certificate::issue(
368 &second_kp,
369 third_kp.public(),
370 &cert,
371 cur_time.checked_add(one_second()).unwrap(),
372 cur_time,
373 cur_time,
374 )
375 .unwrap();
376
377 let serialized = new_cert.to_string();
378 let deserialized = Certificate::from_str(&serialized);
379
380 assert!(deserialized.is_ok());
381 let after_cert = deserialized.unwrap();
382 assert_eq!(&new_cert.chain[0], &after_cert.chain[0]);
383 assert_eq!(&new_cert, &after_cert);
384 }
385
386 #[test]
387 pub fn test_serialization_deserialization_ed25519() {
388 let (_root_kp, second_kp, cert) = generate_root_cert();
389
390 let cur_time = current_time();
391
392 let third_kp = KeyPair::generate_ed25519();
393
394 let new_cert = Certificate::issue(
395 &second_kp,
396 third_kp.public(),
397 &cert,
398 cur_time.checked_add(one_second()).unwrap(),
399 cur_time,
400 cur_time,
401 )
402 .unwrap();
403
404 let serialized = new_cert.encode();
405 let deserialized = Certificate::decode(serialized.as_slice());
406
407 assert!(deserialized.is_ok());
408 let after_cert = deserialized.unwrap();
409 assert_eq!(&new_cert.chain[0], &after_cert.chain[0]);
410 assert_eq!(&new_cert, &after_cert);
411 }
412
413 #[test]
414 fn test_small_chain_ed25519() {
415 let bad_cert = Certificate { chain: Vec::new() };
416
417 let check = Certificate::verify(&bad_cert, &[], current_time());
418 assert!(check.is_err());
419 }
420
421 fn generate_root_cert() -> (KeyPair, KeyPair, Certificate) {
422 let root_kp = KeyPair::generate_ed25519();
423 let second_kp = KeyPair::generate_ed25519();
424
425 let cur_time = current_time();
426
427 (
428 root_kp.clone(),
429 second_kp.clone(),
430 Certificate::issue_root(
431 &root_kp,
432 second_kp.public(),
433 cur_time.checked_add(one_year()).unwrap(),
434 cur_time,
435 ),
436 )
437 }
438
439 #[test]
440 fn test_issue_cert_ed25519() {
441 let (root_kp, second_kp, cert) = generate_root_cert();
442 let trusted_roots = [root_kp.public()];
443
444 let cur_time = Duration::from_secs(
446 SystemTime::now()
447 .duration_since(UNIX_EPOCH)
448 .unwrap()
449 .as_secs() as u64,
450 );
451
452 let third_kp = KeyPair::generate_ed25519();
453
454 let new_cert = Certificate::issue(
455 &second_kp,
456 third_kp.public(),
457 &cert,
458 cur_time.checked_add(one_year()).unwrap(),
459 cur_time,
460 cur_time,
461 );
462 assert_eq!(new_cert.is_ok(), true);
463 let new_cert = new_cert.unwrap();
464
465 println!("cert is\n{}", new_cert.to_string());
466
467 assert_eq!(new_cert.chain.len(), 3);
468 assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
469 assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
470 assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
471 assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
472 }
473
474 #[test]
475 fn test_cert_expiration_ed25519() {
476 let (root_kp, second_kp, cert) = generate_root_cert();
477 let trusted_roots = [root_kp.public()];
478 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
479
480 let third_kp = KeyPair::generate_ed25519();
481
482 let new_cert = Certificate::issue(
483 &second_kp,
484 third_kp.public(),
485 &cert,
486 cur_time.checked_sub(one_second()).unwrap(),
487 cur_time.checked_sub(one_minute()).unwrap(),
488 cur_time,
489 )
490 .unwrap();
491
492 assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_err());
493 }
494
495 #[test]
496 fn test_issue_in_chain_tail_ed25519() {
497 let (root_kp, second_kp, cert) = generate_root_cert();
498 let trusted_roots = [root_kp.public()];
499 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
500
501 let third_kp = KeyPair::generate_ed25519();
502 let fourth_kp = KeyPair::generate_ed25519();
503
504 let new_cert = Certificate::issue(
505 &second_kp,
506 third_kp.public(),
507 &cert,
508 cur_time.checked_add(one_second()).unwrap(),
509 cur_time,
510 cur_time,
511 )
512 .unwrap();
513 let new_cert = Certificate::issue(
514 &third_kp,
515 fourth_kp.public(),
516 &new_cert,
517 cur_time.checked_add(one_second()).unwrap(),
518 cur_time,
519 cur_time,
520 );
521
522 assert_eq!(new_cert.is_ok(), true);
523 let new_cert = new_cert.unwrap();
524
525 assert_eq!(new_cert.chain.len(), 4);
526 assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
527 assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
528 assert_eq!(new_cert.chain[2].issued_for, third_kp.public());
529 assert_eq!(new_cert.chain[3].issued_for, fourth_kp.public());
530 assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
531 }
532
533 #[test]
534 fn test_issue_in_chain_body_ed25519() {
535 let (root_kp, second_kp, cert) = generate_root_cert();
536 let trusted_roots = [root_kp.public()];
537 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
538
539 let third_kp = KeyPair::generate_ed25519();
540 let fourth_kp = KeyPair::generate_ed25519();
541
542 let new_cert = Certificate::issue(
543 &second_kp,
544 third_kp.public(),
545 &cert,
546 cur_time.checked_add(one_second()).unwrap(),
547 cur_time,
548 cur_time,
549 )
550 .unwrap();
551 let new_cert = Certificate::issue(
552 &second_kp,
553 fourth_kp.public(),
554 &new_cert,
555 cur_time.checked_add(one_second()).unwrap(),
556 cur_time,
557 cur_time,
558 );
559
560 assert_eq!(new_cert.is_ok(), true);
561 let new_cert = new_cert.unwrap();
562
563 assert_eq!(new_cert.chain.len(), 3);
564 assert_eq!(new_cert.chain[0].issued_for, root_kp.public());
565 assert_eq!(new_cert.chain[1].issued_for, second_kp.public());
566 assert_eq!(new_cert.chain[2].issued_for, fourth_kp.public());
567 assert!(Certificate::verify(&new_cert, &trusted_roots, cur_time).is_ok());
568 }
569
570 #[test]
571 fn test_no_cert_in_chain_ed25519() {
572 let (_root_kp, _second_kp, cert) = generate_root_cert();
573 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
574
575 let bad_kp = KeyPair::generate_ed25519();
576 let new_cert_bad = Certificate::issue(
577 &bad_kp,
578 bad_kp.public(),
579 &cert,
580 cur_time.checked_add(one_second()).unwrap(),
581 cur_time,
582 cur_time,
583 );
584 assert_eq!(new_cert_bad.is_err(), true);
585 }
586
587 #[test]
588 fn test_no_trusted_root_in_chain() {
589 let (_root_kp, second_kp, cert) = generate_root_cert();
590 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
591
592 let trusted_roots = [second_kp.public()];
593 assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_err());
594 assert!(Certificate::verify(&cert, &[], cur_time).is_err());
595 }
596
597 #[test]
598 fn test_forged_cert() {
599 let (root_kp, _second_kp, cert) = generate_root_cert();
600 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
601 let trusted_roots = [root_kp.public()];
602
603 let mut bad_chain = cert.chain;
605 bad_chain.remove(0);
606 let bad_cert = Certificate { chain: bad_chain };
607
608 assert!(Certificate::verify(&bad_cert, &trusted_roots, cur_time).is_err());
609 }
610
611 #[test]
612 fn test_generate_root_cert() {
613 let (root_kp, second_kp, cert) = generate_root_cert();
614 let cur_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
615
616 let trusted_roots = [root_kp.public()];
617
618 assert_eq!(cert.chain.len(), 2);
619 assert_eq!(cert.chain[0].issued_for, root_kp.public());
620 assert_eq!(cert.chain[1].issued_for, second_kp.public());
621 assert!(Certificate::verify(&cert, &trusted_roots, cur_time).is_ok());
622 }
623}