1#[cfg(feature = "alloc")]
5use alloc::prelude::v1::*;
6
7use crate::base::{BaseError, Body, Header, PrivateOptions};
8use crate::crypto;
9use crate::options::{Options, OptionsList};
10use crate::types::*;
11
12use crate::base::Base;
13
14pub mod header;
16
17pub mod builder;
19pub use builder::Builder;
20
21pub mod container;
23pub use container::Container;
24
25impl<'a, T: AsRef<[u8]>> Container<T> {
26 pub fn parse<P, S>(
29 data: T,
30 mut pub_key_s: P,
31 mut sec_key_s: S,
32 ) -> Result<(Base, usize), BaseError>
33 where
34 P: FnMut(&Id) -> Option<PublicKey>,
35 S: FnMut(&Id) -> Option<SecretKey>,
36 {
37 let mut verified = false;
38
39 let (container, n) = Container::from(data);
41 let header = container.header();
42
43 let flags = header.flags();
45
46 let id: Id = container.id().into();
48
49 let signature: Signature = container.signature().into();
51
52 if !flags.contains(Flags::SECONDARY) {
54 if let Some(key) = (pub_key_s)(&id) {
56 if id != crypto::hash(&key).unwrap() {
58 return Err(BaseError::PublicKeyIdMismatch);
59 }
60
61 verified = crypto::pk_validate(&key, &signature, container.signed())
63 .map_err(|_e| BaseError::ValidateError)?;
64
65 if !verified {
67 info!("Invalid signature with known pubkey");
68 return Err(BaseError::InvalidSignature);
69 }
70 }
71 }
72
73 let mut peer_id = None;
75 let mut pub_key = None;
76 let mut parent = None;
77
78 let public_options: Vec<_> = container
79 .public_options()
80 .filter_map(|o| match &o {
81 Options::PeerId(v) => {
82 peer_id = Some(v.peer_id.clone());
83 None
84 }
85 Options::PubKey(v) => {
86 pub_key = Some(v.public_key.clone());
87 None
88 }
89 Options::PrevSig(v) => {
90 parent = Some(v.sig.clone());
91 None
92 }
93 _ => Some(o),
94 })
95 .collect();
96
97 let signing_id: Id = match (flags.contains(Flags::SECONDARY), &peer_id) {
99 (false, _) => Ok(container.id().into()),
100 (true, Some(id)) => Ok(id.clone()),
101 _ => Err(BaseError::NoPeerId),
102 }?;
103
104 let public_key: Option<PublicKey> = match ((pub_key_s)(&signing_id), &pub_key) {
106 (Some(key), _) => Some(key),
107 (None, Some(key)) => Some(key.clone()),
108 _ => {
109 warn!(
110 "Missing public key for message: {:?} signing id: {:?}",
111 id, signing_id
112 );
113 None
114 }
115 };
116
117 match (verified, public_key) {
119 (false, Some(public_key)) => {
120 if signing_id != crypto::hash(&public_key).unwrap() {
122 error!("Public key mismatch for object from {:?}", id);
123 return Err(BaseError::PublicKeyIdMismatch);
124 }
125
126 verified = crypto::pk_validate(&public_key, &signature, container.signed())
128 .map_err(|_e| BaseError::ValidateError)?;
129
130 if !verified {
132 info!("Invalid signature for self-signed object from {:?}", id);
133 return Err(BaseError::InvalidSignature);
134 }
135 }
136 (false, None) => {
137 error!("No signature or key for object from {:?}", id);
138 return Err(BaseError::ValidateError.into());
139 }
140 _ => (),
141 }
142
143 let mut body_data = container.body().to_vec();
144 let mut private_options_data = container.private_options().to_vec();
145
146 let body = match (flags.contains(Flags::ENCRYPTED), sec_key_s(&id)) {
148 (true, Some(sk)) if body_data.len() > 0 => {
149 let n = crypto::sk_decrypt2(&sk, &mut body_data)
151 .map_err(|_e| BaseError::InvalidSignature)?;
152 body_data = (&body_data[..n]).to_vec();
153
154 Body::Cleartext(body_data)
155 }
156 (true, None) if body_data.len() > 0 => {
157 debug!("No encryption key found for data");
158
159 Body::Encrypted(body_data)
160 }
161 (false, _) if body_data.len() > 0 => Body::Cleartext(body_data),
162 _ => Body::None,
163 };
164
165 let private_options = match (flags.contains(Flags::ENCRYPTED), sec_key_s(&id)) {
167 (true, Some(sk)) if private_options_data.len() > 0 => {
168 let n = crypto::sk_decrypt2(&sk, &mut private_options_data)
170 .map_err(|_e| BaseError::InvalidSignature)?;
171 private_options_data = (&private_options_data[..n]).to_vec();
172
173 let (private_options, _n) = Options::parse_vec(&private_options_data)?;
175
176 PrivateOptions::Cleartext(private_options)
177 }
178 (true, None) if private_options_data.len() > 0 => {
179 debug!("No encryption key found for data");
180
181 PrivateOptions::Encrypted(private_options_data)
182 }
183 _ => PrivateOptions::None,
184 };
185
186 Ok((
188 Base {
189 id,
190 header: Header::new(
191 header.application_id(),
192 header.kind(),
193 header.index(),
194 header.flags(),
195 ),
196 body,
197
198 private_options,
199 public_options,
200
201 parent,
202 peer_id: peer_id.clone(),
203 public_key: pub_key.clone(),
204
205 signature: Some(signature),
206 verified,
207
208 raw: Some(container.raw().to_vec()),
209 },
210 n,
211 ))
212 }
213}
214
215impl<'a, T: AsRef<[u8]> + AsMut<[u8]>> Container<T> {
216 pub fn encode(
217 buff: T,
218 base: &Base,
219 signing_key: &PrivateKey,
220 encryption_key: Option<&SecretKey>,
221 ) -> (Self, usize) {
222 let bb = Builder::new(buff).id(base.id()).header(base.header());
224
225 let encryption_key = match (base.flags().contains(Flags::ENCRYPTED), encryption_key) {
227 (true, Some(k)) => Some(k),
228 (true, None) => panic!("Attempted to encrypt object with no secret key"),
229 _ => None,
230 };
231
232 let bb = bb.body(base.body(), encryption_key).unwrap();
234
235 let mut bb = bb
237 .private_options(base.private_options(), encryption_key)
238 .unwrap();
239
240 if let Some(k) = &base.public_key {
243 bb.public_option(&Options::pub_key(k.clone())).unwrap();
244 }
245
246 if let Some(s) = &base.parent {
247 bb.public_option(&Options::prev_sig(s)).unwrap();
248 }
249
250 if let Some(i) = &base.peer_id {
251 bb.public_option(&Options::peer_id(i.clone())).unwrap();
252 }
253
254 let opts = OptionsList::<_, &[u8]>::Cleartext(base.public_options());
255 let bb = bb.public_options(&opts).unwrap();
256
257 let c = bb.sign(signing_key).unwrap();
259 let len = c.len;
260
261 (c, len)
262 }
263}
264
265#[cfg(test)]
266mod test {}