Make ArmoredReader generic over the type of buffered reader

This requires changing Read bounds through the Decryptor stack to
BufRead bounds.
This commit is contained in:
Jack Grigg 2020-05-16 14:42:30 +12:00
parent 44e1884eac
commit 6605a28f48
7 changed files with 37 additions and 31 deletions

View file

@ -139,8 +139,8 @@ enum StartPos {
Explicit(u64),
}
pub struct ArmoredReader<R: Read> {
inner: BufReader<R>,
pub struct ArmoredReader<R> {
inner: R,
start: StartPos,
is_armored: Option<bool>,
line_buf: Zeroizing<String>,
@ -153,10 +153,16 @@ pub struct ArmoredReader<R: Read> {
data_read: usize,
}
impl<R: Read> ArmoredReader<R> {
impl<R: Read> ArmoredReader<BufReader<R>> {
pub(crate) fn from_reader(inner: R) -> Self {
ArmoredReader::new(BufReader::new(inner))
}
}
impl<R> ArmoredReader<R> {
fn new(inner: R) -> Self {
ArmoredReader {
inner: BufReader::new(inner),
inner,
start: StartPos::Implicit(0),
is_armored: None,
line_buf: Zeroizing::new(String::with_capacity(ARMORED_COLUMNS_PER_LINE + 2)),
@ -325,7 +331,7 @@ impl<R: Read> ArmoredReader<R> {
}
}
impl<R: Read> Read for ArmoredReader<R> {
impl<R: BufRead> Read for ArmoredReader<R> {
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
loop {
match self.is_armored {
@ -397,7 +403,7 @@ impl<R: Read + Seek> ArmoredReader<R> {
}
}
impl<R: Read + Seek> Seek for ArmoredReader<R> {
impl<R: BufRead + Seek> Seek for ArmoredReader<R> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
loop {
match self.is_armored {

View file

@ -6,7 +6,7 @@ use chacha20poly1305::{
};
use secrecy::{ExposeSecret, SecretVec};
use std::convert::TryInto;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::io::{self, BufRead, Read, Seek, SeekFrom, Write};
use super::armor::{ArmoredReader, ArmoredWriter};
@ -218,7 +218,7 @@ enum StartPos {
}
/// Provides access to a decrypted age file.
pub struct StreamReader<R: Read> {
pub struct StreamReader<R> {
stream: Stream,
inner: ArmoredReader<R>,
start: StartPos,
@ -226,7 +226,7 @@ pub struct StreamReader<R: Read> {
chunk: Option<SecretVec<u8>>,
}
impl<R: Read> StreamReader<R> {
impl<R> StreamReader<R> {
fn count_bytes(&mut self, read: usize) {
// We only need to count if we haven't yet worked out the start position.
if let StartPos::Implicit(offset) = &mut self.start {
@ -235,7 +235,7 @@ impl<R: Read> StreamReader<R> {
}
}
impl<R: Read> Read for StreamReader<R> {
impl<R: BufRead> Read for StreamReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if self.chunk.is_none() {
let mut chunk = vec![0; ENCRYPTED_CHUNK_SIZE];
@ -296,7 +296,7 @@ impl<R: Read> Read for StreamReader<R> {
}
}
impl<R: Read + Seek> StreamReader<R> {
impl<R: BufRead + Seek> StreamReader<R> {
fn start(&mut self) -> io::Result<u64> {
match self.start {
StartPos::Implicit(offset) => {
@ -313,7 +313,7 @@ impl<R: Read + Seek> StreamReader<R> {
}
}
impl<R: Read + Seek> Seek for StreamReader<R> {
impl<R: BufRead + Seek> Seek for StreamReader<R> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
// Convert the offset into the target position within the plaintext
let start = self.start()?;

View file

@ -3,7 +3,7 @@
use age_core::primitives::hkdf;
use rand::{rngs::OsRng, RngCore};
use secrecy::{ExposeSecret, SecretString};
use std::io::{self, Read, Write};
use std::io::{self, BufReader, Read, Write};
use std::iter;
use crate::{
@ -122,26 +122,26 @@ impl Encryptor {
}
/// Decryptor for an age file.
pub enum Decryptor<R: Read> {
pub enum Decryptor<R> {
/// Decryption with a list of identities.
Recipients(decryptor::RecipientsDecryptor<R>),
/// Decryption with a passphrase.
Passphrase(decryptor::PassphraseDecryptor<R>),
}
impl<R: Read> From<decryptor::RecipientsDecryptor<R>> for Decryptor<R> {
impl<R> From<decryptor::RecipientsDecryptor<R>> for Decryptor<R> {
fn from(decryptor: decryptor::RecipientsDecryptor<R>) -> Self {
Decryptor::Recipients(decryptor)
}
}
impl<R: Read> From<decryptor::PassphraseDecryptor<R>> for Decryptor<R> {
impl<R> From<decryptor::PassphraseDecryptor<R>> for Decryptor<R> {
fn from(decryptor: decryptor::PassphraseDecryptor<R>) -> Self {
Decryptor::Passphrase(decryptor)
}
}
impl<R: Read> Decryptor<R> {
impl<R: Read> Decryptor<BufReader<R>> {
/// Attempts to create a decryptor for an age file.
///
/// Returns an error if the input does not contain a valid age file.

View file

@ -1,7 +1,7 @@
//! Decryptors for age.
use secrecy::SecretString;
use std::io::Read;
use std::io::BufRead;
use super::{v1_payload_key, Callbacks, NoCallbacks};
use crate::{
@ -14,7 +14,7 @@ use crate::{
},
};
struct BaseDecryptor<R: Read> {
struct BaseDecryptor<R> {
/// The age file.
input: ArmoredReader<R>,
/// The age file's header.
@ -23,7 +23,7 @@ struct BaseDecryptor<R: Read> {
nonce: [u8; 16],
}
impl<R: Read> BaseDecryptor<R> {
impl<R> BaseDecryptor<R> {
fn obtain_payload_key<F>(&mut self, filter: F) -> Result<[u8; 32], Error>
where
F: FnMut(&RecipientStanza) -> Option<Result<FileKey, Error>>,
@ -41,9 +41,9 @@ impl<R: Read> BaseDecryptor<R> {
}
/// Decryptor for an age file encrypted to a list of recipients.
pub struct RecipientsDecryptor<R: Read>(BaseDecryptor<R>);
pub struct RecipientsDecryptor<R>(BaseDecryptor<R>);
impl<R: Read> RecipientsDecryptor<R> {
impl<R: BufRead> RecipientsDecryptor<R> {
pub(super) fn new(input: ArmoredReader<R>, header: Header, nonce: [u8; 16]) -> Self {
RecipientsDecryptor(BaseDecryptor {
input,
@ -81,9 +81,9 @@ impl<R: Read> RecipientsDecryptor<R> {
}
/// Decryptor for an age file encrypted with a passphrase.
pub struct PassphraseDecryptor<R: Read>(BaseDecryptor<R>);
pub struct PassphraseDecryptor<R>(BaseDecryptor<R>);
impl<R: Read> PassphraseDecryptor<R> {
impl<R: BufRead> PassphraseDecryptor<R> {
pub(super) fn new(input: ArmoredReader<R>, header: Header, nonce: [u8; 16]) -> Self {
PassphraseDecryptor(BaseDecryptor {
input,

View file

@ -127,7 +127,7 @@ where
}
fn mount_stream(
stream: StreamReader<File>,
stream: StreamReader<io::BufReader<File>>,
types: String,
mountpoint: String,
) -> Result<(), Error> {

View file

@ -2,7 +2,7 @@ use age::stream::StreamReader;
use fuse_mt::*;
use std::collections::HashMap;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};
use std::io::{self, BufReader, Read, Seek, SeekFrom};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use tar::{Archive, Entry, EntryType};
@ -104,7 +104,7 @@ fn add_to_dir_map(
type OpenFile = (PathBuf, u64, u64);
pub struct AgeTarFs {
inner: Mutex<StreamReader<File>>,
inner: Mutex<StreamReader<BufReader<File>>>,
dir_map: HashMap<PathBuf, Vec<DirectoryEntry>>,
file_map: HashMap<PathBuf, (FileAttr, u64)>,
open_dirs: Mutex<(HashMap<u64, PathBuf>, u64)>,
@ -112,7 +112,7 @@ pub struct AgeTarFs {
}
impl AgeTarFs {
pub fn open(stream: StreamReader<File>) -> io::Result<Self> {
pub fn open(stream: StreamReader<BufReader<File>>) -> io::Result<Self> {
// Build a directory listing for the archive
let mut dir_map: HashMap<PathBuf, Vec<DirectoryEntry>> = HashMap::new();
dir_map.insert(PathBuf::new(), vec![]); // the root

View file

@ -2,7 +2,7 @@ use age::stream::StreamReader;
use fuse_mt::*;
use std::collections::HashMap;
use std::fs::File;
use std::io::{self, Read};
use std::io::{self, BufReader, Read};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use time::Timespec;
@ -84,14 +84,14 @@ fn add_dir_to_map(
}
pub struct AgeZipFs {
inner: Mutex<ZipArchive<StreamReader<File>>>,
inner: Mutex<ZipArchive<StreamReader<BufReader<File>>>>,
dir_map: HashMap<PathBuf, Vec<DirectoryEntry>>,
open_dirs: Mutex<(HashMap<u64, PathBuf>, u64)>,
open_files: Mutex<(HashMap<u64, usize>, u64)>,
}
impl AgeZipFs {
pub fn open(stream: StreamReader<File>) -> io::Result<Self> {
pub fn open(stream: StreamReader<BufReader<File>>) -> io::Result<Self> {
let mut archive =
ZipArchive::new(stream).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;