Error related rustcryptfs-lib refracto
This commit is contained in:
parent
965c07df0a
commit
c57f9b3a85
|
@ -0,0 +1,29 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ConfigError {
|
||||
#[error(transparent)]
|
||||
ScryptError(#[from] ScryptError),
|
||||
#[error(transparent)]
|
||||
HdkfError(#[from] hkdf::InvalidLength),
|
||||
#[error("Failed to decode base64")]
|
||||
Base64Error(#[from] base64::DecodeError),
|
||||
#[error("Failed to decrypt master key")]
|
||||
MasterKeyDecryptError(),
|
||||
#[error("Invalid master key length")]
|
||||
InvalidMasterKeyLengthError(),
|
||||
}
|
||||
|
||||
impl From<aes_gcm::Error> for ConfigError {
|
||||
fn from(_: aes_gcm::Error) -> Self {
|
||||
Self::MasterKeyDecryptError()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ScryptError {
|
||||
#[error(transparent)]
|
||||
InvalidParams(#[from] scrypt::errors::InvalidParams),
|
||||
#[error(transparent)]
|
||||
InvalidOutputLen(#[from] scrypt::errors::InvalidOutputLen),
|
||||
}
|
|
@ -9,7 +9,9 @@ use aes_gcm::{
|
|||
};
|
||||
use hkdf::Hkdf;
|
||||
|
||||
use crate::error::{FilenameDecryptError, Result, ScryptError};
|
||||
mod error;
|
||||
|
||||
pub use error::*;
|
||||
|
||||
/// An enum that contain all the feature flag a gocryptfs config can have.
|
||||
#[derive(serde::Deserialize, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -69,7 +71,7 @@ impl CryptConf {
|
|||
/// See gocryptfs documentation about [master key](https://nuetzlich.net/gocryptfs/forward_mode_crypto/#master-key-storage).
|
||||
///
|
||||
/// ![TODO NAME THIS IMAGE](https://nuetzlich.net/gocryptfs/img/master-key.svg)
|
||||
pub fn get_master_key(&self, password: &[u8]) -> Result<[u8; 32]> {
|
||||
pub fn get_master_key(&self, password: &[u8]) -> Result<[u8; 32], ConfigError> {
|
||||
let block = base64::decode(&self.encrypted_key)?;
|
||||
let key = self.scrypt_object.get_hkdf_key(password)?;
|
||||
|
||||
|
@ -77,7 +79,9 @@ impl CryptConf {
|
|||
let tag = &block[block.len() - 16..];
|
||||
let ciphertext = &block[16..block.len() - 16];
|
||||
|
||||
let mut buf: [u8; 32] = ciphertext.try_into().expect("TODO");
|
||||
let mut buf: [u8; 32] = ciphertext
|
||||
.try_into()
|
||||
.map_err(|_| ConfigError::InvalidMasterKeyLengthError())?;
|
||||
|
||||
let aes = AesGcm::<Aes256, cipher::consts::U16>::new(Key::from_slice(&key));
|
||||
|
||||
|
@ -133,18 +137,13 @@ pub struct ScryptObject {
|
|||
}
|
||||
|
||||
impl ScryptObject {
|
||||
fn get_hkdf_key(&self, password: &[u8]) -> std::result::Result<Vec<u8>, FilenameDecryptError> {
|
||||
fn get_hkdf_key(&self, password: &[u8]) -> Result<Vec<u8>, ConfigError> {
|
||||
let mut key = [0u8; 32];
|
||||
|
||||
let params = scrypt::Params::new((self.n as f64).log2() as u8, self.r, self.p)
|
||||
.map_err(|e| ScryptError::from(e))?;
|
||||
|
||||
scrypt::scrypt(
|
||||
password,
|
||||
&base64::decode(&self.salt).unwrap(),
|
||||
¶ms,
|
||||
&mut key,
|
||||
)
|
||||
scrypt::scrypt(password, &base64::decode(&self.salt)?, ¶ms, &mut key)
|
||||
.map_err(|e| ScryptError::from(e))?;
|
||||
|
||||
let hdkf = Hkdf::<sha2::Sha256>::new(None, &key);
|
|
@ -0,0 +1,19 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ContentCipherError {
|
||||
#[error("Block is too short")]
|
||||
BlockTooShort(),
|
||||
#[error("all-zero nonce")]
|
||||
AllZeroNonce(),
|
||||
#[error("Failed to decrypt content")]
|
||||
ContentDecryptError(),
|
||||
#[error(transparent)]
|
||||
HdkfError(#[from] hkdf::InvalidLength),
|
||||
}
|
||||
|
||||
impl From<aes_gcm::Error> for ContentCipherError {
|
||||
fn from(_: aes_gcm::Error) -> Self {
|
||||
Self::ContentDecryptError()
|
||||
}
|
||||
}
|
|
@ -4,7 +4,9 @@ use aes_gcm::{aead::generic_array::GenericArray, aes::Aes256, AeadInPlace, AesGc
|
|||
use cipher::consts::{U16, U32};
|
||||
use hkdf::Hkdf;
|
||||
|
||||
use crate::error::{DecryptError, Result};
|
||||
mod error;
|
||||
|
||||
pub use error::*;
|
||||
|
||||
type Aes256Gcm = AesGcm<Aes256, U16>;
|
||||
|
||||
|
@ -16,16 +18,15 @@ pub struct ContentEnc {
|
|||
|
||||
impl ContentEnc {
|
||||
/// Init a new ContentEnc from the master key and the iv len.
|
||||
pub fn new(master_key: &[u8], iv_len: u8) -> Self {
|
||||
pub fn new(master_key: &[u8], iv_len: u8) -> Result<Self, ContentCipherError> {
|
||||
let mut key = [0u8; 32];
|
||||
let hdkf = Hkdf::<sha2::Sha256>::new(None, &master_key);
|
||||
hdkf.expand(b"AES-GCM file content encryption", &mut key)
|
||||
.unwrap();
|
||||
hdkf.expand(b"AES-GCM file content encryption", &mut key)?;
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
key: GenericArray::from(key),
|
||||
iv_len: iv_len as usize,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Decrypt a encrypted block of len (iv_len + decrypted_block_size + iv_len), with the block number and the file id.
|
||||
|
@ -34,7 +35,7 @@ impl ContentEnc {
|
|||
block: &[u8],
|
||||
block_number: u64,
|
||||
file_id: Option<&[u8]>,
|
||||
) -> Result<Vec<u8>> {
|
||||
) -> Result<Vec<u8>, ContentCipherError> {
|
||||
// TODO NOT BOX
|
||||
if block.len() == 0 {
|
||||
return Ok(block.into());
|
||||
|
@ -45,7 +46,7 @@ impl ContentEnc {
|
|||
}
|
||||
|
||||
if block.len() < self.iv_len {
|
||||
return Err(DecryptError::BlockTooShort().into());
|
||||
return Err(ContentCipherError::BlockTooShort().into());
|
||||
}
|
||||
|
||||
let nonce = &block[..self.iv_len];
|
||||
|
@ -53,7 +54,7 @@ impl ContentEnc {
|
|||
let ciphertext = &block[self.iv_len..block.len() - self.iv_len];
|
||||
|
||||
if nonce.iter().all(|f| *f == 0) {
|
||||
return Err(DecryptError::AllZeroNonce().into());
|
||||
return Err(ContentCipherError::AllZeroNonce().into());
|
||||
}
|
||||
|
||||
let mut buf = Vec::from(ciphertext);
|
|
@ -1,49 +1,19 @@
|
|||
use thiserror::Error;
|
||||
|
||||
use crate::{config::ConfigError, content::ContentCipherError, filename::FilenameCipherError};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("Failed to decrypt content")]
|
||||
ContentDecryptError(),
|
||||
#[error("Failed to decrypt filename")]
|
||||
FilenameDecryptError(#[from] FilenameDecryptError),
|
||||
#[error("Failed to decode base64")]
|
||||
Base64Error(#[from] base64::DecodeError),
|
||||
#[error(transparent)]
|
||||
DecodeError(#[from] DecryptError),
|
||||
}
|
||||
|
||||
impl From<aes_gcm::Error> for Error {
|
||||
fn from(_: aes_gcm::Error) -> Self {
|
||||
Self::ContentDecryptError()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DecryptError {
|
||||
#[error("Block is too short")]
|
||||
BlockTooShort(),
|
||||
#[error("all-zero nonce")]
|
||||
AllZeroNonce(),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FilenameDecryptError {
|
||||
FilenameCipherError(#[from] FilenameCipherError),
|
||||
#[error(transparent)]
|
||||
ScryptError(#[from] ScryptError),
|
||||
#[error("Failed to decode base64")]
|
||||
Base64Error(#[from] base64::DecodeError),
|
||||
ContentCipherError(#[from] ContentCipherError),
|
||||
#[error(transparent)]
|
||||
HdkfError(#[from] hkdf::InvalidLength),
|
||||
#[error("Failed to decrypt filename")]
|
||||
DecryptError(),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ScryptError {
|
||||
#[error(transparent)]
|
||||
InvalidParams(#[from] scrypt::errors::InvalidParams),
|
||||
#[error(transparent)]
|
||||
InvalidOutputLen(#[from] scrypt::errors::InvalidOutputLen),
|
||||
ConfigError(#[from] ConfigError),
|
||||
#[error(transparent)]
|
||||
JsonError(#[from] serde_json::Error),
|
||||
#[error(transparent)]
|
||||
IoError(#[from] std::io::Error),
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::error::FilenameDecryptError;
|
||||
use cipher::{block_padding::Pkcs7, inout::InOutBufReserved, Iv, Key, KeyIvInit};
|
||||
use cipher::{block_padding::Pkcs7, Iv, Key, KeyIvInit};
|
||||
|
||||
use super::{EmeCipher, EncodedFilename, IntoDecodable};
|
||||
use super::{EmeCipher, EncodedFilename, FilenameCipherError, IntoDecodable};
|
||||
|
||||
pub struct DirFilenameCipher<'a, 'b> {
|
||||
filename_key: &'a Key<EmeCipher>,
|
||||
|
@ -13,7 +12,7 @@ impl<'a, 'b> DirFilenameCipher<'a, 'b> {
|
|||
Self { filename_key, iv }
|
||||
}
|
||||
|
||||
pub fn decode_filename<S>(&self, name: S) -> Result<String, FilenameDecryptError>
|
||||
pub fn decode_filename<S>(&self, name: S) -> Result<String, FilenameCipherError>
|
||||
where
|
||||
S: IntoDecodable,
|
||||
{
|
||||
|
@ -22,7 +21,7 @@ impl<'a, 'b> DirFilenameCipher<'a, 'b> {
|
|||
let mut filename = base64::decode_config(name.to_decodable(), base64::URL_SAFE_NO_PAD)?;
|
||||
let filename_decoded = cipher
|
||||
.decrypt_padded_mut::<Pkcs7>(&mut filename)
|
||||
.map_err(|_| FilenameDecryptError::DecryptError())?;
|
||||
.map_err(|_| FilenameCipherError::DecryptError())?;
|
||||
|
||||
Ok(String::from_utf8_lossy(filename_decoded).to_string())
|
||||
}
|
||||
|
@ -30,17 +29,13 @@ impl<'a, 'b> DirFilenameCipher<'a, 'b> {
|
|||
pub fn encrypt_filename(
|
||||
&self,
|
||||
plain_text_name: &str,
|
||||
) -> Result<EncodedFilename, FilenameDecryptError> {
|
||||
) -> Result<EncodedFilename, FilenameCipherError> {
|
||||
let mut cipher = EmeCipher::new(self.filename_key, self.iv);
|
||||
let mut res = [0u8; 2048];
|
||||
|
||||
let filename_encrypted = cipher
|
||||
.encrypt_padded_inout_mut::<Pkcs7>(
|
||||
InOutBufReserved::from_slices(plain_text_name.as_bytes(), &mut res).unwrap(),
|
||||
)
|
||||
.map_err(|_| FilenameDecryptError::DecryptError())?; // TODO RENAME ERROR
|
||||
|
||||
// TODO LONG FILENAME
|
||||
.encrypt_padded_b2b_mut::<Pkcs7>(plain_text_name.as_bytes(), &mut res)
|
||||
.map_err(|_| FilenameCipherError::EncryptError())?;
|
||||
|
||||
let filename = base64::encode_config(filename_encrypted, base64::URL_SAFE_NO_PAD);
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FilenameCipherError {
|
||||
#[error("Failed to decode base64")]
|
||||
Base64Error(#[from] base64::DecodeError),
|
||||
#[error(transparent)]
|
||||
HdkfError(#[from] hkdf::InvalidLength),
|
||||
#[error("Failed to decrypt filename")]
|
||||
DecryptError(),
|
||||
#[error("Failed to encrypt filename")]
|
||||
EncryptError()
|
||||
}
|
|
@ -3,22 +3,22 @@ use cipher::{Iv, Key};
|
|||
use eme_mode::DynamicEme;
|
||||
use hkdf::Hkdf;
|
||||
|
||||
use crate::error::FilenameDecryptError;
|
||||
|
||||
pub(crate) type EmeCipher = DynamicEme<Aes256>;
|
||||
|
||||
mod dir_filename_cipher;
|
||||
mod filename_encoded;
|
||||
mod error;
|
||||
|
||||
pub use dir_filename_cipher::*;
|
||||
pub use filename_encoded::*;
|
||||
pub use error::*;
|
||||
|
||||
pub struct FilenameCipher {
|
||||
filename_key: Key<Aes256>,
|
||||
}
|
||||
|
||||
impl FilenameCipher {
|
||||
pub fn new(master_key: &[u8]) -> Result<Self, FilenameDecryptError> {
|
||||
pub fn new(master_key: &[u8]) -> Result<Self, FilenameCipherError> {
|
||||
let mut key = [0u8; 32];
|
||||
let hdkf = Hkdf::<sha2::Sha256>::new(None, &master_key);
|
||||
hdkf.expand(b"EME filename encryption", &mut key)?;
|
||||
|
|
|
@ -27,7 +27,7 @@ impl GocryptFs {
|
|||
let base_path = encrypted_dir_path.as_ref();
|
||||
|
||||
let mut config_file =
|
||||
File::open(base_path.join("gocryptfs.conf")).expect("failed to get config");
|
||||
File::open(base_path.join("gocryptfs.conf"))?;
|
||||
|
||||
Self::load_from_reader(&mut config_file, password.as_bytes())
|
||||
}
|
||||
|
@ -39,13 +39,12 @@ impl GocryptFs {
|
|||
where
|
||||
R: Read,
|
||||
{
|
||||
let config = serde_json::from_reader::<_, config::CryptConf>(reader_config)
|
||||
.expect("failed to parse config");
|
||||
let config = serde_json::from_reader::<_, config::CryptConf>(reader_config)?;
|
||||
|
||||
let master_key = config.get_master_key(password)?;
|
||||
|
||||
let filename_decoder = FilenameCipher::new(&master_key)?;
|
||||
let content_decoder = ContentEnc::new(&master_key, 16); // TODO IV LEN
|
||||
let content_decoder = ContentEnc::new(&master_key, 16)?; // TODO IV LEN
|
||||
|
||||
Ok(Self {
|
||||
filename_decoder,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use rustcryptfs_lib::filename::FilenameCipherError;
|
||||
use thiserror::Error;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
@ -11,5 +12,5 @@ pub enum Error {
|
|||
RustCryptFsError(#[from] rustcryptfs_lib::error::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
RustCryptFsFilenameError(#[from] rustcryptfs_lib::error::FilenameDecryptError),
|
||||
RustCryptFsFilenameError(#[from] FilenameCipherError),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue