crypt4gh/
lib.rs

1//! Bob wants to send a message to Alice, containing sensitive data. Bob uses [`Crypt4GH`, the Global Alliance approved secure method for sharing human genetic data][ga4gh].
2//! crypt4gh, a Python tool to encrypt, decrypt or re-encrypt files, according to the [GA4GH encryption file format](http://samtools.github.io/hts-specs/crypt4gh.pdf).
3//! [![How `Crypt4GH` works](https://i.imgur.com/5czeods.png)][ga4gh]
4//!
5//! To learn more about the format visit the [`Crypt4GH` CLI & Format Documentation][format-docs]
6//!
7//! [format-docs]: https://ega-archive.github.io/crypt4gh-rust/
8//! [ga4gh]: https://www.ga4gh.org/news/crypt4gh-a-secure-method-for-sharing-human-genetic-data/
9
10// TODO: Remove comment in the future
11// #![warn(missing_docs)]
12#![warn(rustdoc::missing_doc_code_examples)]
13#![allow(
14	clippy::missing_errors_doc,
15	clippy::missing_panics_doc,
16	clippy::module_name_repetitions,
17	clippy::must_use_candidate,
18	clippy::cast_possible_truncation,
19	clippy::similar_names,
20	clippy::implicit_hasher,
21	clippy::redundant_else
22)]
23
24use std::collections::HashSet;
25use std::io::{self, Read, Write};
26use std::sync::Once;
27
28use header::DecryptedHeaderPackets;
29use sodiumoxide::crypto::aead::chacha20poly1305_ietf::{self, Key, Nonce};
30
31use crate::error::Crypt4GHError;
32
33/// Generate and parse a `Crypt4GH` header.
34pub mod header;
35
36/// Utility to read Crypt4GH-formatted keys.
37pub mod keys;
38
39/// `Crypt4GH` Errors.
40pub mod error;
41
42const CHUNK_SIZE: usize = 4096;
43
44/// Size of the encrypted segments.
45pub const SEGMENT_SIZE: usize = 65_536;
46const CIPHER_DIFF: usize = 28;
47const CIPHER_SEGMENT_SIZE: usize = SEGMENT_SIZE + CIPHER_DIFF;
48
49/// Write buffer wrapper.
50/// * offset: Start writing on position = `offset`
51/// * limit: Write a maximum of `limit` bytes at the time
52/// * `write_buffer`: Write buffer
53pub struct WriteInfo<'a, W: Write> {
54	offset: usize,
55	limit: Option<usize>,
56	write_buffer: &'a mut W,
57}
58
59impl<'a, W: Write> WriteInfo<'a, W> {
60	/// Creates a new `WriteInfo`
61	pub fn new(offset: usize, limit: Option<usize>, write_buffer: &'a mut W) -> Self {
62		Self {
63			offset,
64			limit,
65			write_buffer,
66		}
67	}
68
69	fn write_all(&mut self, data: &[u8]) -> Result<(), Crypt4GHError> {
70		match &mut self.limit {
71			Some(limit) => {
72				if *limit >= data.len() {
73					self.write_buffer.write_all(data)?;
74					*limit -= data.len();
75				}
76				else {
77					self.write_buffer.write_all(&data[..*limit])?;
78					*limit = 0;
79				}
80			},
81			None => self.write_buffer.write_all(&data[self.offset..])?,
82		}
83		Ok(())
84	}
85}
86
87#[derive(Debug, PartialEq, Eq, Hash, Clone)]
88/// Key information.
89pub struct Keys {
90	/// Method used for the key encryption.
91	/// > Only method 0 is supported.
92	pub method: u8,
93	/// Secret key of the encryptor / decryptor (your key).
94	pub privkey: Vec<u8>,
95	/// Public key of the recipient (the key you want to encrypt for).
96	pub recipient_pubkey: Vec<u8>,
97}
98
99pub(crate) static SODIUM_INIT: Once = Once::new();
100
101pub(crate) fn init() {
102	SODIUM_INIT.call_once(|| {
103		sodiumoxide::init().expect("Unable to initialize libsodium");
104	});
105}
106
107/// Reads from the `read_buffer` and writes the encrypted data to `write_buffer`.
108///
109/// Reads from the `read_buffer` and writes the encrypted data (for every `recipient_key`) to `write_buffer`.
110/// If the range is specified, it will only encrypt the bytes from `range_start` to `range_start` + `range_span`.
111/// In case that `range_span` is none, it will encrypt from `range_start` to the end of the input.
112pub fn encrypt<R: Read, W: Write>(
113	recipient_keys: &HashSet<Keys>,
114	read_buffer: &mut R,
115	write_buffer: &mut W,
116	range_start: usize,
117	range_span: Option<usize>,
118) -> Result<(), Crypt4GHError> {
119	crate::init();
120	log::debug!("Start: {}, Span: {:?}", range_start, range_span);
121
122	if recipient_keys.is_empty() {
123		return Err(Crypt4GHError::NoRecipients);
124	}
125
126	log::info!("Encrypting the file");
127	log::debug!("    Start Coordinate: {}", range_start);
128
129	// Seek
130	if range_start > 0 {
131		log::info!("Forwarding to position: {}", range_start);
132	}
133
134	read_buffer
135		.by_ref()
136		.take(range_start as u64)
137		.read_to_end(&mut Vec::new())
138		.map_err(|e| Crypt4GHError::NotEnoughInput(range_start, e.into()))?;
139
140	log::debug!("    Span: {:?}", range_span);
141
142	log::info!("Creating Crypt4GH header");
143	let mut session_key = [0_u8; 32];
144	sodiumoxide::randombytes::randombytes_into(&mut session_key);
145	let header_bytes = encrypt_header(recipient_keys, &Some(session_key))?;
146
147	log::debug!("header length: {}", header_bytes.len());
148
149	write_buffer.write_all(&header_bytes)?;
150
151	log::info!("Streaming content");
152
153	let mut segment = [0_u8; SEGMENT_SIZE];
154
155	// The whole file
156	match range_span {
157		None | Some(0) => loop {
158			let segment_len = read_buffer.read(&mut segment)?;
159			if segment_len == 0 {
160				break;
161			}
162			else if segment_len < SEGMENT_SIZE {
163				let (data, _) = segment.split_at(segment_len);
164				let nonce = Nonce::from_slice(&sodiumoxide::randombytes::randombytes(12))
165					.ok_or(Crypt4GHError::NoRandomNonce)?;
166				let key = Key::from_slice(&session_key).ok_or(Crypt4GHError::NoKey)?;
167				let encrypted_data = encrypt_segment(data, nonce, &key);
168				write_buffer.write_all(&encrypted_data)?;
169				break;
170			}
171			else {
172				let nonce = Nonce::from_slice(&sodiumoxide::randombytes::randombytes(12))
173					.ok_or(Crypt4GHError::NoRandomNonce)?;
174				let key = Key::from_slice(&session_key).ok_or(Crypt4GHError::NoKey)?;
175				let encrypted_data = encrypt_segment(&segment, nonce, &key);
176				write_buffer.write_all(&encrypted_data)?;
177			}
178		},
179		Some(mut remaining_length) => {
180			while remaining_length > 0 {
181				let segment_len = read_buffer.read(&mut segment)?;
182
183				// Stop
184				if segment_len >= remaining_length {
185					let (data, _) = segment.split_at(remaining_length);
186					let nonce = Nonce::from_slice(&sodiumoxide::randombytes::randombytes(12))
187						.ok_or(Crypt4GHError::NoRandomNonce)?;
188					let key = Key::from_slice(&session_key).ok_or(Crypt4GHError::NoKey)?;
189					let encrypted_data = encrypt_segment(data, nonce, &key);
190					write_buffer.write_all(&encrypted_data)?;
191					break;
192				}
193
194				// Not a full segment
195				if segment_len < SEGMENT_SIZE {
196					let (data, _) = segment.split_at(segment_len);
197					let nonce = Nonce::from_slice(&sodiumoxide::randombytes::randombytes(12))
198						.ok_or(Crypt4GHError::NoRandomNonce)?;
199					let key = Key::from_slice(&session_key).ok_or(Crypt4GHError::NoKey)?;
200					let encrypted_data = encrypt_segment(data, nonce, &key);
201					write_buffer.write_all(&encrypted_data)?;
202					break;
203				}
204
205				let nonce = Nonce::from_slice(&sodiumoxide::randombytes::randombytes(12))
206					.ok_or(Crypt4GHError::NoRandomNonce)?;
207				let key = Key::from_slice(&session_key).ok_or(Crypt4GHError::NoKey)?;
208				let encrypted_data = encrypt_segment(&segment, nonce, &key);
209				write_buffer.write_all(&encrypted_data)?;
210
211				remaining_length -= segment_len;
212			}
213		},
214	}
215
216	log::info!("Encryption Successful");
217	Ok(())
218}
219
220/// Builds a header with a random session key
221///
222/// Returns the encrypted header bytes
223pub fn encrypt_header(
224	recipient_keys: &HashSet<Keys>,
225	session_key: &Option<[u8; 32]>,
226) -> Result<Vec<u8>, Crypt4GHError> {
227	let encryption_method = 0;
228	let session_key_or_new = session_key.unwrap_or_else(|| {
229		crate::init();
230		let mut session_key = [0_u8; 32];
231		sodiumoxide::randombytes::randombytes_into(&mut session_key);
232		session_key
233	});
234	let header_content = header::make_packet_data_enc(encryption_method, &session_key_or_new);
235	let header_packets = header::encrypt(&header_content, recipient_keys)?;
236	let header_bytes = header::serialize(header_packets);
237	Ok(header_bytes)
238}
239
240/// Encrypts a segment.
241///
242/// Returns [ nonce + `encrypted_data` ].
243pub fn encrypt_segment(data: &[u8], nonce: Nonce, key: &Key) -> Vec<u8> {
244	vec![nonce.0.to_vec(), chacha20poly1305_ietf::seal(data, None, &nonce, key)].concat()
245}
246
247/// Reads from the `read_buffer` and writes the decrypted data to `write_buffer`.
248///
249/// Reads from the `read_buffer` and writes the decrypted data to `write_buffer`.
250/// If the range is specified, it will only encrypt the bytes from `range_start` to `range_start` + `range_span`.
251/// In case that `range_span` is none, it will encrypt from `range_start` to the end of the input.
252/// If `sender_pubkey` is specified the program will check that the `recipient_key` in the message
253/// is the same as the `sender_pubkey`.
254pub fn decrypt<R: Read, W: Write>(
255	keys: &[Keys],
256	read_buffer: &mut R,
257	write_buffer: &mut W,
258	range_start: usize,
259	range_span: Option<usize>,
260	sender_pubkey: &Option<Vec<u8>>,
261) -> Result<(), Crypt4GHError> {
262	range_span.map_or_else(
263		|| {
264			log::info!("Decrypting file | Range: [{}, EOF)", range_start);
265		},
266		|span| {
267			log::info!("Decrypting file | Range: [{}, {})", range_start, range_start + span + 1);
268		},
269	);
270
271	// Get header info
272	let mut temp_buf = [0_u8; 16]; // Size of the header
273	read_buffer
274		.read_exact(&mut temp_buf)
275		.map_err(|e| Crypt4GHError::ReadHeaderError(e.into()))?;
276	let header_info: header::HeaderInfo = header::deconstruct_header_info(&temp_buf)?;
277
278	// Calculate header packets
279	let encrypted_packets = (0..header_info.packets_count)
280		.map(|_| {
281			// Get length
282			let mut length_buffer = [0_u8; 4];
283			read_buffer
284				.read_exact(&mut length_buffer)
285				.map_err(|e| Crypt4GHError::ReadHeaderPacketLengthError(e.into()))?;
286			let length = bincode::deserialize::<u32>(&length_buffer)
287				.map_err(|e| Crypt4GHError::ParseHeaderPacketLengthError(e))?;
288			let length = length - 4;
289
290			// Get data
291			let mut encrypted_data = vec![0_u8; length as usize];
292			read_buffer
293				.read_exact(&mut encrypted_data)
294				.map_err(|e| Crypt4GHError::ReadHeaderPacketDataError(e.into()))?;
295			Ok(encrypted_data)
296		})
297		.collect::<Result<Vec<Vec<u8>>, Crypt4GHError>>()?;
298
299	let DecryptedHeaderPackets {
300		data_enc_packets: session_keys,
301		edit_list_packet: edit_list,
302	} = header::deconstruct_header_body(encrypted_packets, keys, sender_pubkey)?;
303
304	range_span.map_or_else(
305		|| {
306			log::info!("Slicing from {} | Keeping all bytes", range_start);
307		},
308		|span| {
309			log::info!("Slicing from {} | Keeping {} bytes", range_start, span);
310		},
311	);
312
313	if range_span.is_some() && range_span.unwrap() == 0 {
314		return Err(Crypt4GHError::InvalidRangeSpan(range_span));
315	}
316
317	let mut write_info = WriteInfo::new(range_start, range_span, write_buffer);
318
319	match edit_list {
320		None => body_decrypt(read_buffer, &session_keys, &mut write_info, range_start)?,
321		Some(edit_list_content) => body_decrypt_parts(read_buffer, session_keys, write_info, edit_list_content)?,
322	}
323
324	log::info!("Decryption Over");
325	Ok(())
326}
327
328struct DecryptedBuffer<'a, W: Write> {
329	read_buffer: &'a mut dyn Read,
330	session_keys: Vec<Vec<u8>>,
331	buf: Vec<u8>,
332	is_decrypted: bool,
333	block: u64,
334	output: WriteInfo<'a, W>,
335	index: usize,
336}
337
338impl<'a, W: Write> DecryptedBuffer<'a, W> {
339	fn new(read_buffer: &'a mut impl Read, session_keys: Vec<Vec<u8>>, output: WriteInfo<'a, W>) -> Self {
340		let mut decryptor = Self {
341			read_buffer,
342			session_keys,
343			buf: Vec::with_capacity(CIPHER_SEGMENT_SIZE),
344			is_decrypted: false,
345			block: 0,
346			output,
347			index: 0,
348		};
349
350		decryptor.fetch();
351		decryptor.decrypt();
352		log::debug!("Index = {}", decryptor.index);
353		log::debug!("");
354		decryptor
355	}
356
357	fn fetch(&mut self) {
358		log::debug!("Fetching block {}", self.block);
359		self.block += 1;
360
361		// Fetches a block
362		self.buf.clear();
363		self.read_buffer
364			.take(CIPHER_SEGMENT_SIZE as u64)
365			.read_to_end(&mut self.buf)
366			.unwrap();
367
368		self.is_decrypted = false;
369		log::debug!("");
370	}
371
372	fn decrypt(&mut self) {
373		// Decrypts its buffer
374		if !self.is_decrypted {
375			log::debug!("Decrypting block");
376			self.buf = decrypt_block(&self.buf, &self.session_keys).unwrap();
377			self.is_decrypted = true;
378		}
379		log::debug!("");
380	}
381
382	fn skip(&mut self, size: usize) {
383		assert!(size > 0, "You shouldn't skip 0 bytes");
384		log::debug!("Skipping {} bytes | Buffer size: {}", size, self.buf.len());
385
386		let mut remaining_size = size;
387
388		// Skip fetches
389		while remaining_size > 0 {
390			log::debug!("Left to skip: {} | Buffer size: {}", remaining_size, self.buf.len());
391
392			if remaining_size >= SEGMENT_SIZE {
393				self.fetch();
394				remaining_size -= SEGMENT_SIZE;
395			}
396			else {
397				if (self.index + remaining_size) > SEGMENT_SIZE {
398					self.fetch();
399				}
400				self.index = (self.index + remaining_size) % SEGMENT_SIZE;
401				log::debug!("Index = {}", self.index);
402				remaining_size -= remaining_size;
403			}
404		}
405
406		log::debug!("Finished skipping");
407		log::debug!("");
408
409		// Apply
410		self.decrypt();
411	}
412
413	fn read(&mut self, size: usize) -> usize {
414		assert!(size > 0, "You shouldn't read 0 bytes");
415		log::debug!("Reading {} bytes | Buffer size: {}", size, self.buf.len());
416
417		let mut remaining_size = size;
418
419		while remaining_size > 0 {
420			// Get read length
421			log::debug!("Left to read: {} | Buffer size: {}", remaining_size, self.buf.len());
422			let n_bytes = usize::min(SEGMENT_SIZE - self.index, remaining_size);
423
424			// Process
425			self.decrypt();
426			self.output
427				.write_all(&self.buf[self.index..self.index + n_bytes])
428				.unwrap();
429
430			// Advance
431			self.index = (self.index + n_bytes) % self.buf.len();
432			log::debug!("Index = {}", self.index);
433			if self.index == 0 {
434				self.fetch();
435			}
436
437			// Reduce
438			remaining_size -= n_bytes;
439		}
440
441		log::debug!("Finished reading");
442		log::debug!("");
443
444		size
445	}
446}
447
448/// Decrypts the specified content read using the keys provided.
449///
450/// Reads the bytes of the buffer and decrypts it using the `session_keys`.
451/// Writes the decrypted bytes using the write buffer provided. It skips
452/// the first `range_start` bytes. It uses the `edit_list` packets.
453pub fn body_decrypt_parts<W: Write>(
454	mut read_buffer: impl Read,
455	session_keys: Vec<Vec<u8>>,
456	output: WriteInfo<W>,
457	edit_list: Vec<u64>,
458) -> Result<(), Crypt4GHError> {
459	log::debug!("Edit List: {:?}", edit_list);
460
461	if edit_list.is_empty() {
462		return Err(Crypt4GHError::EmptyEditList);
463	}
464
465	let mut decrypted = DecryptedBuffer::new(&mut read_buffer, session_keys, output);
466
467	let mut skip = true;
468
469	for edit_length in edit_list {
470		if skip {
471			if edit_length != 0 {
472				decrypted.skip(edit_length as usize);
473			}
474		}
475		else {
476			decrypted.read(edit_length as usize);
477		}
478		skip = !skip;
479	}
480
481	if !skip {
482		// If we finished with a skip, read until the end
483		loop {
484			let n = decrypted.read(SEGMENT_SIZE);
485			if n == 0 {
486				break;
487			}
488		}
489	}
490
491	Ok(())
492}
493
494/// Decrypts the content read using the keys provided.
495///
496/// Reads the bytes of the buffer and decrypts it using the `session_keys`.
497/// Writes the decrypted bytes using the write buffer provided. It skips
498/// the first `range_start` bytes.
499pub fn body_decrypt<W: Write>(
500	mut read_buffer: impl Read,
501	session_keys: &[Vec<u8>],
502	output: &mut WriteInfo<W>,
503	range_start: usize,
504) -> Result<(), Crypt4GHError> {
505	if range_start >= SEGMENT_SIZE {
506		let start_segment = range_start / SEGMENT_SIZE;
507		log::info!("Fast-forwarding {} segments", start_segment);
508		let start_ciphersegment = start_segment * CIPHER_SEGMENT_SIZE;
509		read_buffer
510			.read_exact(&mut vec![0_u8; start_ciphersegment])
511			.map_err(|e| Crypt4GHError::BadStartRange(e.into()))?;
512	}
513
514	loop {
515		let mut chunk = Vec::with_capacity(CIPHER_SEGMENT_SIZE);
516		let n = read_buffer
517			.by_ref()
518			.take(CIPHER_SEGMENT_SIZE as u64)
519			.read_to_end(&mut chunk)
520			.map_err(|e| Crypt4GHError::ReadBlockError(e.into()))?;
521
522		if n == 0 {
523			break;
524		}
525
526		let segment = decrypt_block(&chunk, session_keys)?;
527		output
528			.write_all(&segment)
529			.map_err(|e| Crypt4GHError::UnableToWrite(e.into()))?;
530
531		if n < CIPHER_SEGMENT_SIZE {
532			break;
533		}
534	}
535
536	Ok(())
537}
538
539fn decrypt_block(ciphersegment: &[u8], session_keys: &[Vec<u8>]) -> Result<Vec<u8>, Crypt4GHError> {
540	let (nonce_slice, data) = ciphersegment.split_at(12);
541	let nonce = Nonce::from_slice(nonce_slice).ok_or(Crypt4GHError::UnableToWrapNonce)?;
542
543	session_keys
544		.iter()
545		.find_map(|key| Key::from_slice(key).and_then(|key| chacha20poly1305_ietf::open(data, None, &nonce, &key).ok()))
546		.ok_or(Crypt4GHError::UnableToDecryptBlock)
547}
548
549/// Reads from the `read_buffer` and writes the reencrypted data to `write_buffer`.
550///
551/// Reads from the `read_buffer` and writes the reencrypted data to `write_buffer`.
552/// It will decrypt the message using the key in `keys` and then reencrypt it for the
553/// recipient keys specified in `recipient_keys`. If `trim` is true, it will discard
554/// the packages that cannot be decrypted.
555pub fn reencrypt<R: Read, W: Write>(
556	keys: &[Keys],
557	recipient_keys: &HashSet<Keys>,
558	read_buffer: &mut R,
559	write_buffer: &mut W,
560	trim: bool,
561) -> Result<(), Crypt4GHError> {
562	// Get header info
563	let mut temp_buf = [0_u8; 16]; // Size of the header
564	read_buffer
565		.read_exact(&mut temp_buf)
566		.map_err(|e| Crypt4GHError::ReadHeaderError(e.into()))?;
567	let header_info: header::HeaderInfo = header::deconstruct_header_info(&temp_buf)?;
568
569	// Calculate header packets
570	let header_packets = (0..header_info.packets_count)
571		.map(|_| {
572			// Get length
573			let mut length_buffer = [0_u8; 4];
574			read_buffer
575				.read_exact(&mut length_buffer)
576				.map_err(|e| Crypt4GHError::ReadHeaderPacketLengthError(e.into()))?;
577			let length = bincode::deserialize::<u32>(&length_buffer)
578				.map_err(|e| Crypt4GHError::ParseHeaderPacketLengthError(e))?;
579			let length = length - 4;
580
581			// Get data
582			let mut encrypted_data = vec![0_u8; length as usize];
583			read_buffer
584				.read_exact(&mut encrypted_data)
585				.map_err(|e| Crypt4GHError::ReadHeaderPacketDataError(e.into()))?;
586			Ok(encrypted_data)
587		})
588		.collect::<Result<Vec<Vec<u8>>, Crypt4GHError>>()?;
589
590	let packets = header::reencrypt(header_packets, keys, recipient_keys, trim)?;
591	write_buffer.write_all(&header::serialize(packets))?;
592
593	log::info!("Streaming the remainder of the file");
594
595	loop {
596		let mut buf = Vec::with_capacity(CHUNK_SIZE);
597		let data = read_buffer.by_ref().take(CHUNK_SIZE as u64).read_to_end(&mut buf);
598
599		match data {
600			Ok(0) => break,
601			Ok(n) => write_buffer.write_all(&buf[0..n])?,
602			Err(e) if e.kind() == io::ErrorKind::Interrupted => (),
603			Err(e) => return Err(Crypt4GHError::ReadRemainderError(e.into())),
604		}
605	}
606
607	log::info!("Reencryption successful");
608
609	Ok(())
610}
611
612/// Reads from the `read_buffer` and writes the rearranged data to `write_buffer`.
613///
614/// Reads from the `read_buffer` and writes the rearranged data to `write_buffer`.
615/// If the range is specified, it will only rearrange the bytes from `range_start` to `range_start` + `range_span`.
616/// In case that `range_span` is none, it will rearrange from `range_start` to the end of the input.
617pub fn rearrange<R: Read, W: Write>(
618	keys: Vec<Keys>,
619	read_buffer: &mut R,
620	write_buffer: &mut W,
621	range_start: usize,
622	range_span: Option<usize>,
623) -> Result<(), Crypt4GHError> {
624	// Get header info
625	let mut temp_buf = [0_u8; 16]; // Size of the header
626	read_buffer
627		.read_exact(&mut temp_buf)
628		.map_err(|e| Crypt4GHError::ReadHeaderError(e.into()))?;
629	let header_info: header::HeaderInfo = header::deconstruct_header_info(&temp_buf)?;
630
631	// Calculate header packets
632	let header_packets = (0..header_info.packets_count)
633		.map(|_| {
634			// Get length
635			let mut length_buffer = [0_u8; 4];
636			read_buffer
637				.read_exact(&mut length_buffer)
638				.map_err(|e| Crypt4GHError::ReadHeaderPacketLengthError(e.into()))?;
639			let length = bincode::deserialize::<u32>(&length_buffer)
640				.map_err(|e| Crypt4GHError::ParseHeaderPacketLengthError(e))?;
641			let length = length - 4;
642
643			// Get data
644			let mut encrypted_data = vec![0_u8; length as usize];
645			read_buffer
646				.read_exact(&mut encrypted_data)
647				.map_err(|e| Crypt4GHError::ReadHeaderPacketDataError(e.into()))?;
648			Ok(encrypted_data)
649		})
650		.collect::<Result<Vec<Vec<u8>>, Crypt4GHError>>()?;
651
652	let (packets, mut segment_oracle) = header::rearrange(header_packets, keys, range_start, range_span, &None)?;
653	write_buffer.write_all(&header::serialize(packets))?;
654
655	log::info!("Streaming the remainder of the file");
656
657	loop {
658		let mut buf = Vec::with_capacity(SEGMENT_SIZE + CIPHER_DIFF);
659		let data = read_buffer
660			.by_ref()
661			.take((SEGMENT_SIZE + CIPHER_DIFF) as u64)
662			.read_to_end(&mut buf);
663
664		let keep_segment = segment_oracle.next().unwrap();
665
666		log::debug!("Keep segment: {:?}", keep_segment);
667
668		match data {
669			Ok(0) => break,
670			Ok(n) => {
671				if keep_segment {
672					write_buffer.write_all(&buf[0..n])?;
673				}
674			},
675			Err(e) if e.kind() == io::ErrorKind::Interrupted => (),
676			Err(e) => return Err(Crypt4GHError::ReadRemainderError(e.into())),
677		}
678	}
679
680	log::info!("Rearrangement successful");
681
682	Ok(())
683}