1use super::aesgcm::{decrypt, encrypt, get_key};
4
5use crate::artifacts::{PublicKey, SigningKeyExt, UserSecretKey, VerifyingKey};
6use crate::client::*;
7use crate::error::Error;
8use crate::identity::{EncryptionPolicy, Policy};
9use crate::util::preamble_checked;
10use ibs::gg::{Identity, Signature, Signer, Verifier, SIG_BYTES};
11
12use futures::{Sink, SinkExt, Stream, StreamExt};
13use ibe::kem::cgw_kv::CGWKV;
14use js_sys::Uint8Array;
15use rand::{CryptoRng, RngCore};
16use wasm_bindgen::{JsCast, JsValue};
17
18use alloc::string::ToString;
19use alloc::vec::Vec;
20
21#[derive(Debug)]
23pub struct StreamSealerConfig {
24 segment_size: u32,
25 key: [u8; KEY_SIZE],
26 nonce: [u8; STREAM_NONCE_SIZE],
27}
28
29#[derive(Debug)]
31pub struct StreamUnsealerConfig {
32 segment_size: u32,
33 spill: Vec<u8>,
34}
35
36impl SealerConfig for StreamSealerConfig {}
37impl UnsealerConfig for StreamUnsealerConfig {}
38impl crate::client::sealed::SealerConfig for StreamSealerConfig {}
39impl crate::client::sealed::UnsealerConfig for StreamUnsealerConfig {}
40
41impl<'r, Rng: RngCore + CryptoRng> Sealer<'r, Rng, StreamSealerConfig> {
42 pub fn new(
44 pk: &PublicKey<CGWKV>,
45 policies: &EncryptionPolicy,
46 pub_sign_key: &SigningKeyExt,
47 rng: &'r mut Rng,
48 ) -> Result<Self, Error> {
49 let (header, ss) = Header::new(pk, policies, rng)?;
50
51 let (segment_size, _) = stream_mode_checked(&header)?;
52 let Algorithm::Aes128Gcm(iv) = header.algo;
53
54 let mut key = [0u8; KEY_SIZE];
55 let mut nonce = [0u8; STREAM_NONCE_SIZE];
56
57 key.copy_from_slice(&ss.0[..KEY_SIZE]);
58 nonce.copy_from_slice(&iv.0[..STREAM_NONCE_SIZE]);
59
60 Ok(Sealer {
61 rng,
62 header,
63 pub_sign_key: crate::client::canonical_signing_key(pub_sign_key),
64 priv_sign_key: None,
65 config: StreamSealerConfig {
66 segment_size,
67 key,
68 nonce,
69 },
70 })
71 }
72
73 pub async fn seal<R, W>(mut self, mut r: R, mut w: W) -> Result<(), Error>
80 where
81 R: Stream<Item = Result<JsValue, JsValue>> + Unpin,
82 W: Sink<JsValue, Error = JsValue> + Unpin,
83 {
84 let size_hint = r.size_hint();
85 let new_hint = (size_hint.0 as u64, size_hint.1.map(|x| x as u64));
86
87 self.header = self.header.with_mode(Mode::Streaming {
88 segment_size: self.config.segment_size,
89 size_hint: new_hint,
90 });
91
92 w.feed(Uint8Array::from(&PRELUDE[..]).into()).await?;
93 w.feed(Uint8Array::from(&VERSION_2.to_be_bytes()[..]).into())
94 .await?;
95
96 let header_vec = crate::bincode_compat::serialize(&self.header)?;
97
98 w.feed(Uint8Array::from(&(header_vec.len() as u32).to_be_bytes()[..]).into())
99 .await?;
100
101 w.feed(Uint8Array::from(&header_vec[..]).into()).await?;
102
103 let mut signer = Signer::default().chain(&header_vec);
104 let header_sig = signer.clone().sign(&self.pub_sign_key.key.0, self.rng);
105 let header_sig_ext = SignatureExt {
106 sig: header_sig,
107 pol: self.pub_sign_key.policy.clone(),
108 };
109 let header_sig_bytes = crate::bincode_compat::serialize(&header_sig_ext)?;
110
111 w.feed(Uint8Array::from(&(header_sig_bytes.len() as u32).to_be_bytes()[..]).into())
112 .await?;
113 w.feed(Uint8Array::from(&header_sig_bytes[..]).into())
114 .await?;
115
116 let key = get_key(&self.config.key).await?;
117
118 let pub_pol_bytes = crate::bincode_compat::serialize(&self.pub_sign_key.policy)?;
120 let signing_key = self.priv_sign_key.unwrap_or(self.pub_sign_key);
121
122 let pol_bytes = crate::bincode_compat::serialize(&signing_key.policy)?;
123 let pol_len: u32 = (pol_bytes.len() + pub_pol_bytes.len()) as u32;
124
125 if pol_len + POL_SIZE_SIZE as u32 > self.config.segment_size {
126 return Err(Error::ConstraintViolation.into());
127 }
128
129 let buf = Uint8Array::new_with_length(self.config.segment_size + SIG_BYTES as u32);
130
131 buf.set(
143 &Uint8Array::from(&(pol_len as u32).to_be_bytes()[..]).into(),
144 0,
145 );
146 buf.set(
147 &Uint8Array::from(&pol_bytes[..]).into(),
148 POL_SIZE_SIZE as u32,
149 );
150 buf.set(
151 &Uint8Array::from(&pub_pol_bytes[..]).into(),
152 POL_SIZE_SIZE as u32 + pol_bytes.len() as u32,
153 );
154
155 let mut counter = 0u32;
156 let mut buf_tail: u32 = POL_SIZE_SIZE as u32 + pol_len;
157 let mut start: u32 = buf_tail;
158
159 while let Some(Ok(data)) = r.next().await {
160 let mut array: Uint8Array = data.dyn_into()?;
161
162 while array.byte_length() != 0 {
163 let len = array.byte_length();
164 let rem = self.config.segment_size - buf_tail;
165
166 if len < rem {
167 buf.set(&array, buf_tail);
168 array = Uint8Array::new_with_length(0);
169 buf_tail += len;
170 } else {
171 buf.set(&array.slice(0, rem), buf_tail);
172 array = array.slice(rem, len);
173 buf_tail += rem;
174
175 signer.update(&buf.slice(start, buf_tail).to_vec());
176 let sig = signer
177 .clone()
178 .chain(&counter.to_be_bytes())
179 .chain(&[0x00])
180 .sign(&signing_key.key.0, self.rng);
181 let sig_bytes = crate::bincode_compat::serialize(&sig)?;
182
183 buf.set(&Uint8Array::from(&sig_bytes[..]).into(), buf_tail);
184
185 let ct = encrypt(
186 &key,
187 &aead_nonce(&self.config.nonce, counter, false),
188 &Uint8Array::new_with_length(0),
189 &buf,
190 )
191 .await?;
192
193 w.feed(ct.into()).await?;
194
195 counter = counter.checked_add(1).ok_or(Error::Symmetric)?;
196 buf_tail = 0;
197 start = 0;
198 }
199 }
200 }
201
202 signer.update(&buf.slice(start, buf_tail).to_vec());
203 let sig = signer
204 .chain(&counter.to_be_bytes())
205 .chain(&[0x01])
206 .sign(&signing_key.key.0, self.rng);
207 let sig_bytes = crate::bincode_compat::serialize(&sig)?;
208
209 buf.set(&Uint8Array::from(&sig_bytes[..]).into(), buf_tail);
210 buf_tail += SIG_BYTES as u32;
211
212 let final_ct = encrypt(
213 &key,
214 &aead_nonce(&self.config.nonce, counter, true),
215 &Uint8Array::new_with_length(0),
216 &buf.slice(0, buf_tail),
217 )
218 .await?;
219
220 w.feed(final_ct.into()).await?;
221
222 w.flush().await?;
223 w.close().await?;
224
225 Ok(())
226 }
227}
228
229fn aead_nonce(nonce: &[u8], counter: u32, last_block: bool) -> [u8; IV_SIZE] {
231 let mut iv = [0u8; IV_SIZE];
232
233 iv[..STREAM_NONCE_SIZE].copy_from_slice(nonce);
234 iv[STREAM_NONCE_SIZE..IV_SIZE - 1].copy_from_slice(&counter.to_be_bytes());
235 iv[IV_SIZE - 1] = last_block as u8;
236
237 iv
238}
239
240async fn read_atleast<R>(mut r: R, buf: &mut [u8], spill: &mut Vec<u8>) -> Result<(), Error>
241where
242 R: Stream<Item = Result<JsValue, JsValue>> + Unpin,
243{
244 let buf_len = buf.len();
245 let spill_len = spill.len();
246
247 if buf_len <= spill_len {
248 buf.copy_from_slice(&spill[..buf_len]);
249 spill.drain(..buf_len);
250
251 Ok(())
252 } else {
253 buf[..spill_len].copy_from_slice(&spill);
254 let mut rem = buf_len - spill_len;
255 spill.clear();
256
257 while let Some(Ok(data)) = r.next().await {
258 let arr: Uint8Array = data.dyn_into()?;
259 let len = arr.byte_length();
260
261 if len as usize >= rem {
262 buf[buf_len - rem..].copy_from_slice(&arr.slice(0, rem as u32).to_vec()[..]);
263 spill.extend_from_slice(&arr.slice(rem as u32, len).to_vec()[..]);
264 rem = 0;
265 break;
266 } else {
267 buf[buf_len - rem..buf_len - rem + len as usize].copy_from_slice(&arr.to_vec()[..]);
268 rem -= len as usize;
269 }
270 }
271
272 if rem == 0 {
273 Ok(())
274 } else {
275 Err(Error::FormatViolation("unexpected EOF".to_string()).into())
276 }
277 }
278}
279
280impl<R> Unsealer<R, StreamUnsealerConfig>
283where
284 R: Stream<Item = Result<JsValue, JsValue>> + Unpin,
285{
286 pub async fn new(mut r: R, vk: &VerifyingKey) -> Result<Self, Error> {
293 let mut spill = Vec::new();
294
295 let mut preamble = [0u8; PREAMBLE_SIZE];
296 read_atleast(&mut r, &mut preamble, &mut spill).await?;
297 let (version, header_len) = preamble_checked(&preamble)?;
298
299 let mut header_raw = vec![0u8; header_len];
300 read_atleast(&mut r, &mut header_raw, &mut spill).await?;
301
302 let mut h_sig_len_bytes = [0u8; SIG_SIZE_SIZE];
303 read_atleast(&mut r, &mut h_sig_len_bytes, &mut spill).await?;
304 let header_sig_len = u32::from_be_bytes(h_sig_len_bytes) as usize;
305
306 if header_sig_len > MAX_SIG_SIZE {
309 return Err(Error::ConstraintViolation);
310 }
311
312 let mut header_sig_raw = vec![0u8; header_sig_len];
313 read_atleast(&mut r, &mut header_sig_raw, &mut spill).await?;
314 let h_sig_ext: SignatureExt = crate::bincode_compat::deserialize(&header_sig_raw)?;
315
316 let verifier = Verifier::default().chain(&header_raw);
317 let pub_id = h_sig_ext.pol.derive_ibs()?;
318
319 if !verifier.clone().verify(&vk.0, &h_sig_ext.sig, &pub_id) {
320 return Err(Error::IncorrectSignature.into());
321 }
322
323 let header: Header = crate::bincode_compat::deserialize(&header_raw)?;
324 let (segment_size, _) = stream_mode_checked(&header)?;
325
326 Ok(Unsealer {
327 version,
328 header,
329 pub_id: h_sig_ext.pol,
330 verifier,
331 vk: vk.clone(),
332 r,
333 config: StreamUnsealerConfig {
334 spill,
335 segment_size,
336 },
337 })
338 }
339
340 pub async fn unseal<W>(
342 &mut self,
343 ident: &str,
344 usk: &UserSecretKey<CGWKV>,
345 mut w: W,
346 ) -> Result<VerificationResult, Error>
347 where
348 W: Sink<JsValue, Error = JsValue> + Unpin,
349 {
350 let rec_info = self
351 .header
352 .recipients
353 .get(ident)
354 .ok_or_else(|| Error::UnknownIdentifier(ident.to_string()))?;
355
356 let ss = rec_info.decaps(usk)?;
357 let key = get_key(&ss.0[..KEY_SIZE]).await?;
358
359 let Algorithm::Aes128Gcm(iv) = self.header.algo;
360 let nonce = &iv.0[..STREAM_NONCE_SIZE];
361
362 let segment_size: u32 = self.config.segment_size + (SIG_BYTES + TAG_SIZE) as u32;
363
364 let buf = Uint8Array::new_with_length(segment_size);
365 let mut counter = 0u32;
366 let mut buf_tail = 0;
367 let mut pol_id: Option<(Policy, Identity)> = None;
368
369 fn extract_policy(
370 plain: Uint8Array,
371 pub_id: &Policy,
372 ) -> Result<(Option<(Policy, Identity)>, Uint8Array), Error> {
373 if plain.byte_length() < POL_SIZE_SIZE as u32 {
374 return Err(Error::FormatViolation(alloc::string::String::from(
375 "policy length",
376 )));
377 }
378 let pol_len =
379 u32::from_be_bytes(plain.slice(0, POL_SIZE_SIZE as u32).to_vec()[..].try_into()?);
380 let pol_end = (POL_SIZE_SIZE as u32).checked_add(pol_len).ok_or_else(|| {
381 Error::FormatViolation(alloc::string::String::from("policy length overflow"))
382 })?;
383 if plain.byte_length() < pol_end {
384 return Err(Error::FormatViolation(alloc::string::String::from(
385 "policy truncated",
386 )));
387 }
388 let pol_bytes = plain.slice(POL_SIZE_SIZE as u32, pol_end).to_vec();
389 let (pol, read): (Policy, usize) =
390 crate::bincode_compat::deserialize_with_len(&pol_bytes)?;
391
392 if read < pol_bytes.len() {
400 let sealed_pub_pol: Policy =
401 crate::bincode_compat::deserialize(&pol_bytes[read..])?;
402
403 if &sealed_pub_pol != pub_id {
404 return Err(Error::IncorrectSignature.into());
405 }
406 }
407
408 let id = pol.derive_ibs()?;
409 let new_plain = plain.slice(pol_end, plain.byte_length());
410
411 Ok((Some((pol, id)), new_plain))
412 }
413
414 loop {
415 let mut array: Uint8Array = if !self.config.spill.is_empty() {
417 let arr = Uint8Array::from(&self.config.spill[..]);
418 self.config.spill.clear();
419 arr
420 } else if let Some(Ok(data)) = self.r.next().await {
421 data.dyn_into()?
422 } else {
423 break;
424 };
425
426 while array.byte_length() != 0 {
427 let len = array.byte_length();
428 let rem = buf.byte_length() - buf_tail;
429
430 if len < rem {
431 buf.set(&array, buf_tail);
432 array = Uint8Array::new_with_length(0);
433 buf_tail += len;
434 } else {
435 buf.set(&array.slice(0, rem), buf_tail);
436 array = array.slice(rem, len);
437
438 let mut plain = decrypt(
439 &key,
440 &aead_nonce(nonce, counter, false),
441 &Uint8Array::new_with_length(0),
442 &buf,
443 )
444 .await?;
445
446 if counter == 0 {
447 (pol_id, plain) = extract_policy(plain, &self.pub_id)?;
448 }
449
450 if plain.byte_length() < SIG_BYTES as u32 {
451 return Err(Error::FormatViolation(alloc::string::String::from(
452 "segment too short for signature",
453 ))
454 .into());
455 }
456
457 let m = plain.slice(0, plain.byte_length() - SIG_BYTES as u32);
458 let sig =
459 plain.slice(plain.byte_length() - SIG_BYTES as u32, plain.byte_length());
460 let sig: Signature = crate::bincode_compat::deserialize(&sig.to_vec())?;
461
462 self.verifier.update(&m.to_vec());
463
464 if !self
465 .verifier
466 .clone()
467 .chain(&counter.to_be_bytes())
468 .chain(&[0x00])
469 .verify(&self.vk.0, &sig, &pol_id.as_ref().unwrap().1)
470 {
471 return Err(Error::IncorrectSignature.into());
472 }
473
474 w.feed(m.into()).await?;
475
476 counter = counter.checked_add(1).ok_or(Error::Symmetric)?;
477 buf_tail = 0;
478 }
479 }
480 }
481
482 let mut final_plain = decrypt(
483 &key,
484 &aead_nonce(nonce, counter, true),
485 &Uint8Array::new_with_length(0),
486 &buf.slice(0, buf_tail),
487 )
488 .await?;
489
490 if counter == 0 {
491 (pol_id, final_plain) = extract_policy(final_plain, &self.pub_id)?;
492 }
493
494 if final_plain.byte_length() < SIG_BYTES as u32 {
495 return Err(Error::FormatViolation(alloc::string::String::from(
496 "final segment too short for signature",
497 ))
498 .into());
499 }
500 let m = final_plain.slice(0, final_plain.byte_length() - SIG_BYTES as u32);
501 let sig = final_plain.slice(
502 final_plain.byte_length() - SIG_BYTES as u32,
503 final_plain.byte_length(),
504 );
505
506 let sig: Signature = crate::bincode_compat::deserialize(&sig.to_vec())?;
507 self.verifier.update(&m.to_vec());
508 if !self
509 .verifier
510 .clone()
511 .chain(&counter.to_be_bytes())
512 .chain(&[0x01])
513 .verify(&self.vk.0, &sig, &pol_id.as_ref().unwrap().1)
514 {
515 return Err(Error::IncorrectSignature.into());
516 }
517
518 w.feed(m.into()).await?;
519
520 w.flush().await?;
521 w.close().await?;
522
523 let private_id = pol_id.unwrap().0;
524 let private = if self.pub_id == private_id {
525 None
526 } else {
527 Some(private_id)
528 };
529
530 Ok(VerificationResult {
531 public: self.pub_id.clone(),
532 private,
533 })
534 }
535}