Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split README file #253

Merged
merged 13 commits into from
Dec 11, 2024
492 changes: 45 additions & 447 deletions README.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions docs/Altenatives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#Alternatives
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved

- [Alternatives](https://www.libhunt.com/r/rencfs)
- [Cryptomator](https://cryptomator.org/)
- [gocryptfs](https://nuetzlich.net/gocryptfs/)
- [VeraCrypt](https://www.veracrypt.fr/code/VeraCrypt/?h=NewSysEncWizard)
- [TrueCrypt](https://truecrypt.sourceforge.net/)
- [DroidFS, F-Droid](https://f-droid.org/en/packages/sushi.hardcore.droidfs/)
- [EncFS](https://vgough.github.io/encfs/) and [alternatives](https://alternativeto.net/software/encfs/)
- [CryFS](https://www.cryfs.org/)
- [fscrypt](https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html)
- [LUKS, dm-crypt](https://guardianproject.info/archive/luks/)
- [AES Crypt](https://www.aescrypt.com/)
- [Windows BitLocker](https://learn.microsoft.com/en-us/windows/security/operating-system-security/data-protection/bitlocker/)
- [File Lock PEA](https://eck.cologne/peafactory/en/html/file_pea.html)
- [ZenCrypt](https://play.google.com/store/apps/details?id=com.zestas.cryptmyfiles&hl=en)
- [Hat.sh](https://hat.sh/)
152 changes: 152 additions & 0 deletions docs/Build_from_Source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Build from source

## Browser

If you want to give it a quick try and not setup anything locally, you can
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/radumarias/rencfs)

[![Open Rustlings On Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/?repo=radumarias%2Frencfs&ref=main)

You can compile it, run it, and give it a quick try in the browser. After you start it from above

```bash
apt-get update && apt-get install fuse3
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
mkdir mnt && mkdir data
cargo run --release -- mount -m mnt -d data
```

Open another terminal

```bash
cd mnt
mkdir a && cd a
echo "test" > test.txt
cat test.txt
```

## Locally

For now, the `FUSE` (`fuse3` crate) only works on `Linux`, so to start the project, you will need to be on Linux.
Instead, you can [Develop inside a Container](#developing-inside-a-container), which will start a local Linux container, the IDE will connect to it,
and you can build and start the app there and also use the terminal to test it.
On Windows, you can start it in [WSL](https://harsimranmaan.medium.com/install-and-setup-rust-development-environment-on-wsl2-dccb4bf63700).

### Getting the sources

```bash
git clone [email protected]:radumarias/rencfs.git && cd rencfs
````

### Dependencies

#### Rust

To build from source, you need to have Rust installed, you can see more details on how to install
it [here](https://www.rust-lang.org/tools/install).

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
````

Accordingly, it is customary for Rust developers to include this directory in their `PATH` environment variable.
During installation `rustup` will attempt to configure the `PATH`. Because of differences between platforms, command
shells,
and bugs in `rustup`, the modifications to `PATH` may not take effect until the console is restarted, or the user is
logged out, or it may not succeed at all.

If, after installation, running `rustc --version` in the console fails, this is the most likely reason.
In that case please add it to the `PATH` manually.

The project is set up to use the `nightly` toolchain in `rust-toolchain. tool`; on the first build, you will see it fetch the nightly.

Make sure to add this to your `$PATH` too

```bash
export PATH="$PATH::$HOME/.cargo/bin"
```

```bash
cargo install cargo-aur
cargo install cargo-generate-rpm
```

### Other dependencies

Also, these dependencies are required (or based on your distribution):

#### Arch

```bash
sudo pacman -Syu && sudo pacman -S fuse3 base-devel act
```

#### Ubuntu

```bash
sudo apt-get update && sudo apt-get install fuse3 build-essential act
```

#### Fedora

```bash
sudo dnf update && sudo dnf install fuse3 && dnf install @development-tools act
```

### Build for debug

```bash
cargo build
```

### Build release

```bash
cargo build --release
```

### Run

```bash
cargo run --release -- mount --mount-point MOUNT_POINT --data-dir DATA_DIR
```

#### Dev settings

If you don't want to be prompted for a password, you can set this env var and run it like this:

```bash
RENCFS_PASSWORD=PASS cargo run --release -- mount --mount-point MOUNT_POINT --data-dir DATA_DIR
```

For dev mode it is recommended to run with `DEBUG` log level:

```bash
cargo run --release -- --log-level DEBUG mount --mount-point MOUNT_POINT --data-dir DATA_DIR
```

### Build local RPM for Fedora

This is using [cargo-generate-rpm](https://crates.io/crates/cargo-generate-rpm)

```bash
cargo install cargo-generate-rpm
cargo build --release
cargo generate-rpm
```

The generated RPM will be located here: `target/generate-rpm`.

#### Install and run local RPM

```bash
cd target/generate-rpm/
sudo dnf localinstall rencfs-xxx.x86_64.rpm
```

## Developing inside a Container

See here how to configure for [RustRover](https://www.jetbrains.com/help/rust/connect-to-devcontainer.html) and for [VsCode](https://code.visualstudio.com/docs/devcontainers/containers).

You can use the `.devcontainer` directory from the project to start a container with all the necessary tools to build
and run the app.
31 changes: 31 additions & 0 deletions docs/Cipher_comparison.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Cipher comparison
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved

## AES-GCM vs. ChaCha20-Poly1305

- If you have hardware acceleration (e.g. `AES-NI`), then `AES-GCM` provides better performance. On my benchmarks, it was
faster by a factor of **1.28** on average.
If you do not have hardware acceleration, `AES-GCM` is either slower than `ChaCha20-Poly1305`, or it leaks your
encryption
keys in cache timing.
- `AES-GCM` can target multiple security levels (`128-bit`, `192-bit`, `256-bit`), whereas `ChaCha20-Poly1305` is only defined at
the `256-bit` security level.
- Nonce size:
- `AES-GCM`: Varies, but the standard is `96-bit` (`12 bytes`).
If you supply a longer nonce, this gets hashed down to `16 bytes`.
- `ChaCha20-Poly1305`: The standardized version uses `96-bit` nonce (`12 bytes`), but the original used `64-bit`
nonce (`8 bytes`).
- Wear-out of a single (key, nonce) pair:
- `AES-GCM`: Messages must be less than `2^32 – 2` blocks (a.k.a. `2^36 – 32 bytes`, a.k.a. `2^39 – 256-bit`), that's
roughly `64GB`.
This also makes the security analysis of `AES-GCM` with long nonces complicated since the hashed nonce doesn’t
start
with the lower `4 bytes` set to `00 00 00 02`.
- `ChaCha20-Poly1305`: `ChaCha` has an internal counter (`32-bit` in the standardized IETF variant, `64-bit` in the
original design). Max message length is `2^39 - 256-bit`, about `256GB`
- Neither algorithm is **nonce misuse-resistant**.
- `ChaChaPoly1305` is better at `SIMD`

### Conclusion

Both are good options. `AES-GCM` can be faster with **hardware support**, but **pure-software** implementations of
`ChaCha20-Poly1305` are almost always **fast** and **constant-time**.
12 changes: 12 additions & 0 deletions docs/Considerations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Considerations

- Please note that this project doesn't try to reinvent the wheel or be better than already proven implementations
- This project doesn't want to be a replacement in any way for already proven file encryption solutions. If you really
want to be close to bulletproof solutions, then maybe this is not the ideal one for you. But is trying to offer a simple use
of an encryption solution that should be used, taking into consideration all the security concerns from above
- It started as a learning project of Rust programming language, and I feel like I keep building more on it
- It's a fairly simple and standard implementation that tries to respect all security standards and correctly use secure and robust
primitives so that it can be extended from this. Indeed, it doesn't have the maturity yet to "fight" other well-known
implementations.
But it can be a project from which others can learn or build upon, or why not for some to actually use it, keeping in
mind all the above
20 changes: 20 additions & 0 deletions docs/Functionality.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Functionality

Some of these are still being worked on and marked with `[WIP]`.

- It keeps all `encrypted` data and `master encryption key` in a dedicated directory with files structured on `inodes` (with
metadata info), files for binary content, and directories with files/directories entries. All data, metadata, and filenames
are encrypted. It generates unique inodes for new files in a multi-instance run and offline mode.
- The password is collected from CLI and saved in the OS's `keyring` while the app runs. This is because, for security concerns, we
clear the password from memory on inactivity, and we derive it again from the password just when needed.
- Master encryption key is also encrypted with another key derived from the password. This gives the ability to change
the
password without re-encrypting all data, we just `re-encrypt` the `master key`.
- Files are `encrypted` in `chunks` of `256KB`, so when making a change, we just re-encrypt that chunks.
- `Fast seek` on read and write, so if you're watching a movie, you can seek any position, and that would be instant.
This is because we can seek a particular chunk.
- The encryption key is `zeroize` in the mem when disposing and idle. Also, it's `mlock`ed while used to prevent being moved to swap. It's
also `mprotect`ed while not in use.
- `[WIP]` Ensure file integrity by saving each change to WAL, so for crashes or power loss, we apply the pending
changes at the next start. This makes the write operations atomic.
- Multiple writes in parallel to the same file, ideal for torrent-like applications.
21 changes: 21 additions & 0 deletions docs/Key_features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## Key features
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved

Some of these are still being worked on and marked with `[WIP]`.

- `Security` using well-known audited `AEAD` cryptography primitives;
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved
- `[WIP]` `Data integrity`, data is written with `WAL` to ensure integrity even on crash or power loss;
- `[WIP]` Hide all info for enhanced `privacy`, all `metadata`, `content`, `file name`, `file size`, `*time` fields, `files count`, and directory structure is encrypted;
- `Safely` manage `credentials` in memory with `mlock(2)`, `mprotect`, `zeroize`, and `expiry` to mitigate cold boot attacks;
- `Memory safety`, `performance`, and `optimized` for `concurrency` with Rust;
- Simplicity;
- Encryption key generated from password;
- Password saved in OS's `keyring`;
- `Change password` without re-encrypting all data;
- `[WIP]` Generate `unique nonce` in `offline mode`;
- `Fast seek` on both reads and writes;
- `Writes in parallel`;
- Exposed with `FUSE`;
- Fully `concurrent` for all operations;
- `[WIP]` Handle `long file names`;
- `[WIP]` Abstraction layer for `Rust File` and `fs` API to use it as lib to `switch to using encrypted files` by just `changing the use statements`;
- `[WIP]` Abstraction layer to `access the storage` with implementations for desktop, Wasm, Android, and iOS and the ability to write your own implementation.
23 changes: 23 additions & 0 deletions docs/Security.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ⚠️ Security Warning: Hazmat!

- **Phantom reads**: Reading older content from a file is not possible. Data is written with WAL and periodically
flushed to file. This ensures data integrity and maintains change order.
One problem that may occur is if we do a truncation, we change the content of the file, but the process is killed before
we write the metadata with the new file size. In this case, the next time we mount the system, we will still see the old
files. However, the content of the file could be bigger, and we read until the old size offset, so we would not
pick up
the new zeros bytes are written on truncating by increasing the size. If content is smaller, the read would stop and
end-of-file of the actual content, so this would not be such a big issue
- **What kind of metadata does it leak**: None, we encrypt filename, content, and metadata and we hide file count, size, and all-time fields
- It's always recommended to use encrypted disks for at least your sensitive data; this project is not a replacement for
that
- To reduce the risk of the encryption key being exposed from memory, it's recommended to disable memory dumps on the
OS level. Please see [here](https://www.cyberciti.biz/faq/disable-core-dumps-in-linux-with-systemd-sysctl/) how to do
it on Linux
- **Cold boot attacks**: to reduce the risk of this, we keep the encryption key in memory just as long as we really
need it to encrypt/decrypt data, and we are zeroing it after that. We also remove it from memory after a period of
inactivity
- Please note that no security expert audited this project. It's built with security in mind and tries to
follow all the best practices, but it's not guaranteed to be secure
- **Also, please back up your data; the project is still in development, and there might be bugs that can lead to data
loss**
12 changes: 12 additions & 0 deletions docs/Stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Stack
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved

- it's fully async built upon [tokio](https://crates.io/crates/tokio) and [fuse3](https://crates.io/crates/fuse3)
- [ring](https://crates.io/crates/ring) for encryption and [argon2](https://crates.io/crates/argon2) for key derivation
function (generating key from password used to encrypt the master encryption key)
- [rand_chacha](https://crates.io/crates/rand_chacha) for random generators
- [shush-rs](https://crates.io/crates/shush-rs) keeps pass and encryption keys safe in memory and zero them when
not used. It keeps encryption keys in memory only while being used, and when not active, it will release and zeroing
them in memory. It locks the memory page as well, preventing it from being written to swap.
- [blake3](https://crates.io/crates/blake3) for hashing
- password saved in OS keyring using [keyring](https://crates.io/crates/keyring)
- [tracing](https://crates.io/crates/tracing) for logs
Loading
Loading