trust_graph/
certificate.rs

1/*
2 * Copyright 2020 Fluence Labs Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use 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
29/// Serialization format of a certificate.
30/// TODO
31const FORMAT: &[u8; 2] = &[0, 0];
32/// Serialization format version of a certificate.
33/// TODO
34const VERSION: &[u8; 4] = &[0, 0, 0, 0];
35const TRUST_NUMBER_LEN: usize = 1;
36
37/// Chain of trusts started from self-signed root trust.
38#[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        // check if `issued_by` is allowed to issue a certificate (i.e., there’s a trust for it in a chain)
110        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        // splitting old chain to add new trust after given public key
122        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    /// Creates new certificate with root trust (self-signed public key) from a key pair.
134    #[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    /// Adds a new trust into chain of trust in certificate.
152    #[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        // first, verify given certificate
169        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        // check if `issued_by_pk` is allowed to issue a certificate (i.e., there’s a trust for it in a chain)
178        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        // splitting old chain to add new trust after given public key
190        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    /// Verifies that a certificate is valid and you trust to this certificate.
204    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        // check root trust and its existence in trusted roots list
216        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        // check if every element in a chain is not expired and has the correct signature
223        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    /// Convert certificate to byte format
236    /// 2 format + 4 version + 1 trusts number + ((1 trust size byte + trust) for each trust)
237    #[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        // TODO do match different formats and versions
264        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        // TODO for future purposes
314        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        // we don't need nanos for serialization, etc
445        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        // forged cert
604        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}