ndn_protocol/
certificate.rs1use std::path::Path;
2
3use base64::Engine;
4use bytes::Bytes;
5use ndn_tlv::{Tlv, TlvDecode, TlvEncode};
6use rsa::{
7 pkcs8::{DecodePrivateKey, DecodePublicKey},
8 RsaPrivateKey, RsaPublicKey,
9};
10
11use crate::{error::NdnError, Data, KeyLocator, Name, SignatureInfo};
12
13#[derive(Tlv, Clone, Hash, Debug)]
14#[tlv(128)]
15pub struct SafeBag {
16 pub certificate: Data<Bytes>,
17 pub encrypted_key: EncryptedKey,
18}
19
20#[derive(Tlv, Clone, Hash, Debug)]
21#[tlv(129)]
22pub struct EncryptedKey {
23 pub data: Bytes,
24}
25
26#[derive(Clone, Debug, Hash)]
27pub struct Certificate(pub Data<Bytes>);
28
29pub trait ToCertificate {
30 fn to_certificate(&self) -> Certificate;
31}
32
33#[derive(Clone, Debug, Hash)]
34pub struct RsaCertificate {
35 cert: Certificate,
36 public_key: RsaPublicKey,
37 private_key: Option<RsaPrivateKey>,
38}
39
40impl RsaCertificate {
41 pub fn new(cert: Certificate) -> Option<Self> {
42 let key = RsaPublicKey::from_public_key_der(&cert.0.content()?).ok()?;
43 Some(Self {
44 cert,
45 public_key: key,
46 private_key: None,
47 })
48 }
49
50 pub fn with_private(cert: Certificate, private_key: RsaPrivateKey) -> Option<Self> {
51 let key = RsaPublicKey::from_public_key_der(&cert.0.content()?).ok()?;
52 Some(Self {
53 cert,
54 public_key: key,
55 private_key: Some(private_key),
56 })
57 }
58
59 pub fn from_safebag<P>(bag: SafeBag, password: P) -> Option<Self>
60 where
61 P: AsRef<[u8]>,
62 {
63 let key =
64 RsaPrivateKey::from_pkcs8_encrypted_der(&bag.encrypted_key.data, password).ok()?;
65 Self::with_private(Certificate(bag.certificate), key)
66 }
67
68 pub fn name(&self) -> &Name {
69 self.cert.name()
70 }
71
72 pub fn public_key(&self) -> &RsaPublicKey {
73 &self.public_key
74 }
75
76 pub fn private_key(&self) -> Option<&RsaPrivateKey> {
77 self.private_key.as_ref()
78 }
79}
80
81impl ToCertificate for RsaCertificate {
82 fn to_certificate(&self) -> Certificate {
83 self.cert.clone()
84 }
85}
86
87impl SafeBag {
88 pub fn load_file(path: impl AsRef<Path>) -> Result<Self, NdnError> {
89 let mut file_content = std::fs::read(path)?;
90 file_content.retain(|x| *x != b'\n' && *x != b'\r');
91 let safebag_data = base64::engine::general_purpose::STANDARD
92 .decode(&file_content)
93 .map_err(|_| {
94 NdnError::GenericError("Could not base64-decode certificate".to_string())
95 })?;
96 Ok(SafeBag::decode(&mut Bytes::from(safebag_data))?)
97 }
98}
99
100impl Certificate {
101 pub fn load_file<P>(path: P) -> Result<Self, NdnError>
102 where
103 P: AsRef<Path>,
104 {
105 let mut file_content = std::fs::read(path)?;
106 file_content.retain(|x| *x != b'\n' && *x != b'\r');
107 let safebag_data = base64::engine::general_purpose::STANDARD
108 .decode(&file_content)
109 .map_err(|_| {
110 NdnError::GenericError("Could not base64-decode certificate".to_string())
111 })?;
112 Ok(Self(Data::<Bytes>::decode(&mut Bytes::from(safebag_data))?))
113 }
114
115 pub fn name(&self) -> &Name {
116 self.0.name()
117 }
118
119 pub fn identity(&self) -> Name {
120 let mut name = self.name().clone();
121 name.components.pop();
122 name.components.pop();
123 name.components.pop();
124 name.components.pop();
125 name
126 }
127
128 pub fn name_locator(&self) -> KeyLocator {
129 KeyLocator::new(crate::signature::KeyLocatorData::Name(self.name().clone()))
130 }
131
132 pub fn as_data(&self) -> &Data<Bytes> {
133 &self.0
134 }
135
136 pub fn signature_info(&self) -> Option<&SignatureInfo> {
137 self.0.signature_info()
138 }
139}
140
141impl TlvEncode for Certificate {
142 fn encode(&self) -> Bytes {
143 self.0.encode()
144 }
145
146 fn size(&self) -> usize {
147 self.0.size()
148 }
149}
150
151impl TlvDecode for Certificate {
152 fn decode(bytes: &mut Bytes) -> ndn_tlv::Result<Self> {
153 Data::<Bytes>::decode(bytes).map(Self)
154 }
155}