48 个版本 (11 个破坏性更新)
新 0.13.66 | 2024 年 8 月 19 日 |
---|---|
0.13.59 | 2024 年 7 月 31 日 |
133 在 文件系统 中
每月 660 次下载
400KB
10K SLoC
rencfs
[!警告]
这个crate还没有被审计,它使用了众所周知且经过审计的ring
crate,所以原则上至少原始应该提供类似的安全级别。
这仍在开发中。请勿使用它处理敏感数据,请等待稳定版发布。
它主要适用于实验性和学习项目。
一个用 Rust 编写的加密文件系统,在 Linux 上通过 FUSE 挂载。它可以用来创建加密目录。
然后您可以安全地将加密目录备份到不受信任的服务器,而不用担心数据泄露。您也可以将其存储在任何云存储中,如Google Drive、Dropbox等,并跨多个设备同步。
您可以使用它作为 CLI 或用它构建自定义的 FUSE 实现。
主要特性
- 使用公认的经过审计的 AEAD 密码学原语进行安全
- 数据完整性,数据写入WAL以确保即使在崩溃或断电的情况下也能保持完整性
- 所有元数据和内容都进行了加密
- 使用 mlock(2) 和零化安全地管理内存中的凭据
- 基于密码生成加密密钥
- 密码保存在操作系统的密钥链中
- 更改密码而无需重新加密所有数据
- 读写操作中快速查找
- 并行写入
- 通过 FUSE 暴露
- 所有操作都是完全并发的
功能
- 它将所有加密数据和管理加密密钥的元信息保存在一个专用目录中,该目录中的文件按inode结构(包括元信息),二进制内容的文件和包含文件/目录条目的目录。所有数据、元数据和文件名都进行了加密。对于新文件,它在
u64
空间中随机生成inode编号,因此在使用离线并稍后同步时减少了冲突的机会。 - 密码从CLI收集并在应用程序运行时保存在操作系统密钥链中。这是出于安全原因,我们在不活动时从内存中清除密码,并在需要时再次从密钥链中重新加载它。
- 主加密密钥也使用从密码派生的另一个密钥进行加密。这允许在不重新加密所有数据的情况下更改密码,我们只需重新加密主密钥。
- 文件以256KB的块加密,因此在进行更改时,我们只需重新加密这些块。
- 读写时快速定位,因此如果您正在观看电影,您可以跳转到任何位置,这将非常快速。这是因为我们可以定位到特定的块。
- 加密密钥在空闲时在内存中进行
zeroize
。同时,它在使用时被mlock
以防止移动到交换区。在不读取时,它也被mprotect
。
进行中
- 通过将每次更改保存到WAL来确保文件完整性,因此,在崩溃或电源故障后重启时,我们将应用挂起的更改。这使得写操作原子化。
- 对同一文件进行并行写入,非常适合类似BT的应用程序
堆栈
- 它完全基于tokio和fuse3异步构建
- ring用于加密和argon2用于密钥派生函数(创建用于从密码加密主加密密钥的密钥)
- rand_chacha用于随机生成器
- secrecy用于在内存中安全地存储密码和加密密钥,并在不再使用时将其清零。它只在使用时将加密密钥保留在内存中,在不活跃时将释放并在内存中清零它们
- blake3用于哈希
- 使用keyring在OS密钥环中保存密码
- tracing用于日志记录
用法
使用Docker进行快速尝试
获取镜像
docker pull xorio42/rencfs
启动一个容器以在其中设置挂载
docker run -it --device /dev/fuse --cap-add SYS_ADMIN --security-opt apparmor:unconfined xorio42/rencfs:latest /bin/sh
在容器中创建挂载和数据目录
mkdir fsmnt && mkdir fsdata
启动rencfs
rencfs mount --mount-point fsmnt --data-dir fsdata
输入加密密码。
获取容器ID
docker ps
在另一个终端中,使用上述ID附加到正在运行的容器
docker exec -it <ID> /bin/sh
从这里,您可以在fsmnt
目录中创建文件来测试它
cd fsmnt
mkdir 1
ls
echo "test" > 1/test
cat 1/test
作为库
对于库,您可以查阅文档。
命令行工具
依赖关系
要使用加密文件系统,您需要在您的系统上安装FUSE。您可以通过运行以下命令(或根据您的发行版)进行安装。
Arch
sudo pacman -Syu && sudo pacman -S fuse3
Ubuntu
sudo apt-get update && sudo apt-get -y install fuse3
从AUR安装
您可以使用以下命令安装加密文件系统的二进制文件
yay -Syu && yay -S rencfs
使用cargo安装
您可以使用以下命令安装加密文件系统的二进制文件
cargo install rencfs
以下是一个使用加密文件系统的基本示例
rencfs mount --mount-point MOUNT_POINT --data-dir DATA_DIR
MOUNT_POINT
作为客户端,在给定路径挂载FUSEDATA_DIR
是存储加密数据的同步提供程序的位置。但它需要与data-dir位于同一文件系统上
它将提示您输入密码以加密/解密数据。
更改密码
主加密密钥存储在文件中,并使用从密码派生的密钥进行加密。这提供了更改密码而不需要重新加密整个数据的机会。这是通过使用旧密码解密主密钥,然后使用新密码重新加密它来完成的。
要更改密码,您可以运行以下命令
rencfs passwd --data-dir DATA_DIR
DATA_DIR
是加密数据存储的位置
它将提示您输入旧密码和新密码。
加密信息
您可以通过将此参数添加到命令行来指定加密算法。
--cipher CIPHER ...
其中,CIPHER
是加密算法。您可以使用 rencfs --help
命令来检查可用的加密。
默认值是 ChaCha20Poly1305
。
日志级别
您可以通过将 --log-level
参数添加到命令行来指定日志级别。可能的值有:TRACE
、DEBUG
、INFO(默认)、
WARN
、ERROR
。
rencfs --log-level LEVEL ...
在 Rust 中使用
更多信息请见这里
从源码构建
浏览器
您可以在浏览器中编译、运行并快速尝试它。启动它后
sudo apt-get update && sudo 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
打开另一个终端
cd mnt
mkdir a && cd a
echo "test" > test.txt
cat test.txt
本地
目前,FUSE
(fuse3
包)仅在 Linux
上工作,因此要启动项目,您需要在 Linux 上。或者,您可以在容器中开发,这将启动一个本地 Linux 容器,IDE 将连接到它,您可以在其中构建和启动应用程序,并使用终端测试它。
获取源代码
git clone [email protected]:radumarias/rencfs.git && cd rencfs
依赖关系
Rust
要从源码构建,您需要安装 Rust,有关如何安装的详细信息,请参阅这里。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
因此,Rust 开发者通常会将此目录包含在其 PATH
环境变量中。在安装过程中,rustup
将尝试配置 PATH
。由于平台、命令 shells 和 rustup
中的差异和错误,对 PATH
的修改可能需要重新启动控制台、注销用户或可能根本无法成功。
如果在安装后,在控制台中运行 rustc --version
失败,这很可能是最可能的原因。在这种情况下,请手动将其添加到 PATH
中。
项目配置为使用 nightly
工具链,在 rust-toolchain.toml
中,首次构建时将获取 nightly。
cargo install cargo-aur
cargo install cargo-generate-rpm
其他依赖项
此外,还需要以下依赖项(或根据您的发行版)
Arch
sudo pacman -Syu && sudo pacman -S fuse3 base-devel
Ubuntu
sudo apt-get update && sudo apt-get install fuse3 build-essential
Fedora
sudo dnf update && sudo dnf install fuse3 && dnf install @development-tools
调试构建
cargo build
发布构建
cargo build --release
运行
cargo run --release -- mount --mount-point MOUNT_POINT --data-dir DATA_DIR
开发设置
如果您不想被提示输入密码,可以设置此环境变量并按如下方式运行:
RENCFS_PASSWORD=PASS cargo run --release -- mount --mount-point MOUNT_POINT --data-dir DATA_DIR
对于开发模式,建议使用 DEBUG
日志级别运行。
cargo run --release -- --log-level DEBUG mount --mount-point MOUNT_POINT --data-dir DATA_DIR
为 Fedora 构建本地 RPM
这使用了 cargo-generate-rpm。
cargo install cargo-generate-rpm
cargo build --release
cargo generate-rpm
生成的 RPM 将位于此处:target/generate-rpm
。
安装和运行本地 RPM
cd target/generate-rpm/
sudo dnf localinstall rencfs-xxx.x86_64.rpm
在容器中开发
您可以使用项目中的 .devcontainer
目录来启动一个容器,其中包含构建和运行应用程序所需的所有必要工具。
最低支持的 Rust 版本 (MSRV)
最低支持的版本是 1.75
。
未来
- 计划也在 macOS 和 Windows 上实现它
- Systemd 服务正在开发中 rencfs-daemon
- GUI正在开发中 rencfs-desktop 和 rencfs-kotlin
- 移动应用针对 Android 和 iOS 正在开发中 rencfs-kotlin
性能
Aes256Gcm
平均比 ChaCha20Poly1305
快 1.28 倍。这是因为大多数 CPU 通过 AES-NI 对 AES 进行了硬件加速。但是,在没有硬件加速的地方,ChaCha20Poly1305
更快。此外,ChaChaPoly1305
在 SIMD
方面表现更好。
加密比较
AES-GCM 与 ChaCha20-Poly1305
- 如果你有硬件加速(例如
AES-NI
),那么AES-GCM
提供更好的性能。在我的基准测试中,它平均快了 1.28 倍。
如果你没有硬件加速,AES-GCM
要么比ChaCha20-Poly1305
慢,要么在缓存时间泄露你的加密密钥。 AES-GCM
可以针对多个安全级别(128-位
,192-位
,256-位
),而ChaCha20-Poly1305
仅定义在256-位
安全级别。- nonce 的大小
AES-GCM
:可变,但标准是96 位
(12 字节
)。如果你提供一个更长的 nonce,它将被哈希到16 字节
。ChaCha20-Poly1305
:标准版本使用96-位
nonce(12 字节
),但原始版本使用64-位
nonce(8 字节
)。
- 单个(密钥,nonce)对的磨损
AES-GCM
:消息长度必须小于2^32 – 2
块(即2^36 – 32 字节
,也称为2^39 – 256 位
),大约为64GB
。这也使得对具有长非ces的AES-GCM
的安全分析变得复杂,因为散列的非ces不以00 00 00 02
设置的最低4 字节
开始。ChaCha20-Poly1305
:ChaCha 有一个内部计数器(在标准化 IETF 变体中为32 位
,在原始设计中为64 位
)。最大消息长度为2^39 - 256 位
,大约为256GB
- 这两种算法都不是 nonce误用抵抗的。
ChaChaPoly1305
在SIMD
方面表现更好
结论
两者都是不错的选择。 AES-GCM
在 硬件支持 的情况下可能更快,但 ChaCha20-Poly1305
的纯软件实现几乎总是 快速 且 常量时间。
安全
- 幽灵读取:从文件中读取旧内容,这是不可能的。数据使用 WAL 写入,并定期刷新到文件。这确保了数据完整性和更改顺序。可能出现的一个问题是,如果我们执行截断操作,我们改变了文件的内容,但在我们用新的文件大小写入元数据之前进程被杀死了。在这种情况下,下次我们挂载系统时,我们仍然看到旧的文件大小。然而,文件的内容可能更大,我们读取到旧大小偏移量,因此我们不会拾取截断时增加大小所写入的新零字节。如果内容更小,读取会停止并结束实际内容的文件结束,所以这不会是一个大问题
- 会泄露什么样的元数据:几乎没有。文件名、实际文件大小和其他文件属性(时间、权限、其他标志)都保持加密。它可能泄露以下内容
- 如果一个目录有子目录,我们将这些子目录保存在一个以inode编号为名的目录中,子目录的加密名称作为文件存储在其中。因此,我们可以看到目录有多少个子目录。然而,我们不能识别实际的目录名,我们只能看到它的inode编号(每个文件的内部表示,类似于id),我们也不能看到目录或子目录的实际文件名。此外,我们也不能确定哪个文件内容对应于目录的子目录
- 每个文件内容都保存在单独的文件中,因此我们可以看到加密内容的尺寸,但不是实际文件大小
- 我们还可以看到文件最后被访问的时间
- 始终建议至少为敏感数据使用加密磁盘,本项目不是替代品
- 为了降低加密密钥从内存中被暴露的风险,建议在操作系统级别禁用内存转储。请参阅这里了解如何在Linux上操作
- 冷启动攻击:为了降低这种攻击的风险,我们将加密密钥保留在内存中,仅在我们真正需要它来加密/解密数据时,并在之后将其置零。我们还在一段时间的非活动期后将其从内存中删除
- 请注意,该项目尚未由任何安全专家审计。该项目以安全为前提,并尝试遵循所有最佳实践,但无法保证其安全性
- 此外,请备份您的数据,该项目仍在开发中,可能存在导致数据丢失的错误
注意事项
- 请注意,该项目并不试图重新发明轮子或优于已经证实的实现
- 该项目不想在任何方面替代已经证实的文件加密解决方案。如果您真的需要一个几乎无懈可击的解决方案,那么这可能不是最适合您的。但它试图提供一个简单的加密解决方案,在考虑上述所有安全问题时应该使用
- 它始于Rust编程语言的学习项目,我感到继续构建下去很有意义
- 这是一个相当简单且标准化的实现,试图尊重所有安全标准,正确使用安全和健壮的原始程序,以便可以在此基础上扩展。确实,它还没有达到可以“对抗”其他知名实现的成熟度。但它可以是一个供他人学习或在此基础上构建的项目,或者为什么不为一些人实际使用它并考虑到上述所有因素
贡献
请随意将其分叉,以任何您希望的方式更改和使用它。如果您构建了有趣的东西并愿意分享,则拉取请求总是受欢迎的。
如何贡献
请参阅CONTRIBUTING.md。
依赖关系
~23–38MB
~699K SLoC