ic_cbor/
cbor_parse_certificate.rs1use 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}