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
53 changes: 53 additions & 0 deletions Dockerfile_from_scratch
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
################
##### Builder
FROM alpine:3.19.1 AS builder

RUN apk update && apk upgrade && apk add binutils build-base ca-certificates curl file g++ gcc make patch fuse3

RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

RUN . ~/.cargo/env && rustup target add x86_64-unknown-linux-musl

RUN . ~/.cargo/env && rustup default nightly && rustup update

# Cache downloaded+built dependencies
#COPY Cargo.toml Cargo.lock /usr/src/rencfs/
#RUN mkdir /usr/src/rencfs/src && \
# echo 'fn main() {}' > /usr/src/rencfs/src/main.rs
#
#RUN . ~/.cargo/env && cd /usr/src/rencfs/ && cargo build --release && \
# rm -Rvf /usr/src/rencfs/src

# Build our actual code
#COPY Cargo.toml Cargo.lock /usr/src/rencfs/
#COPY src /usr/src/rencfs
COPY . /usr/src/rencfs
#COPY examples /usr/src/rencfs/examples
RUN . ~/.cargo/env && \
cd /usr/src/rencfs/ && \
cargo build --target x86_64-unknown-linux-musl --release

#Copy the fusermount3 binary and libraries into a directory
RUN mkdir /fusermount3dep && \
cp $(which fusermount3) /fusermount3dep/ && \
ldd $(which fusermount3) | awk '{ print $3 }' | xargs -I {} cp {} /fusermount3dep/


################
##### Runtime
FROM scratch AS runtime

# Copy fusermount3
COPY --from=builder /fusermount3dep/fusermount3 /usr/bin/

# Copy busybox
COPY --from=builder /bin/ /bin/

# Copy ld-musl (fusermount3 & busybox dep)
COPY --from=builder /fusermount3dep/ld* /lib/

# Copy application binary from builder image
COPY --from=builder /usr/src/rencfs/target/x86_64-unknown-linux-musl/release/rencfs /usr/bin/

# Run the application
CMD ["rencfs", "--help"]
63 changes: 38 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,8 @@ You can use it as CLI or as a library to build your custom FUSE implementation o

- A short story
radumarias marked this conversation as resolved.
Show resolved Hide resolved

[The Hitchhiker’s Guide to Building an Encrypted Filesystem in Rust](docs/The_Hitchhiker_s_Guide_to_Building_an_Encrypted_Filesystem_in_Rust_2.pdf)
[The Hitchhiker’s Guide to Building an Encrypted Filesystem in Rust](docs/The_Hitchhiker_s_Guide_to_Building_an_Encrypted_Filesystem_in_Rust_2.pdf)

- Blog and tutorial

There will be a [series](https://medium.com/@xorio42/list/828492b94c23) of articles about the evolution of this project, trying to keep it like a tutorial. This is the [first one](https://systemweakness.com/the-hitchhikers-guide-to-building-an-encrypted-filesystem-in-rust-4d678c57d65c).

- Talks

Expand All @@ -62,11 +59,27 @@ You can use it as CLI or as a library to build your custom FUSE implementation o

# Features

- [KEY features](docs/Key_features.md)

- GUI

There is a [GUI](https://github.com/radumarias/rencfs-desktop/blob/main/demo.gif) too.
- Key features

Some of these are still being worked on and marked with `[WIP]`.
- `Security` using well-known audited `AEAD` cryptography primitives;
- [WIP] [Data integrity, data is written with WAL to ensure integrity even on crash or power loss](https://github.com/radumarias/rencfs/issues/48)
- [WIP] [Hide all info for enhanced privacy; all metadata, content, file name, file size, *time fields, files count, and directory structure is encrypted](https://github.com/radumarias/rencfs/issues/53)
- `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](https://github.com/radumarias/rencfs/issues/47)
- [WIP] [Add file inode and chunk index to AAD](https://github.com/radumarias/rencfs/issues/49) This prevents blocks from being copied between or within files by an attacker.
- `Fast seek` on both reads and writes;
- `Writes in parallel`;
- Exposed with `FUSE`;
- Fully `concurrent` for all operations;
- [WIP] [Handle long file names](https://github.com/radumarias/rencfs/issues/47)
- [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](https://github.com/radumarias/rencfs/issues/97)
- [WIP] [Abstraction layer to access the storage with implementations for desktop, Wasm, Android, and iOS and the ability to write your own implementation](https://github.com/radumarias/rencfs/issues/111)

- [Alternatives](docs/Alternatives.md)
radumarias marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -82,17 +95,14 @@ There is a [GUI](https://github.com/radumarias/rencfs-desktop/blob/main/demo.gif

# Documentation

- Docs
- [Docs](docs/)

[![rencfs](website/resources/layers.png)](website/resources/layers.png)

For detailed description of the various sequence flows please look into [Flows](docs/flows.md).


- What separates us

[Asked](https://chatgpt.com/share/66e7a5a5-d254-8003-9359-9b1556b75fe9) ChatGPT if there are other solutions out there which offer all the key functionalities we do, seems like there are none :)
You can see the [key features](README.md#key-features) that separate us.



Expand All @@ -109,33 +119,36 @@ You can see the [key features](README.md#key-features) that separate us.



# Future and Considerations
# Next steps

- Future

The plan is to implement it also on macOS and Windows
- The plan is to implement it also on macOS and Windows
- **Systemd service** is being worked on [rencfs-daemon](https://github.com/radumarias/rencfs-daemon)
- **GUI** is being worked on [rencfs-desktop](https://github.com/radumarias/rencfs-desktop) and [rencfs-kotlin](https://github.com/radumarias/rencfs-kotlin)
- **Mobile apps** for **Android** and **iOS** are being worked on [rencfs-kotlin](https://github.com/radumarias/rencfs-kotlin)

- Performance
# Considerations
- Performance

`Aes256Gcm` is slightly faster than `ChaCha20Poly1305` by a factor of **1.28** on average. This is because of the hardware acceleration of AES
`Aes256Gcm` is slightly faster than `ChaCha20Poly1305` by a factor of **1.28** on average. This is because of the hardware acceleration of AES
on most CPUs via AES-NI. However, where hardware acceleration is not available, `ChaCha20Poly1305` is faster. Also `ChaChaPoly1305` is better at `SIMD`.

- [Cipher comparison](docs/Cipher_comparison.md)

- [⚠️ Security ](docs/Security.md)
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved

- [Considerations](docs/Considerations.md)
- [Cipher comparison](docs/Cipher_comparison.md)
- [Others](docs/Considerations.md)



# Contribute

Feel free to fork it, change and use it however you want. If you build something interesting and feel like sharing
- Feel free to fork it, change and use it however you want. If you build something interesting and feel like sharing
pull requests are always appreciated.

## How to contribute
- How to contribute

Please see [CONTRIBUTING.md](CONTRIBUTING.md).

# Follow us
- Blog and tutorial

Please see [CONTRIBUTING.md](CONTRIBUTING.md).
There will be a [series](https://medium.com/@xorio42/list/828492b94c23) of articles about the evolution of this project, trying to keep it like a tutorial. This is the [first one](https://systemweakness.com/the-hitchhikers-guide-to-building-an-encrypted-filesystem-in-rust-4d678c57d65c).
5 changes: 5 additions & 0 deletions docs/Altenatives.md → docs/Alternatives.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@
- [File Lock PEA](https://eck.cologne/peafactory/en/html/file_pea.html)
IoanaAlexandraO marked this conversation as resolved.
Show resolved Hide resolved
- [ZenCrypt](https://play.google.com/store/apps/details?id=com.zestas.cryptmyfiles&hl=en)
- [Hat.sh](https://hat.sh/)

- What separates us

[Asked](https://chatgpt.com/share/66e7a5a5-d254-8003-9359-9b1556b75fe9) ChatGPT if there are other solutions out there which offer all the key functionalities we do, seems like there are none :)
You can see the [key features](README.md#key-features) that separate us.
14 changes: 7 additions & 7 deletions docs/Key_features.md
Original file line number Diff line number Diff line change
@@ -1,21 +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;
- [WIP] [Data integrity, data is written with WAL to ensure integrity even on crash or power loss](https://github.com/radumarias/rencfs/issues/48)
- [WIP] [Hide all info for enhanced privacy; all metadata, content, file name, file size, *time fields, files count, and directory structure is encrypted](https://github.com/radumarias/rencfs/issues/53)
- `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`;
- [WIP] [Generate unique nonce in offline mode](https://github.com/radumarias/rencfs/issues/47)
- [WIP] [Add file inode and chunk index to AAD](https://github.com/radumarias/rencfs/issues/49) This prevents blocks from being copied between or within files by an attacker.
- `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.
- [WIP] [Handle long file names](https://github.com/radumarias/rencfs/issues/47)
- [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](https://github.com/radumarias/rencfs/issues/97)
- [WIP] [Abstraction layer to access the storage with implementations for desktop, Wasm, Android, and iOS and the ability to write your own implementation](https://github.com/radumarias/rencfs/issues/111)
12 changes: 9 additions & 3 deletions java-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use rencfs::crypto::Cipher;
use rencfs::encryptedfs::PasswordProvider;
use rencfs::log::log_init;
use rencfs::mount::{create_mount_point, umount, MountHandle};
use secrets::SecretVec;
use shush_rs::SecretString;
use std::collections::BTreeMap;
use std::ops::Add;
Expand Down Expand Up @@ -119,6 +120,8 @@ pub extern "system" fn Java_RustLibrary_mount(
let mount_path: String = env.get_string(&mnt).unwrap().into();
let data_dir_path: String = env.get_string(&data_dir).unwrap().into();
let password: String = env.get_string(&password).unwrap().into();
let new_pass = SecretVec::<u8>::new(password.into_bytes()); // create new pass using secretvec
// drop(password); // drop password after

info!("mount_path: {}", mount_path);
info!("data_dir_path: {}", data_dir_path);
Expand Down Expand Up @@ -171,21 +174,24 @@ pub extern "system" fn Java_RustLibrary_mount(
});
}

struct PasswordProviderImpl(String);
struct PasswordProviderImpl(SecretVec<u8>); // use secretvec instead of string
impl PasswordProvider for PasswordProviderImpl {
fn get_password(&self) -> Option<SecretString> {
Some(SecretString::from_str(&self.0).unwrap())
let password_str = String::from_utf8_lossy(self.0.expose_secret());
Some(SecretString::from_str(&password_str).unwrap())
}
}

let mount_point = create_mount_point(
Path::new(&mount_path),
Path::new(&data_dir_path),
Box::new(PasswordProviderImpl(password)),
Box::new(PasswordProviderImpl(new_pass)), // use the pass one time
Cipher::ChaCha20Poly1305,
false,
false,
false,
);
drop(new_pass); // drop pass after use

let handle = match RT.block_on(async {
match mount_point.mount().await {
Expand Down
17 changes: 17 additions & 0 deletions src/encryptedfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,17 @@ impl EncryptedFs {
self.read_only
}

fn validate_filename(&self, secret_filename: &SecretBox<String>) -> FsResult<()> {
let filename = secret_filename.expose_secret().to_string();
if filename.contains('/') {
Err(FsError::InvalidInput("'/' not allowed in the filename"))
} else if filename.contains('\\') {
Err(FsError::InvalidInput("'\\' not allowed in the filename"))
} else {
Ok(())
}
}

/// Create a new node in the filesystem
#[allow(clippy::missing_panics_doc)]
#[allow(clippy::missing_errors_doc)]
Expand All @@ -681,6 +692,7 @@ impl EncryptedFs {
if self.exists_by_name(parent, name)? {
return Err(FsError::AlreadyExists);
}
self.validate_filename(&name)?;

// spawn on a dedicated runtime to not interfere with other higher priority tasks
let self_clone = self
Expand Down Expand Up @@ -966,6 +978,7 @@ impl EncryptedFs {
if !matches!(attr.kind, FileType::RegularFile) {
return Err(FsError::InvalidInodeType);
}
// todo move to method
let self_clone = self
.self_weak
.lock()
Expand Down Expand Up @@ -1150,6 +1163,9 @@ impl EncryptedFs {
}
}
};

self.validate_filename(&name)?;

let file_path = entry.path().to_str().unwrap().to_owned();
// try from cache
let lock = self.dir_entries_meta_cache.get().await?;
Expand Down Expand Up @@ -1998,6 +2014,7 @@ impl EncryptedFs {
if !self.exists_by_name(parent, name)? {
return Err(FsError::NotFound("name not found"));
}
self.validate_filename(&new_name)?;

if parent == new_parent && name.expose_secret() == new_name.expose_secret() {
// no-op
Expand Down
Loading