ic_cbor/
cbor_parse_certificate.rs

1use crate::{parse_cbor, parsed_cbor_to_tree, CborError, CborResult, CborValue};
2use ic_certification::{Certificate, Delegation};
3
4pub trait CertificateToCbor {
5    fn from_cbor(cbor: &[u8]) -> CborResult<Certificate>;
6}
7
8impl CertificateToCbor for Certificate {
9    fn from_cbor(cbor: &[u8]) -> CborResult<Certificate> {
10        let parsed_cbor = parse_cbor(cbor).map_err(|e| CborError::MalformedCbor(e.to_string()))?;
11
12        parsed_cbor_to_certificate(parsed_cbor)
13    }
14}
15
16fn parsed_cbor_to_certificate(parsed_cbor: CborValue) -> CborResult<Certificate> {
17    let CborValue::Map(map) = parsed_cbor else {
18        return Err(CborError::MalformedCertificate(
19            "Expected Map when parsing Certificate Cbor".into(),
20        ));
21    };
22
23    let Some(tree_cbor) = map.get("tree") else {
24        return Err(CborError::MalformedCertificate(
25            "Expected Tree when parsing Certificate Cbor".into(),
26        ));
27    };
28
29    let tree = parsed_cbor_to_tree(tree_cbor)?;
30
31    let signature = if let Some(CborValue::ByteString(signature)) = map.get("signature") {
32        signature.to_owned()
33    } else {
34        return Err(CborError::MalformedCertificate(
35            "Expected Signature when parsing Certificate Cbor".into(),
36        ));
37    };
38
39    let delegation = if let Some(CborValue::Map(delegation_map)) = map.get("delegation") {
40        let Some(CborValue::ByteString(subnet_id)) = delegation_map.get("subnet_id") else {
41            return Err(CborError::MalformedCertificate(
42                "Expected Delegation Map to contain a Subnet ID when parsing Certificate Cbor"
43                    .into(),
44            ));
45        };
46
47        let Some(CborValue::ByteString(certificate)) = delegation_map.get("certificate") else {
48            return Err(CborError::MalformedCertificate(
49                "Expected Delegation Map to contain a Certificate when parsing Certificate Cbor"
50                    .into(),
51            ));
52        };
53
54        Some(Delegation {
55            subnet_id: subnet_id.to_owned(),
56            certificate: certificate.to_owned(),
57        })
58    } else {
59        None
60    };
61
62    Ok(Certificate {
63        tree,
64        signature,
65        delegation,
66    })
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use ic_response_verification_test_utils::{
73        cbor_encode, create_certificate, create_certificate_delegation,
74    };
75
76    #[test]
77    fn deserialize_from_cbor() {
78        let certificate = create_certificate(None);
79
80        let cbor = cbor_encode(&certificate);
81
82        let result = Certificate::from_cbor(&cbor).unwrap();
83
84        assert_eq!(result, certificate);
85    }
86
87    #[test]
88    fn deserialize_from_cbor_with_delegation() {
89        let mut certificate = create_certificate(None);
90        certificate.delegation = Some(create_certificate_delegation());
91
92        let cbor = cbor_encode(&certificate);
93
94        let result = Certificate::from_cbor(&cbor).unwrap();
95
96        assert_eq!(result, certificate);
97    }
98}