use cipher::zeroize::Zeroize;
use std::cell::RefCell;
use std::cmp::min;
use std::fmt;
use std::io::{Read, Write};
use std::rc::Rc;
use crate::argon::Argon;
use crate::asymmetric::{
BottlePublicKey, BottleSecretKey, Ed25519PublicKey,
EncryptedKeyHeader, PublicKeyAlgorithm, public_key_from_header
};
use crate::bottle::{BottleReader, BottleStream, BottleWriter};
use crate::bottle_cap::BottleType;
use crate::bottle_error::{BottleError, BottleResult};
use crate::encryption::{
check_key_commitment, commit_key, cprng, encryption_for,
EncryptionAlgorithm, EncryptionCipher
};
use crate::header::Header;
use crate::header_stream::{read_header_stream, write_header_stream};
use crate::streams::{ReadStream, ReadStreamRef};
const FIELD_ENCRYPTION_TYPE_INT: u8 = 0;
const FIELD_BLOCK_SIZE_BITS_INT: u8 = 1;
const FIELD_RECIPIENT_COUNT_INT: u8 = 2;
const FIELD_PUBLIC_KEY_TYPE_INT: u8 = 3;
const FIELD_ARGON_PARAMS_BYTES: u8 = 0;
const FIELD_ARGON_KEY_BYTES: u8 = 1;
const FIELD_KEY_COMMITMENT: u8 = 2;
const DEFAULT_BLOCK_SIZE_BITS: usize = 20;
const COMMITMENT_SIZE: usize = 32;
#[derive(Clone, Debug, PartialEq)]
pub enum EncryptionKey {
Generated,
Key(Vec<u8>),
Password(String),
}
#[derive(Clone, Debug, PartialEq)]
pub struct EncryptedBottleWriterOptions {
pub algorithm: EncryptionAlgorithm,
pub block_size_bits: usize,
pub key: EncryptionKey,
pub argon: Option<Argon>,
pub write_old_x25519_keys: bool,
pub omit_key_commitment: bool,
}
impl EncryptedBottleWriterOptions {
pub fn new() -> EncryptedBottleWriterOptions {
EncryptedBottleWriterOptions {
algorithm: EncryptionAlgorithm::XCHACHA20_POLY1305,
block_size_bits: DEFAULT_BLOCK_SIZE_BITS, key: EncryptionKey::Generated,
argon: None,
write_old_x25519_keys: false,
omit_key_commitment: false,
}
}
}
impl Default for EncryptedBottleWriterOptions {
fn default() -> Self {
EncryptedBottleWriterOptions::new()
}
}
pub struct EncryptedBottleWriter<W: Write> {
bottle_writer: BottleWriter<W>,
encryption_cipher: Box<dyn EncryptionCipher>,
buffer: Vec<u8>,
buffer_used: usize,
}
impl<W: Write> EncryptedBottleWriter<W> {
pub fn for_recipients<K: BottlePublicKey>(
writer: W,
options: EncryptedBottleWriterOptions,
public_keys: &[K],
) -> BottleResult<EncryptedBottleWriter<W>> {
let encryption = encryption_for(options.algorithm)?;
let mut header = Header::new();
header.add_int(FIELD_ENCRYPTION_TYPE_INT, options.algorithm as u64)?;
header.add_int(FIELD_BLOCK_SIZE_BITS_INT, options.block_size_bits as u64)?;
if !public_keys.is_empty() {
header.add_int(FIELD_RECIPIENT_COUNT_INT, public_keys.len() as u64)?;
header.add_int(FIELD_PUBLIC_KEY_TYPE_INT, public_keys[0].algorithm() as u64)?;
}
let mut key = vec![0u8; encryption.key_length()];
match options.key {
EncryptionKey::Generated => cprng(&mut key)?,
EncryptionKey::Key(ref supplied) => {
if supplied.len() != encryption.key_length() { return Err(BottleError::BadKeySize); }
key.copy_from_slice(supplied);
},
EncryptionKey::Password(ref password) => {
cprng(&mut key)?;
let argon = options.argon.unwrap_or(Argon::new()?);
let mut buffer = [0u8; 64];
header.add_bytes(FIELD_ARGON_PARAMS_BYTES, argon.encode(&mut buffer))?;
let argon_key = argon.generate_key(&mut buffer[0 .. encryption.key_key_length()], password.as_bytes())?;
let mut buffer2 = [0u8; 64];
let encrypted_key = &mut buffer2[..encryption.key_length()];
encryption.encrypt_key(encrypted_key, &key, argon_key);
header.add_bytes(FIELD_ARGON_KEY_BYTES, encrypted_key)?;
},
};
if !options.omit_key_commitment {
header.add_bytes(FIELD_KEY_COMMITMENT, &commit_key::<COMMITMENT_SIZE>(&key)?)?;
}
let mut bottle_writer = BottleWriter::new(writer, BottleType::Encrypted, header, options.block_size_bits)?;
for public_key in public_keys {
write_header_stream(&mut bottle_writer, &public_key.to_header(&key, options.write_old_x25519_keys)?)?;
}
bottle_writer.write_data_stream()?;
let encryption_cipher = encryption.create(&key);
key.zeroize();
let buffer = vec![0u8; 1 << options.block_size_bits];
Ok(EncryptedBottleWriter { bottle_writer, encryption_cipher, buffer, buffer_used: 0 })
}
pub fn new(writer: W, options: EncryptedBottleWriterOptions) -> BottleResult<EncryptedBottleWriter<W>> {
EncryptedBottleWriter::for_recipients(writer, options, &[] as &[Ed25519PublicKey])
}
fn write_block(&mut self) -> std::io::Result<usize> {
if self.buffer_used == 0 {
return Ok(0);
}
let buffer = &mut self.buffer[0 .. self.buffer_used];
let mut metadata_buffer = [0u8; 64];
let metadata = &mut metadata_buffer[0 .. self.encryption_cipher.encryption().metadata_length()];
self.encryption_cipher.encrypt_block(buffer, metadata).map_err(|e| e.to_io_error())?;
self.bottle_writer.write_all(metadata)?;
self.bottle_writer.write_all(buffer)?;
Ok(metadata.len() + buffer.len())
}
pub fn close(mut self) -> BottleResult<W> {
self.write_block()?;
self.bottle_writer.close_stream()?;
self.bottle_writer.close()
}
}
impl<W: Write> Write for EncryptedBottleWriter<W> {
fn write(&mut self, data: &[u8]) -> std::io::Result<usize> {
let len = min(self.buffer.len() - self.buffer_used, data.len());
self.buffer[self.buffer_used .. self.buffer_used + len].copy_from_slice(&data[..len]);
self.buffer_used += len;
if self.buffer_used == self.buffer.len() {
self.write_block()?;
self.buffer_used = 0;
}
Ok(len)
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
pub struct EncryptedBottleReaderOptions<'a> {
pub key_type: EncryptionKey,
pub possible_keys: Option<&'a [Box<dyn BottleSecretKey>]>,
pub allow_missing_key_commitment: bool,
}
impl EncryptedBottleReaderOptions<'_> {
pub fn new(key_type: EncryptionKey) -> EncryptedBottleReaderOptions<'static> {
EncryptedBottleReaderOptions {
key_type,
possible_keys: None,
allow_missing_key_commitment: false,
}
}
pub fn with_keys(possible_keys: &[Box<dyn BottleSecretKey>]) -> EncryptedBottleReaderOptions<'_> {
EncryptedBottleReaderOptions {
key_type: EncryptionKey::Generated,
possible_keys: Some(possible_keys),
allow_missing_key_commitment: false,
}
}
}
impl Default for EncryptedBottleReaderOptions<'static> {
fn default() -> Self {
EncryptedBottleReaderOptions::new(EncryptionKey::Generated)
}
}
impl fmt::Debug for EncryptedBottleReaderOptions<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f, "EncryptedBottleReaderOptions(key_type={:?}, possible_keys={}, allow_missing_key_commitment={:?})",
self.key_type,
self.possible_keys.map_or(0, |v| v.len()),
self.allow_missing_key_commitment,
)
}
}
#[derive(Debug)]
pub struct EncryptedBottleReader<R: Read> {
bottle_reader: BottleReader<R>,
encryption_cipher: Box<dyn EncryptionCipher>,
buffer: Vec<u8>,
buffer_used: usize,
buffer_size: usize,
pub info: Option<EncryptedBottleInfo>,
}
#[derive(Debug)]
pub struct EncryptedBottleInfo {
pub algorithm: EncryptionAlgorithm,
pub public_key_algorithm: PublicKeyAlgorithm,
pub block_size_bits: u64,
pub argon: Option<Argon>,
pub encrypted_key: Option<Vec<u8>>,
pub public_encrypted_keys: Vec<EncryptedKeyHeader>,
pub key_commitment: Option<Vec<u8>>,
}
impl<R: Read> EncryptedBottleReader<R> {
pub fn unpack_info(
bottle_reader: &mut BottleReader<R>,
) -> BottleResult<EncryptedBottleInfo> {
let header = &bottle_reader.bottle_cap.header;
bottle_reader.expect_type(BottleType::Encrypted)?;
let id = header.get_int(FIELD_ENCRYPTION_TYPE_INT).ok_or(BottleError::UnknownEncryption)?;
let algorithm: EncryptionAlgorithm = (id as u8).try_into().map_err(|_| BottleError::UnknownEncryption)?;
let block_size_bits = header.get_int(FIELD_BLOCK_SIZE_BITS_INT).unwrap_or(DEFAULT_BLOCK_SIZE_BITS as u64);
let argon = header.get_bytes(FIELD_ARGON_PARAMS_BYTES).map(Argon::decode);
let encrypted_key = header.get_bytes(FIELD_ARGON_KEY_BYTES).map(|k| k.to_vec());
let recipient_count = header.get_int(FIELD_RECIPIENT_COUNT_INT).unwrap_or(0);
let id = header.get_int(FIELD_PUBLIC_KEY_TYPE_INT).unwrap_or(0);
let public_key_algorithm: PublicKeyAlgorithm =
(id as u8).try_into().map_err(|_| BottleError::UnknownEncryption)?;
let key_commitment = header.get_bytes(FIELD_KEY_COMMITMENT).map(|b| b.to_vec());
let public_encrypted_keys: Result<Vec<_>, BottleError> = (0..recipient_count).map(|_i| {
let header = read_header_stream(bottle_reader)?;
public_key_from_header(public_key_algorithm, header).ok_or(BottleError::CorruptPublicKey)
}).collect();
let public_encrypted_keys = public_encrypted_keys?;
Ok(EncryptedBottleInfo {
algorithm, public_key_algorithm, block_size_bits, argon, encrypted_key, public_encrypted_keys,
key_commitment,
})
}
pub fn build_with_info(
mut bottle_reader: BottleReader<R>,
info: &EncryptedBottleInfo,
options: EncryptedBottleReaderOptions<'_>,
) -> BottleResult<EncryptedBottleReader<R>> {
let encryption = encryption_for(info.algorithm)?;
let possible_key_count = options.possible_keys.map_or(0, |v| v.len());
let mut key = vec![0u8; encryption.key_length()];
match options.key_type {
EncryptionKey::Generated => {
if possible_key_count == 0 || info.public_encrypted_keys.is_empty() {
return Err(BottleError::RequiresKey);
}
}
EncryptionKey::Key(ref supplied) => {
if supplied.len() != encryption.key_length() { return Err(BottleError::BadKeySize); }
key.copy_from_slice(supplied);
},
EncryptionKey::Password(ref password) => {
let argon = info.argon.ok_or(BottleError::NotPasswordEncrypted)?;
let encrypted_key = info.encrypted_key.as_ref().ok_or(BottleError::NotPasswordEncrypted)?;
let mut buffer = [0u8; 64];
let argon_key = argon.generate_key(&mut buffer[0 .. encryption.key_key_length()], password.as_bytes())?;
encryption.decrypt_key(&mut key, encrypted_key, argon_key);
},
}
let mut found_key = options.key_type != EncryptionKey::Generated;
if !found_key && let Some(possible_keys) = options.possible_keys {
for key_header in &info.public_encrypted_keys {
for sk in possible_keys {
if !found_key && sk.matches_public_key(key_header.public_key.as_ref()) {
key = sk.decrypt(&key_header.encrypted_key)?;
found_key = true;
}
}
}
}
if !found_key {
return Err(
BottleError::NoMatchingPublicKey(
info.public_encrypted_keys.iter().map(|ek| String::from(ek.public_key.name())).collect()
)
)
}
if info.key_commitment.is_none() && !options.allow_missing_key_commitment {
return Err(BottleError::NoKeyCommitment);
}
if let Some(key_commitment) = &info.key_commitment && !check_key_commitment(&key, key_commitment) {
return Err(BottleError::BadKeyCommitment);
}
let encryption_cipher = encryption.create(&key);
key.zeroize();
bottle_reader.expect_next_stream(BottleStream::Data)?;
let buffer = vec![0u8; (1 << info.block_size_bits) + encryption.metadata_length()];
Ok(EncryptedBottleReader {
bottle_reader, encryption_cipher, info: None, buffer, buffer_used: 0, buffer_size: 0
})
}
pub fn build(
mut bottle_reader: BottleReader<R>,
options: EncryptedBottleReaderOptions,
) -> BottleResult<EncryptedBottleReader<R>> {
let info = EncryptedBottleReader::unpack_info(&mut bottle_reader)?;
let mut ret = EncryptedBottleReader::build_with_info(bottle_reader, &info, options)?;
ret.info = Some(info);
Ok(ret)
}
fn finish_stream(&mut self) -> BottleResult<()> {
self.bottle_reader.close_stream()?;
self.bottle_reader.expect_end_and_finish()
}
pub fn close(mut self) -> BottleResult<R> {
self.bottle_reader.close_stream()?;
self.bottle_reader.expect_end_and_close()
}
pub fn next_block(&mut self) -> std::io::Result<usize> {
let mut i = 0;
while i < self.buffer.len() {
let n = self.bottle_reader.data_stream().map_err(|e| e.to_io_error())?.read(&mut self.buffer[i..])?;
i += n;
if n == 0 { break; }
}
self.buffer_size = i;
self.buffer_used = 0;
if self.buffer_size == 0 { return Ok(0) }
let metadata_len = self.encryption_cipher.encryption().metadata_length();
if self.buffer_size < metadata_len {
return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "Short block"));
}
let (metadata, block) = self.buffer.split_at_mut(metadata_len);
self.buffer_used = metadata_len;
let block_size = self.buffer_size - metadata_len;
self.encryption_cipher.decrypt_block(&mut block[..block_size], metadata).map_err(|e| e.to_io_error())?;
Ok(self.buffer_size - self.buffer_used)
}
}
impl<R: fmt::Debug + Read + 'static> EncryptedBottleReader<R> {
pub fn stream(self) -> ReadStreamRef {
ReadStreamRef::new(Rc::new(RefCell::new(self)))
}
}
impl<R: fmt::Debug + Read> ReadStream for EncryptedBottleReader<R> {
fn finish(&mut self) -> BottleResult<()> {
self.finish_stream()
}
}
impl<R: Read> Read for EncryptedBottleReader<R> {
fn read(&mut self, buffer: &mut [u8]) -> std::io::Result<usize> {
if self.buffer_used == self.buffer_size {
self.next_block()?;
}
if self.buffer_used == self.buffer_size {
return Ok(0);
}
let len = min(self.buffer_size - self.buffer_used, buffer.len());
buffer[0 .. len].copy_from_slice(&self.buffer[self.buffer_used .. self.buffer_used + len]);
self.buffer_used += len;
Ok(len)
}
}
#[cfg(test)]
mod test {
use hex::decode;
use std::io::{Read, Write};
use crate::{BottleError, BottleSecretKey, EncryptionAlgorithm};
use crate::asymmetric::{Ed25519PublicKey, Ed25519SecretKey};
use crate::bottle::{BottleReader, BottleStream, BottleWriter};
use crate::bottle_cap::BottleType;
use crate::header::Header;
use super::{
EncryptedBottleReader, EncryptedBottleReaderOptions, EncryptedBottleWriter, EncryptedBottleWriterOptions,
EncryptionKey
};
#[test]
fn known_key() {
let key_data = decode("826e3631501115482ee5808dbceaec06").unwrap();
let data = b"And the things I do, not set in stone";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.algorithm = EncryptionAlgorithm::AES_128_GCM;
options.key = EncryptionKey::Key(key_data.clone());
{
let mut bottle_writer = EncryptedBottleWriter::new(&mut buffer, options).unwrap();
bottle_writer.write_all(data).unwrap();
bottle_writer.close().unwrap();
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let mut encrypted_bottle_reader = EncryptedBottleReader::build(
bottle_reader,
EncryptedBottleReaderOptions::new(EncryptionKey::Key(key_data.clone()))
).unwrap();
let mut data_buffer = Vec::new();
let len = encrypted_bottle_reader.read_to_end(&mut data_buffer).unwrap();
encrypted_bottle_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
#[test]
fn password() {
let password = "trespass";
let data = b"And the things I do, not set in stone";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.key = EncryptionKey::Password(String::from(password));
{
let mut bottle_writer = EncryptedBottleWriter::new(&mut buffer, options).unwrap();
bottle_writer.write_all(data).unwrap();
bottle_writer.close().unwrap();
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let mut encrypted_bottle_reader = EncryptedBottleReader::build(
bottle_reader,
EncryptedBottleReaderOptions::new(EncryptionKey::Password(String::from(password)))
).unwrap();
let mut data_buffer = Vec::new();
let len = encrypted_bottle_reader.read_to_end(&mut data_buffer).unwrap();
encrypted_bottle_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
#[test]
fn public_key_old_x25519() {
const PK_HEX: &str = "112905df7c79c726b6250ec6e87aaa35d9127e2f48736a65c7352e8768d77865";
const SK_HEX: &str = "bc29877fa28b3e03ea6b58d35818e65a1fb4870dae35c4a452de880205108efb";
let pk = Ed25519PublicKey::from_ssh_bytes(&hex::decode(PK_HEX).unwrap(), String::from("eeyore")).unwrap();
let sk = Ed25519SecretKey::from_ssh_bytes(&hex::decode(SK_HEX).unwrap(), String::from("eeyore")).unwrap();
let data = b"And the things I do, not set in stone";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.key = EncryptionKey::Generated;
options.write_old_x25519_keys = true;
{
let recipients = [ pk ];
let mut bottle_writer = EncryptedBottleWriter::for_recipients(&mut buffer, options, &recipients).unwrap();
bottle_writer.write_all(data).unwrap();
bottle_writer.close().unwrap();
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let mut encrypted_bottle_reader =
EncryptedBottleReader::build(bottle_reader, EncryptedBottleReaderOptions::with_keys(&[ Box::new(sk) ])).unwrap();
let mut data_buffer = Vec::new();
let len = encrypted_bottle_reader.read_to_end(&mut data_buffer).unwrap();
encrypted_bottle_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
#[test]
fn public_key() {
const PK_HEX: &str = "112905df7c79c726b6250ec6e87aaa35d9127e2f48736a65c7352e8768d77865";
const SK_HEX: &str = "bc29877fa28b3e03ea6b58d35818e65a1fb4870dae35c4a452de880205108efb";
let pk = Ed25519PublicKey::from_ssh_bytes(&hex::decode(PK_HEX).unwrap(), String::from("eeyore")).unwrap();
let sk = Ed25519SecretKey::from_ssh_bytes(&hex::decode(SK_HEX).unwrap(), String::from("eeyore")).unwrap();
let data = b"And the things I do, not set in stone";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.key = EncryptionKey::Generated;
{
let recipients = [ pk ];
let mut bottle_writer = EncryptedBottleWriter::for_recipients(&mut buffer, options, &recipients).unwrap();
bottle_writer.write_all(data).unwrap();
bottle_writer.close().unwrap();
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let mut encrypted_bottle_reader =
EncryptedBottleReader::build(bottle_reader, EncryptedBottleReaderOptions::with_keys(&[ Box::new(sk) ])).unwrap();
let mut data_buffer = Vec::new();
let len = encrypted_bottle_reader.read_to_end(&mut data_buffer).unwrap();
encrypted_bottle_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
#[test]
fn nested_bottle_known_key() {
let key_data = decode("826e3631501115482ee5808dbceaec06").unwrap();
let data = b"Oh the bright ideas / In the dark when you feel oh so cold";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.algorithm = EncryptionAlgorithm::AES_128_GCM;
options.key = EncryptionKey::Key(key_data.clone());
{
let mut eb_writer = EncryptedBottleWriter::new(&mut buffer, options).unwrap();
let mut b_writer = BottleWriter::new(&mut eb_writer, BottleType::Test, Header::new(), 6).unwrap();
b_writer.write_data_stream().unwrap();
b_writer.write_all(data).unwrap();
b_writer.close_stream().unwrap();
b_writer.close().unwrap();
eb_writer.close().unwrap();
assert_eq!(buffer.len(), 187);
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let mut eb_reader = EncryptedBottleReader::build(
bottle_reader,
EncryptedBottleReaderOptions::new(EncryptionKey::Key(key_data.clone()))
).unwrap();
let mut b_reader = BottleReader::new(&mut eb_reader).unwrap();
assert_eq!(b_reader.bottle_cap.bottle_type, BottleType::Test);
assert_eq!(b_reader.next_stream().unwrap(), BottleStream::Data);
let mut data_buffer = Vec::new();
let len = b_reader.data_stream().unwrap().read_to_end(&mut data_buffer).unwrap();
b_reader.close_stream().unwrap();
assert_eq!(b_reader.next_stream().unwrap(), BottleStream::End);
b_reader.close().unwrap();
eb_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
#[test]
fn missing_key_commitment() {
const PK_HEX: &str = "112905df7c79c726b6250ec6e87aaa35d9127e2f48736a65c7352e8768d77865";
const SK_HEX: &str = "bc29877fa28b3e03ea6b58d35818e65a1fb4870dae35c4a452de880205108efb";
let pk = Ed25519PublicKey::from_ssh_bytes(&hex::decode(PK_HEX).unwrap(), String::from("eeyore")).unwrap();
let sk = Ed25519SecretKey::from_ssh_bytes(&hex::decode(SK_HEX).unwrap(), String::from("eeyore")).unwrap();
let data = b"And the things I do, not set in stone";
let mut buffer = Vec::new();
let mut options = EncryptedBottleWriterOptions::new();
options.key = EncryptionKey::Generated;
options.omit_key_commitment = true;
{
let recipients = [ pk ];
let mut bottle_writer = EncryptedBottleWriter::for_recipients(&mut buffer, options, &recipients).unwrap();
bottle_writer.write_all(data).unwrap();
bottle_writer.close().unwrap();
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
assert_eq!(bottle_reader.bottle_cap.bottle_type, BottleType::Encrypted);
{
let error = EncryptedBottleReader::build(
bottle_reader,
EncryptedBottleReaderOptions::with_keys(&[ Box::new(sk.clone()) ])
).expect_err("failed to notice missing commitment");
assert!(matches!(error, BottleError::NoKeyCommitment));
}
let bottle_reader = BottleReader::new(&buffer[..]).unwrap();
{
let keys = vec![Box::new(sk) as Box<dyn BottleSecretKey>];
let mut options = EncryptedBottleReaderOptions::with_keys(&keys);
options.allow_missing_key_commitment = true;
let mut encrypted_bottle_reader = EncryptedBottleReader::build(
bottle_reader,
options,
).unwrap();
let mut data_buffer = Vec::new();
let len = encrypted_bottle_reader.read_to_end(&mut data_buffer).unwrap();
encrypted_bottle_reader.close().unwrap();
assert_eq!(&data_buffer[0 .. len], data);
}
}
}