1 个稳定版本
1.0.0 | 2021 年 6 月 30 日 |
---|
#814 在 密码学
115KB
2.5K SLoC
oramfs - 用 Rust 编写的 ORAM 文件系统
Oramfs 提供了一个完全加密且可选验证的无感知 RAM 文件系统。它不仅保护了数据机密性,还防止远程攻击者观察数据访问模式。
oramfs
特性
- ORAM - 加密文件并隐藏从远程存储中的读写访问模式。增强隐私!
- 可调整大小的 ORAM - 当需要更多空间时扩展您的 ORAM!
- 云存储无关 - 将您的文件同步到任何可以挂载为本地目录的远程服务器
- 文件系统无关 - 默认使用 ext4。手动模式允许您使用您喜欢的文件系统。
- 支持 多种加密算法 - ChaCha8,AES-CTR,AES-GCM
- 支持 多种 ORAM 方案 - 路径 ORAM 等。
- 用 Rust 编写 - 避免内存安全问题,性能优异
[免责声明] oramfs
是一个原型,可能不适合生产环境。它可能会删除您的一些数据。在使用此软件之前,请务必备份重要数据。
为什么使用 oramfs?
在加密文件系统中,ORAM 可以防止攻击者知道是否执行了读写操作以及文件系统的哪些部分被访问。这种增强的隐私性会带来性能损失。
设置 ORAM 需要两个输入。一个公共目录和一个私有目录。公共目录可以看作是服务器,私有目录可以看作是客户端。
公共目录可以是任何本地目录,包括挂载为本地目录的远程数据。因此,隐藏对远程 SSH 目录或远程云存储的访问模式是可能的。实际上,这些远程存储首先需要挂载为本地目录,然后,该目录可以用作 oramfs
的公共目录。例如,Rclone 支持将各种云存储服务挂载为本地目录。
私有目录是用于访问存储在ORAM中的文件的目录。对私有目录进行的任何操作都会影响公共目录。如果该公共目录是挂载的远程存储,那么每当对私有目录进行操作时,它就会安全且透明地与远程服务器同步。
要求
- Rust
- FUSE(在基于Debian的系统上,需要安装
libfuse-dev
包,在Arch上,需要安装fuse
包)
入门
如果尚未安装,请使用rustup安装Rust。
在/etc/fuse.conf
中,请确保启用user_allow_other
选项。
如果尚未安装,请使用您的包管理器安装libfuse-dev
包(基于Debian的系统)。对于其他系统,该包可能名称不同。
然后,使用cargo
构建oramfs
。
cargo build --release
为了获得最佳性能并利用原生CPU指令(AES-NI),请在发布模式下构建并针对原生CPU进行构建
RUSTFLAGS="-Ctarget-cpu=native" cargo build --release
oramfs
二进制文件将在target/release
目录下创建。为了方便,请将其添加到您的PATH
中。请注意,也可以使用cargo install --path .
安装二进制文件。它将默认安装到~/.cargo/bin
。
export PATH=$PATH:target/release
然后,创建或挂载一个要由ORAM保护的公共目录和一个私有目录
mkdir public
mkdir private
最后,运行可执行文件并创建一个名为myoram
的ORAM配置
oramfs add myoram public/ private/
按照交互式说明完成ORAM的设置。
一旦设置ORAM配置,详细信息将保存到~/.config/oramfs/oramfs.yml
。
现在,可以使用此配置随时挂载和卸载ORAM。
oramfs mount myoram
要卸载ORAM
oramfs umount myoram
要扩大ORAM的大小,请确保首先将其卸载,然后将其大小加倍
oramfs enlarge myoram
然后,它可以像往常一样挂载,大小将比之前更大。
它是如何工作的?
而不是实现完整的文件系统,oramfs
只提供挂载的文件。因此,用户应在该文件之上创建文件系统,使用循环设备,他们选择的文件系统,最后挂载该文件系统。请注意,此类操作通常需要root权限,因此oramfs
需要这些权限来挂载。通过调用sudo来实现这一点,因此oramfs
可以以普通用户身份运行。当调用sudo进行与挂载相关的操作时,它将提示您输入密码。
oramfs
接受一个公共目录作为输入,并公开一个单一的私有文件,该文件是读写操作的代理,从而使它们通过ORAM方案保持隐私。
挂载的私有文件可以使用losetup
设置循环设备。然后,可以在该循环设备上创建任何文件系统,例如ext4。 oramfs
自动化此过程,但也可以让用户手动执行,如果他们愿意的话。
+---------------------------------------------------+
| |
| ext4 filesystem | <---+ or any other FS or your choice
| |
+---------------------------------------------------+
| |
| Loop device (/dev/loop0) | <---+ created with losetup
| |
+---------------------------------------------------+
| |
| ORAMFS (FUSE) | <---+ Input : *public* local directory
| | Output : *private* single file,
+-------------------+-----------------+-------------+ for use with loop device
| | | |
| Local directory | Cloud storage | SSHFS | <---+ Input directory can be anything
| | | | that appears as a local directory,
+-------------------+-----------------+-------------+ including mounted remote directories.
Examples: SSH, FTP, anything supported
by rclone or similar tools,
any mounted FUSE filesystem, etc.
在开始使用ORAMFS之前
$ tree
.
├── private <---+ empty directory
└── public <---+ this is the directory that the attacker can see ("public" directory)
当使用ORAMFS时,在“私人”目录中进行的每个操作,或者在挂载点目录中直接对“oram”私人文件进行的操作,都会在“公共”目录中以ORAM化的形式出现。在标准使用场景中,用户不会直接修改“oram”私人文件,而是使用更高层次的抽象(“私人”目录中的文件系统)。用户通常在运行ORAMFS之前将其公共云存储挂载到“公共”目录,以便以保护隐私的方式透明地将公共文件同步到云中。
当使用ORAMFS时
$ tree
.
├── private
│ └── lost+found
│ └── very_private_document.txt
└── public
└── node_0.oram
└── node_1.oram
└── node_2.oram
└── ...
$ tree /tmp/oramfs_myoram/
/tmp/oramfs_myoram/
└── oram
远程存储示例
在这个例子中,我们将设置一个ORAM,它可以将数据透明地同步到远程FTP服务器。当然,可以使用任何其他远程存储(SSH服务器、Google Drive等)。任何可以挂载为本地目录的东西。
我们假设已经使用rclone config
为可以访问的FTP服务器配置了一个rclone
远程,使用rclone config
。该rclone
配置文件应该有一个针对该远程的条目,类似于以下内容:
[myftp]
type = ftp
host = 1.2.3.4
user = myusername
pass = mypassword
让我们将远程FTP服务器目录挂载为本地目录。我们将使用该目录作为ORAM的公共目录
rclone mount --daemon --allow-other --dir-cache-time 1s --poll-interval 1s --vfs-cache-mode writes --vfs-write-back 200ms myftp:somedirectory/ public
创建一个名为myoram
的ORAM
$ oramfs add myoram public/ private/
Please enter desired ORAM total size in bytes,
or press enter to use default [default: 16000000 (16 MB)]:
Adjusting ORAM size to closest valid value: 16711680 bytes
Please enter path to client data directory to use, or press enter to use default [default: /home/foobar/.config/oramfs/myoram]:
Please enter path to mointpoint directory to use, or press enter to use default [default: /tmp/oramfs_myoram]:
Successfully added ORAM myoram.
挂载ORAM,向其中写入文件
$ oramfs mount myoram
$ echo hello world > private/somefile
完成后,取消挂载
$ oramfs unmount myoram
就是这样!写入/读取到私人目录的文件都会加密,访问模式对FTP服务器隐藏。有关更多详细信息,请务必阅读下方的隐私部分。
配置
主要配置文件位于~/.config/oramfs/oramfs.yml
。可以通过简单地编辑该文件来修改现有的ORAM配置文件。例如,可以将ORAM方案从pathoram
更改为fakeoram
。有关所有选项的描述,请参阅oramfs add -h
。请注意,更改这些选项可能需要重新初始化ORAM,因此不可能在不丢失现有ORAM中的数据的情况下更改这些选项。
高级使用
使用cargo run -- -h
显示帮助
前台模式
默认情况下,oramfs
在后台运行。使用--foreground
以避免这种情况。
请注意,当oramfs
在前台运行时,意味着使用手动模式。
oramfs mount myoram --foreground
手动模式
为了最大程度地控制,可以使用手动模式(--manual
)。使用显式参数通过路径ORAM挂载ORAMFS。挂载的ORAMFS在指定的挂载点目录下作为一个文件出现。默认情况下,它位于/tmp/oramfs_{ORAM_NAME}/oram
。
mkdir private
mkdir public
oramfs add myoram public/ private/
oramfs mount myoram --manual
由于手动模式不会自动为您挂载文件系统,因此您必须自己完成。为此,在ORAM上创建一个ext4文件系统。请注意,mount
会自动为我们创建一个循环设备
mkfs.ext4 /tmp/oramfs_myoram/oram
mount -o sync /tmp/oramfs_myoram/oram private/
echo "hello oram" > private/hello.txt
使用不同于ext4的文件系统
oramfs
支持任何文件系统。要使用默认的ext4以外的其他文件系统,请执行以下操作。
在初始化期间,传递--manual
标志,然后在挂载点目录中的oram
文件上手动创建您选择的文件系统。以下是一个使用ext3的示例
oramfs add myoram public/ private/
oramfs mount myoram --manual
mkfs.ext3 /tmp/oramfs_myoram/oram
oramfs umount myoram
oramfs mount myoram
当使用不同的文件系统扩大ORAM时,传递--manual
标志。然后,手动调整大小和取消挂载oram
文件
oramfs umount myoram
oramfs enlarge myoram --manual
resize2fs -f /tmp/oramfs_myoram/oram # or equivalent for your filesystem
oramfs umount myoram
oramfs mount myoram
同时挂载多个ORAM
同时挂载多个ORAM时,请确保ORAM使用不同的公共目录、私有目录、挂载点和客户端数据目录。
ORAM初始化
重要:ORAM首次挂载时,会自动传递--init
选项。--init
是一个破坏性操作,它将永久销毁现有ORAM中的任何数据。实际上,手动传递--init
的需求很少。
oramfs
会检查全局或oramfs配置文件中的init
属性,以确定ORAM是否已经初始化。
使用除Path ORAM之外的其他ORAM方案
此原型目前仅实现了Path ORAM,但它设计得可以添加更多方案。为了证明这一点,内置了一个名为fakeoram
的第二个方案,但不建议在生产环境中使用,因为它不是真正的ORAM。FakeORAM是一个“Hello World”示例ORAM方案,对希望向oramfs
添加新ORAM方案的开发商可能很有用。
要使用另一个方案,例如fakeoram
,请更新配置文件,并将algorithm
条目更改为fakeoram
。然后简单挂载和初始化ORAM。
隐私
public
目录可以安全地镜像到云上,而云服务提供商不知道正在访问哪个文件以及是否执行了读写操作。一种场景是将远程Google Drive目录作为public
目录挂载,并使用该public
目录作为ORAMFS的公共目录。
性能
当可以使用本地CPU指令时,AES可能比ChaCha8更快。可以通过在添加ORAM时传递--cipher aes-ctr
或--cipher aes-gcm
标志来更改加密方式。也可以直接编辑配置文件,并使用更新的加密方式重新初始化ORAM。请注意,这将销毁ORAM中的任何数据,因此初始化ORAM时请谨慎操作。
为了获得最佳性能,请确保使用cargo
的--release
标志构建或运行,并传递环境变量RUSTFLAGS="-Ctarget-cpu=native"
。
基准测试
oramfs
与UtahFS进行了比较。Oramfs使用默认值(AES-GCM,16MB ORAM大小)。UtahFS使用本地磁盘,并将oram
选项设置为true。
请注意,性能高度依赖于n
、z
和b
参数在oramfs
中的选择。在此基准测试中,10MB使用默认值。然后将ORAM扩展(n
加倍)至25MB。
读取性能
文件大小 | oramfs | UtahFS | 加速 |
---|---|---|---|
10 MB | 1秒 | 9秒 | 9倍 |
25 MB | 3秒 | 26.5秒 | 8.8倍 |
写入性能
文件大小 | oramfs | UtahFS | 加速 |
---|---|---|---|
10 MB | 15秒 | 30秒 | 2倍 |
25 MB | 50秒 | 95秒 | 1.9倍 |
在SSD或闪存存储上的使用
对于每个读取或写入操作,ORAM方案实际上在幕后执行多个操作。即使是读取操作,也会执行底层的写入操作。这可能会显著缩短SSD的使用寿命。
限制和未来工作
请注意,oramfs
仍然是一个原型,并存在以下已知的局限性。
内存零化
当前在退出/崩溃时不会对内存进行零化。攻击者可能能够从未零化的内存中提取私钥或密码短语。
读取缓存
如果读取被缓存,那么 ORAM 不会对缓存读取进行任何操作。这是一个隐私问题,因为这意味着如果所有读取都被缓存,那么我们可以确信对公共目录的任何修改都必须是写入操作。
为了避免读取缓存,在 Linux 上,在从 ORAM 读取文件之前始终清除内核缓存
# sync; echo 1 > /proc/sys/vm/drop_caches
测试
使用 cargo test --release
运行测试
贡献
请随时提交问题或拉取请求。
代码应使用 rustfmt 格式化。要自动格式化整个项目
cargo fmt
运行 cargo build
和 cargo clippy
时不应出现警告。此外,所有测试都应该通过(见测试部分)。
许可证和版权
版权(c) 2021 Nagravision SA。
本程序是免费软件:您可以在自由软件基金会发布的 GNU 通用公共许可证第 3 版的条款下重新分发和/或修改它。
本程序以希望它将是有用的,但没有任何保证;甚至没有关于适销性或适用于特定目的的暗示保证。有关详细信息,请参阅 GNU 通用公共许可证。
您应已收到一份 GNU 通用公共许可证副本。如果没有,请参阅https://gnu.ac.cn/licenses/。
依赖项
~13–23MB
~335K SLoC