![MIT License](https://img.shields.io/badge/license-MIT-blue.svg) ============== EN | 中文 cppcryptfs ------ cppcryptfs 基于 [gocryptfs](https://github.com/rfjakob/gocryptfs) 的设计,gocryptfs 是一个用 Go 语言编写的加密覆盖文件系统。 cppcryptfs 是 gocryptfs 文件系统在 Windows 上的 C++ 实现。cppcryptfs 与 gocryptfs 兼容。使用其中一个创建的文件系统通常可以用另一个进行挂载(和同步)。请参阅本文档末尾附近关于兼容性的声明。 cppcryptfs 提供对虚拟文件系统中的文件和文件名进行实时、静态和云端加密。它使用 [Dokany](https://github.com/dokan-dev/dokany) 驱动程序和库在 Windows 下的用户模式中提供虚拟文件系统。 **重要提示**:根据 [此](https://github.com/rfjakob/gocryptfs/issues/50) 讨论,如果你的密码很强,你才应该将创建的 gocryptfs.conf 存储在云端。 如果攻击者获取了你的 gocryptfs.conf,那么他们将能够动用他们拥有的任何资源对你加密的密码进行暴力破解。增加 scryptn 会减慢他们的破解速度(见下文)。开发者将他的 gocryptfs.conf 存储在云端并使用非常强的密码。 你可以使用 cppcryptfs 在一个文件夹中创建一个加密文件系统。这个加密文件系统由你选择的密码保护。 当你使用 cppcryptfs 并提供密码来挂载加密文件系统时,你将在 Windows 中获得一个新的驱动器号。这个虚拟驱动器号为你提供文件的未加密视图。加密和解密是实时进行的,对使用该虚拟驱动器上文件的应用程序是透明的。 当你告诉 cppcryptfs 卸载虚拟驱动器号后,除非使用你的密码重新挂载该文件系统,否则无法访问你的未加密数据。 关闭计算机将自动卸载所有 cppcryptfs 驱动器号。 如果保存加密文件的文件夹正在与云服务同步,那么只有带有加密文件名的加密文件会被上传到云服务。 这样,云服务的员工和任何入侵云服务的人都无法使用你的文件。 此外,如果有人偷走了你的计算机,并且加密文件系统未被挂载,那么小偷无法使用你的文件。 由于加密是按文件进行的,而不是使用容器文件来存储数据,你不必提前决定需要多少加密存储空间。cppcryptfs 的存储开销非常小,并且你的加密文件系统可以动态增长,仅受加密文件系统所在物理驱动器上可用空间的限制。 按文件加密相对于基于容器的加密的另一个优点是,按文件加密可以非常快速有效地与基于云的服务同步。 当前状态 -------------- 开发者已经在正向(正常)模式下使用 cppcryptfs 超过三年,并且没有丢失任何数据。至少有另一个人也在使用它。 反向模式仅由开发者进行了有限的测试。 由开发者 Bailey Brown Jr 签名的二进制版本发布在 [发布页面](https://github.com/bailey27/cppcryptfs/releases) 上。 为了以防万一,备份你的数据总是明智的。 测试 ------- 当以管理员身份运行时,cppcryptfs 在 [winfstest](https://github.com/bailey27/winfstest) 中通过了 506/506 个测试。如果没有管理员权限,cppcryptfs 通过 500/506 个测试。这个 winfstest 是从 Dokany 项目使用的版本派生而来的。Dokany 团队添加了额外的测试。 cppcryptfs 在没有管理员权限运行时失败的测试与对 DACL(自由访问控制列表)的操作有关。为了使这些操作正常工作,cppcryptfs 必须以管理员身份运行。在没有管理员权限的情况下运行似乎不会影响 cppcryptfs 的正常使用。 注意:Windows 10 版本 1909(操作系统版本 18363.1016)似乎允许 cppcryptfs 在不必以管理员身份运行的情况下通过所有 506 个测试。 构建要求 ----- Microsoft Visual Studio 2022 社区版、perl、nasm 和 git(均为免费) OpenSSL - https://github.com/openssl/openssl(需要静态构建) RapidJSON - https://github.com/miloyip/rapidjson(用于解析 gocryptfs.conf) Dokany - https://github.com/dokan-dev/dokany 对于 Dokany,你可能想从这里使用二进制发行版: https://github.com/dokan-dev/dokany/releases (确保在安装程序选项中选择“安装开发文件”) 在 [INSTALL.md](INSTALL.md) 中有详细的构建说明。 cppcryptfs 当前与 Dokany 2.3.0.1000 保持同步。 使用方法 ------- cppcryptfs 运行时不需要管理员权限,但 如果它不是以管理员身份运行,那么它将无法获取 SE_SECURITY_NAME 权限。SE_SECURITY_NAME 是 Windows API 函数 SetFileSecurity() 和 GetFileSecurity() 执行某些操作所必需的。 cppcryptfs 在没有 SE_SECURITY_NAME 权限的情况下似乎也能正常工作。如果你遇到问题,可以尝试以管理员身份运行 cppcryptfs,看看是否有帮助。 在 Windows 上,你应该对页面文件进行加密,以避免在磁盘上泄露敏感数据。首先以管理员身份在 CMD.exe 中运行以下命令:`fsutil behavior set EncryptPagingFile 1`。 要创建一个新的加密虚拟文件系统,首先点击“创建”选项卡。 ![Alt text](/screenshots/screenshot_create.png?raw=true "创建选项卡") 你需要找到或创建一个目录作为文件系统的根目录。你可以在用户界面的目录选择器中创建一个目录。 如果你使用的是正常(正向)模式,那么这个目录必须为空。 如果你使用的是反向模式,那么该目录不必为空(请参阅本文档中关于反向模式的部分)。 强烈建议这个目录位于 NTFS 文件系统上。 然后你需要选择一个(希望是强密码)并重复输入。对话框最多接受 255 个字符的密码。 密码字段类将一个字符视为特殊字符。这个字符看起来像一个小 x,但又不一样。它是 Unicode 215,即十六进制的 0xd7。 结果是你不能在密码中使用该字符。 你可以选择使用 AES256-EME 对文件名进行加密,或者不加密文件名(纯文本)。 如果勾选了“长文件名”,那么在使用加密文件名时,文件和目录的名称最长可以达到 255 个字符。如果使用纯文本文件名,此选项无效(纯文本文件名最长可以达到 255 个字符)。有关更多信息,请参阅本文档末尾附近的“文件名和路径长度限制”部分。 如果选择了小于 255 的“长名称最大值”(最小值为 62),那么 cppcryptfs 将限制文件名长度。即使选择 62,创建的文件名最长也可达 67 个字符。当使用对文件名长度有一定限制的云服务时,此选项很有用。 如果勾选了“确定性名称”,那么 cppcryptfs 将不使用 DirIV 文件。以下解释摘自 gocryptfs 手册页: ``` 禁用文件名随机化和 gocryptfs.diriv 文件的创建。这可以防止在同步文件时发生同步冲突,但会泄露跨目录相同文件名的信息(请参阅 https://nuetzlich.net/gocryptfs/comparison/#file-names 中的 “相同名称泄露”)。 生成的 gocryptfs.conf 中 “FeatureFlags” 里会缺少 “DirIV”。 ``` 你可以选择 AES256-GCM 或 AES256-SIV(RFC 5297)对文件数据进行加密。默认是 AES256-GCM,推荐使用。对于流式读写,GCM 的速度大约是 SIV 的两倍。实现 SIV 是为了支持反向模式。 注意:在 gocryptfs 文档中,SIV 模式被称为 AES-512-SIV,这是此操作模式的正确名称。然而,在 cppcryptfs 中它被称为 AES256-SIV,因为 512 位的 SIV 密钥是从 256 位的主密钥派生而来的(gocryptfs 也是如此)。此外,cppcryptfs 的开发者不想在用户界面中将其称为 AES512-SIV,因为这可能会让用户认为它比 AES256-GCM 更安全。 如果你勾选“反向”,那么你将创建一个反向模式的文件系统。有关更多信息,请参阅本文档中关于反向模式的部分。 如果你愿意,你可以指定一个配置文件。这个文件包含文件系统的设置,以及使用你的密码加密的随机 256 位 AES 主密钥。为了额外的安全性,配置文件可以保存在加密文件系统之外。 当你点击“创建”按钮时,将创建配置文件。除非你指定了其他配置文件,否则它将在加密文件系统的根目录中创建为 gocryptfs.conf。除非你选择使用纯文本文件名,否则还会在那里创建一个 gocryptfs.diriv。确保备份这些文件,以防它们丢失或损坏。如果 gocryptfs.conf 出现问题,你将无法访问任何数据。除非你更改卷标(见下文),否则 gocryptfs.conf 在文件系统的整个生命周期内都不会改变。 如果你选择为卷添加标签,那么该标签将在 gocryptfs.conf 中加密。卷标最大长度为 32 个字符。 卷标使用主密钥、128 位随机初始化向量和 8 字节零认证数据进行 AES256-GCM 加密。然后将其与初始化向量一起进行 base64 编码并保存在 gocryptfs.conf 中。 你可以在文件资源管理器中右键单击已挂载的驱动器号,选择“属性”,然后更改卷标。但是,这样做会导致 cppcryptfs 在卸载驱动器时重写 gocryptfs.conf。这确实会给你的 gocryptfs.conf 带来一些风险。同样,最好将你的 gocryptfs.conf 文件备份到其他地方。 如果底层文件系统(例如通过 Samba 共享的 Linux 文件系统)不支持命名流,则可能需要“禁用命名流”选项。cppcryptfs 通常会在挂载时自动检测底层文件系统是否支持命名流。但是,在某些配置中,底层文件系统报告它支持命名流,但实际上并不支持。开发者在 Ubuntu 16.04 Samba 上进行了测试,没有遇到这个问题。添加此功能是为了帮助一个在不同 Linux 版本上遇到此问题的用户。如果你在使用 Samba 时遇到问题,并且想在创建文件系统后追溯禁用命名流,请参阅 https://github.com/bailey27/cppcryptfs/issues/63。 然后转到“挂载”选项卡,选择一个驱动器号并选择你刚刚创建文件系统的文件夹。然后输入密码并点击“挂载”按钮。 ![Alt text](/screenshots/screenshot_mount.png?raw=true "挂载选项卡") 你也可以在驱动器号列表中右键单击并选择“添加挂载点”。这将允许你将一个空目录添加到驱动器号列表中。这个空目录(必须位于 NTFS 卷上)可以作为挂载点代替驱动器号。添加的挂载点将添加到驱动器号下方的列表中。你也可以右键单击添加的挂载点并将其从列表中删除。你添加的挂载点目录会保存在 Windows 注册表中。 注意:虽然 A: 和 B: 可以用作挂载点,但不建议使用它们,因为已知将加密文件系统挂载到它们会导致 Windows 更新出现问题。 你还可以右键单击已挂载的文件系统,然后卸载它或[查看其属性](/screenshots/screenshot_properties.png?raw=true)。 双击已挂载的卷将在其上打开一个文件资源管理器窗口。 如果在创建文件系统时为配置文件指定了自定义路径,那么在此处也必须指定该路径。 如果为配置文件指定了自定义路径,并且该文件系统是反向文件系统,则还必须选择“反向”。否则,cppcryptfs 将自动检测文件系统应以前向还是反向模式挂载。 注意:cppcryptfs 使用加密文件系统的路径作为键,来记住配置文件的自定义路径(如果有的话)以及反向和只读等其他设置。因此,当你选择要挂载的路径时,请务必验证这些设置是否是你此次希望使用的设置。 有关“scryptn”的信息,请参阅 cppcryptfsctl 的 --scryptn 参数文档。 挂载文件系统后,你将获得一个新的驱动器号,你可以像使用普通驱动器号一样使用它,并在其中存储敏感信息。数据会被加密并保存在你指定文件夹中的文件里。 如果勾选“只读”,则文件系统将以只读(写保护)模式挂载。 有关 cppcryptfs 中保存密码的工作原理的解释,请参阅下面的“保存的密码”部分。 如果勾选“自动挂载”(此功能需要保存密码才能生效),那么下次启动 cppcryptfs 时,该路径将在启动时挂载到该挂载点。要使此功能生效,你必须已为该挂载保存了密码。 该路径将继续自动挂载,直到你在取消勾选“自动挂载”的情况下手动挂载它。 有关 gocryptfs 加密设计的技术细节,请访问[gocryptfs 项目页面](https://github.com/rfjakob/gocryptfs)。 当你使用完驱动器号后,转到“挂载”选项卡,选择驱动器号,然后单击“卸载”或单击“全部卸载”。驱动器号将被卸载,加密密钥将从内存中删除。 只要有可用的未使用驱动器号,你就可以挂载任意数量的 gocryptfs 文件系统。 密码和密钥使用 VirtualLock() 锁定在内存中。当它们不再需要时,使用 SecureZeroMemory() 将其擦除,然后解锁。如果你从不使计算机进入休眠状态,那么你不必担心密码或密钥会被写入硬盘。 如果关闭 cppcryptfs 窗口,它将隐藏在系统托盘中。要退出 cppcryptfs,请使用挂载页面上的“退出”按钮或系统托盘图标上的上下文菜单。 设置 --------- 还有一个设置选项卡。 ![Alt text](/screenshots/screenshot_settings.png?raw=true "设置选项卡") *显示推荐设置* 在设置选项卡上更改值会影响随后挂载的所有文件系统。任何已经挂载的文件系统都不会受到影响。 当前设置存储在 Windows 注册表中,下次挂载文件系统时(即使是从命令行挂载)也会使用这些设置。 设置选项卡有以下设置: **I/O 缓冲区大小(KB)** 此设置控制 cppcryptfs 在底层文件系统上进行的最大读写大小。 cppcryptfs 实际上以加密块大小的倍数进行 I/O 操作,加密块大小为 4,128 字节。因此,当你指定 4KB 时,缓冲区大小实际上是 4,128 字节;当你指定 1024KB 时,缓冲区大小实际上是 1,056,768 字节。 增大 I/O 缓冲区大小可能会提高性能。 **缓存生存时间** cppcryptfs 会缓存有关文件系统的信息。如果缓存中的某个条目超过了生存时间,那么在使用该条目之前会对其进行重新验证。 增加缓存生存时间或将其设置为无限期可能会提高性能。 但是,如果你经常将 cppcryptfs 文件系统与运行在另一台计算机上的另一个 cppcryptfs 实例或 gocryptfs 实例下的同一文件系统的副本进行同步,那么将生存时间设置得过高可能会导致错误,前提是文件系统在另一台计算机上被修改。 如果你不在两个同时运行的 cppcryptfs 实例之间或 cppcryptfs 实例与 gocryptfs 实例之间同步文件系统,那么没有理由不将缓存生存时间设置为较高的值或无限期。 **多线程** 如果启用此选项,则每个文件系统可以有多个线程处理请求。这可能会提高性能。Dokany 会自动选择要使用的线程数。 如果禁用此选项,则每个文件系统将仅使用一个线程来处理请求。 **不区分大小写** 此选项仅在前向模式下且使用加密文件名时有效。使用加密文件名的反向模式文件系统始终区分大小写,而使用纯文本文件名的文件系统始终不区分大小写。 通常,当使用文件名加密时,cppcryptfs 要求使用与创建文件和目录时相同的大小写来打开文件和目录。 如果勾选了不区分大小写选项,那么在前向模式下,即使使用文件名加密,cppcryptfs 也会忽略文件和目录名的大小写。这与 Windows API 的正常操作方式相同。不过,性能会稍慢一些。 有关更多信息,请参阅“大小写敏感性”部分。 **启用挂载管理器(回收站)** 当选择默认设置或推荐设置时,此设置当前未启用。如果你希望使用它,则必须单独启用。此设置尚未经过全面测试。 此设置可在加密卷上启用 Windows 挂载管理器。启用挂载管理器后可启用回收站。此设置仅在以管理员身份运行 cppcryptfs 时有效。如果你在勾选此设置的情况下尝试挂载文件系统,但 cppcryptfs 未以管理员身份运行,那么 cppcryptfs 将显示一个警告对话框(可以禁用),并且不会启用挂载管理器。 此设置对反向文件系统或以只读模式挂载的文件系统无效。 注意:如果你正在将文件系统的加密文件与 Dropbox 同步,那么如果你启用挂载管理器(回收站),Dropbox 将无法同步回收站中的文件,因为它没有足够的权限。 你应该以管理员身份运行 Dropbox,或者确定哪个加密文件夹名是回收站的名称,并使用 Dropbox 的选择性同步功能将其排除。如果你使用的是纯文本文件名,那么回收站将简单地显示为“$RECYCLE.BIN”。如果将文件系统根目录的(未加密)路径作为参数提供给 --list 命令行开关,则可以使用该开关来查找回收站的加密名称。 例如: ``` cppcryptfs --list=d:\ ``` **启用保存密码** 此设置可启用密码保存功能。有关保存密码的更多信息,请参阅下面的“保存的密码”部分。 启用此设置后,挂载选项卡中的“保存密码”复选框将可用。 如果将“启用保存密码”设置从勾选状态更改为未勾选状态,那么 cppcryptfs 会询问是否应删除所有保存的密码。 在默认设置和推荐设置中,此设置均未启用。 **从不保存历史记录** 此设置可防止 cppcryptfs 在 Windows 注册表中保存除本页面所述值之外的任何值。例如,它将防止保存历史记录中的路径,并且即使启用了保存密码功能,也不会保存密码。 勾选此设置后,cppcryptfs 在 Windows 注册表中存储的所有值都将被删除,但本页面所述的设置除外(保存的密码除外)。但是,在此设置生效期间,不会保存任何新密码。 要删除保存的密码,你必须取消勾选“保存密码”设置。 在默认设置和推荐设置中,此设置均未启用。 **删除 desktop.ini 文件** 此设置是为解决 [https://github.com/bailey27/cppcryptfs/issues/62](https://github.com/bailey27/cppcryptfs/issues/62) 创建的。据报告,Google Drive 会在加密文件源文件夹的每个目录中创建隐藏的 desktop.ini 文件。这些文件阻止用户从非加密端删除目录。如果在启用此设置的情况下挂载文件系统,那么 cppcryptfs 在删除目录时将自动删除未加密的 desktop.ini 文件。 此设置仅在前向模式下且使用加密文件名时有效。 在默认设置和推荐设置中,此设置均未启用。 **挂载时打开** 如果启用此设置,那么在挂载加密卷时,它将使用默认的 Windows 文件管理程序(通常是文件资源管理器)自动打开。 在默认设置和推荐设置中,此设置均未启用。 **在内存中加密密钥** 启用此设置后,cppcryptfs 在不需要加密密钥(主密钥和任何派生密钥)时,会使用 Windows 数据保护 API (DPAPI) 对其进行加密。密钥使用 DPAPI 进行加密,在需要时进行解密,然后在不需要时将未加密的副本清零。有关 DPAPI 的更多信息,请参阅下面的“保存的密码”部分。 此设置可降低恶意软件从 cppcryptfs 进程内存中读取未加密密钥的风险。 此外,此设置可防止未加密的密钥在系统进入休眠状态时出现在休眠文件中。 此设置是全新的,**其实现过程中的任何漏洞都可能导致数据丢失**。建议仅在你经常备份加密文件系统时使用此设置。 建议将此设置与“在内存中缓存密钥”(见下文)配合使用。否则,如果不启用“在内存中缓存密钥”,性能将受到显著影响。 无论是默认设置还是推荐设置,都未启用此设置。 **在内存中缓存密钥** 除非启用“在内存中加密密钥”,否则此设置无效。 当启用此设置且同时启用了在内存中加密密钥时,cppcryptfs 将在使用间隔内缓存未加密的密钥,最长缓存时间为一秒。 此设置可将“在内存中加密密钥”对性能的影响基本降为零。如果不启用此设置,在内存中加密密钥会显著降低性能。 当系统即将进入待机或休眠模式时,cppcryptfs 会自动禁用缓存,这样在系统进入低功耗模式时,未加密的密钥就不会留在内存中。系统唤醒时,缓存会自动重新启用。 无论是默认设置还是推荐设置,都未启用此设置。 **启用快速挂载** 以前,cppcryptfs 总是等待 Dokany 回调以指示挂载操作是否成功。 Dokany 通常需要 5 秒才能回调。然而,文件系统几乎会立即显示为已挂载并可用。 启用快速挂载后,cppcryptfs 既会等待 Dokany 的回调,也会定期检查(轮询)文件系统是否已挂载。如果 cppcryptfs 发现文件系统似乎已挂载,它将停止等待 Dokany 的回调,并假定挂载操作成功。如果禁用此设置,cppcryptfs 将仅等待 Dokany 的回调。 启用此设置后,在开发人员的机器上,成功的挂载操作大约在 31 毫秒内完成,而不是之前的 5 秒。 注意:当挂载点是一个空的 NTFS 目录而不是驱动器号时,此设置无效。如果挂载点是目录,Dokany 会迅速发出挂载成功的信号,在这种情况下轮询没有意义。 此设置默认启用。 **卸载时若正在使用则发出警告** 如果启用此设置,当用户尝试卸载文件系统、卸载所有文件系统或退出程序时,如果挂载的文件系统上仍有任何打开的文件或目录,cppcryptfs 将通知用户并询问是否应继续卸载。 如果启用此设置,在卸载正在使用的文件系统时,命令行中需要使用 --force 标志。 无论是默认设置还是推荐设置,都未启用此设置。 **拒绝其他会话访问** 如果启用此设置,加密卷将仅在启动挂载它们的 cppcryptfs 实例的会话中可访问。用于挂载的任何驱动器号在其他会话中仍然可见,但其他会话无法访问这些驱动器。 此检查仅在调用 CreateFile API(该 API 既可以创建新文件和目录,也可以打开现有文件和目录)时进行。仅在 CreateFile 中拒绝其他会话的访问似乎就足够了。 此功能的测试范围让开发人员相信,此设置可以使挂载的卷免受共享同一台计算机并登录到不同会话的其他普通登录用户的访问。然而,不能确定一个有决心且有知识的攻击者无法找到绕过此保护的方法。 有关更多信息,请参阅下面的“拒绝服务访问”说明。 无论是默认设置还是推荐设置,都未启用此设置。 **拒绝服务访问** 如果启用此设置,加密卷将无法被在会话 0 中运行的 Windows 服务访问。 在系统账户下运行的 Windows 服务或具有“作为操作系统的一部分执行”用户权限的用户创建的进程,有可能创建访问令牌并在其中设置任意会话 ID。因此,此保护并非绝对可靠,但应能防止 Windows 服务在正常使用情况下访问挂载的文件系统。 无论是默认设置还是推荐设置,都未启用此设置。 **默认设置和推荐设置** 这些按钮可将所有设置恢复为默认设置或推荐设置。 目前,默认设置和推荐设置相同。 **重置警告** 按下“重置警告”按钮将重新启用之前通过选择“不再显示此消息”而禁用的任何警告对话框。 更多设置 --------- 还有一个设置选项卡。 ![Alt text](/screenshots/screenshot_more_settings.png?raw=true "设置选项卡") *显示推荐设置* 更多设置选项卡有以下附加设置: **写入后启用刷新** 有用户报告,在将大量数据复制到使用 exFAT 文件系统格式化的外部驱动器时会出现超时问题。 这个问题似乎是 exFAT 特有的。 解决方法是启用写入后刷新。启用此设置后,cppcryptfs 会在每次被要求执行写入操作后,强制 Windows 将数据写入磁盘。 此选项会显著降低写入性能。对于复制大文件,性能大约降低 50%。对于大量小文件,性能下降得更严重。 如果任何条件为真,则此设置开启,因此若要始终启用它,可以同时勾选“NTFS”和“非 NTFS”框。 保存的密码 ------ 如果在设置选项卡中启用了“启用保存密码”设置,那么挂载选项卡上的“保存密码”复选框将可用。 当 cppcryptfs 保存密码时,它会使用 Windows 数据保护 API (DPAPI) 对密码进行加密。Windows DPAPI 的相关信息可在此处查看。 https://msdn.microsoft.com/en-us/library/ms995355.aspx 使用 Windows DPAPI 加密的数据的安全性仅取决于用于登录 Windows 的密码的强度和安全性。 保存的密码与加密文件系统的根路径相关联。 此外,“保存密码”设置本身也与路径相关联。 要保存密码,请在挂载文件系统时确保勾选“保存密码”框。 密码将使用 DPAPI 加密并保存在 Windows 注册表中。 要在不输入密码的情况下挂载文件系统,请确保勾选“保存密码”,然后从路径历史记录中选择路径,此时该路径的密码(如果找到)将填充到密码字段中(显示为圆点)。或者,如果你不选择路径,而是在路径字段中输入路径并在不输入密码的情况下按下挂载按钮,那么如果找到该路径的保存密码,将使用该密码。 可以使用 -P 命令行选项从命令行使用该路径保存的密码来挂载文件系统。 反向模式 ------ 在反向模式下,文件系统使用的源(根)目录包含未加密的文件。挂载此目录后,cppcryptfs 驱动器号将提供这些文件的即时加密视图。 反向模式还会显示配置文件(显示为 gocryptfs.conf),如果使用了加密文件名,每个目录中还会显示一个 gocryptfs.diriv 文件。如果在使用加密文件名时使用了长文件名,还会显示特殊的长文件名文件。 反向模式文件系统始终以只读方式挂载。 创建反向模式文件系统时,文件系统的根目录不必为空(这与创建普通正向模式文件系统的情况不同)。cppcryptfs 将在文件系统的根目录中创建配置文件。这是一个隐藏文件,名为 .gocryptfs.reverse.conf(而不是普通/正向模式中使用的非隐藏的 gocryptfs.conf)。 当你尝试挂载文件系统时,cppcryptfs 首先会查找 .gocryptfs.reverse.conf,如果找到它,将以反向模式挂载文件系统。如果未找到 .gocryptfs.reverse.conf,它将尝试打开 gocryptfs.conf,如果成功,文件系统将以正向(正常)模式挂载。 如果你指定了自定义配置文件路径,则必须勾选“反向”以反向模式挂载文件系统。 如果你挂载了一个反向文件系统,然后将整个目录树复制到其他位置,你可以将该副本(包含加密文件、正常模式配置文件和其他支持文件)作为正向(正常)文件系统挂载。 反向模式适用于你想备份未加密文件的目录树,但希望备份文件是加密的情况。 反向模式对文件数据使用确定性的 AES256 - SIV 加密模式(实际上是 AES512 - SIV,但 512 位的 SIV 密钥是从 256 位的主密钥派生而来),并且对文件名的加密也是确定性的。 注意:当你以正向模式使用 AES256 - SIV 挂载文件系统时,任何新的加密操作都是非确定性的(就像 gocryptfs 那样)。 由于反向模式下的加密是确定性的,你可以使用像 rsync 这样的工具来备份加密文件,它只会复制那些发生了更改的文件。此外,如果你的备份工具支持增量同步(如 rsync),在处理未加密数据时可以进行增量同步,那么在反向模式下处理加密数据时,只要数据是在原地更改的,它也能进行增量同步。然而,如果向文件中插入数据,那么从插入数据的位置开始(实际上是从整个加密块开始),加密文件数据会出现级联更改,从该位置起的数据需要再次复制。 可以以正向模式挂载已挂载的反向文件系统。正向文件系统也将是只读的,这主要用于测试。 ### 命令行选项 cppcryptfs 接受一些用于挂载和卸载文件系统的命令行选项。目前,只能通过图形用户界面 (GUI) 创建文件系统。 cppcryptfs 只能有一个主实例运行。如果没有其他 cppcryptfs 实例正在运行,那么 cppcryptfs 会处理命令行参数,然后继续运行。如果已经有另一个 cppcryptfs 实例正在运行,那么 cppcryptfs 会将其命令行参数发送给正在运行的主实例。如果从控制台窗口运行,它会将处理命令行的任何输出打印到控制台。如果不是从控制台运行,它会在消息框中显示输出。 还有一个配套程序 cppcryptfsctl,可用于向正在运行的 cppcryptfs 发送命令。cppcryptfsctl 是一个控制台程序,使用它的优点是它会设置 ERRORLEVEL,因此可以在批处理脚本中进行测试。此外,还可以将 cppcryptfsctl 的输出重定向到文件,或将其通过管道传递给其他程序,如 grep 或 findstr。而 cppcryptfs 不会设置 ERRORLEVEL,其输出也不能被重定向。 cppcryptfsctl 在成功时将 ERRORLEVEL 设置为 0,发生错误时设置为 1,如果无法连接(意味着 cppcryptfs 没有运行)则设置为 2。 通过命令行传递的密码并不十分安全。cppcryptfs 会锁定并清空其内部的命令行副本,但例如,它不会清空存储在 Windows 进程环境块 (PEB) 中的命令行。此外,如果 cppcryptfs 已经在运行,那么从命令行调用 cppcryptfs(或 cppcryptfsctl)会导致它将命令行传递给正在运行的实例。它会尝试以一种相当安全的方式进行此操作,通过本地 Windows 命名管道与正在运行的实例进行通信。如果管道两端的程序都经过签名,那么它会验证管道另一端的程序也从经过签名的可执行文件运行,并且两个签名上的通用名称相同。然而,不清楚 Windows 会在 cppcryptfs 控制之外复制命令行多少次。因此,如果正在使用分页文件,通过命令行传递的密码有可能最终出现在分页文件中。 命名管道的名称会用启动 cppcryptfs 的用户的用户名和域名进行修饰。因此,cppcryptfs/cppcryptfsctl 只能与同一用户启动的 cppcryptfs 实例进行通信。 ### 使用方法 ``` 用法:cppcryptfs/cppcryptfsctl [选项] 挂载: -m, --mount=PATH 挂载位于 PATH 的文件系统 -d, --drive=D 挂载到盘符 D 或空目录 DIR -p, --password=PASS 使用密码 PASS -P, --saved-password 使用已保存的密码 -r, --readonly 以只读方式挂载 -c, --config=PATH 用于初始化/挂载的配置文件路径 -s, --reverse 初始化/挂载反向文件系统(初始化时意味着使用 SIV 模式) --deny-other-sessions [1|0] 启用/禁用拒绝其他会话访问 --deny-services [1|0] 启用/禁用拒绝服务访问 卸载: -u, --unmount=D 卸载盘符 D 或目录 DIR -u, --unmount=all 卸载所有盘符 -f, --force 如果文件系统正在使用则强制卸载 杂项: -t, --tray 隐藏在系统托盘中 -x, --exit 如果没有挂载的盘符则退出 -l, --list 列出可用的盘符和已挂载的文件系统 -ld:\p, --list=d:\p 列出明文和加密的文件名 -C, --csv 文件列表以逗号分隔 -D, --dir 文件列表先列出目录并在末尾加上反斜杠 \ -Mpath, --transform=path 转换完整路径(加密或解密) -i, --info=D 显示已挂载文件系统的信息 -v, --version 输出版本号(使用 --init -v 查看 cppcryptfsctl 的版本号) -h, --help 显示此帮助信息 初始化(仅适用于 cppcryptfsctl): -I, --init=PATH 初始化位于 PATH 的加密文件系统 -V, --volumename=NAME 为文件系统指定卷名 -T, --plaintext 使用明文文件名(默认是 AES256-EME 模式) --deterministicnames 禁用创建 gocryptfs.diriv 文件。 -S, --siv 使用 AES256-SIV 进行数据加密(默认是 GCM 模式) -L, --longnames [1|0] 启用/禁用长文件名。默认启用(1) -b, --streams [1|0] 启用/禁用流。默认启用(1) --longnamemax N 将文件名长度限制为最多 N 个字符 --scryptn N 设置用于密码的 Scrypt 哈希所需的内存 恢复/维护(仅适用于 cppcryptfsctl): --changepassword=PATH 更改用于保护主密钥的密码 --printmasterkey=PATH 以人类可读格式打印主密钥 --recover=PATH 提示输入主密钥和新密码以进行恢复 ``` 只有 cppcryptfsctl 可以通过命令行(--init)创建文件系统。要使用 cppcryptfs 创建文件系统,你必须使用图形用户界面(GUI)。 在创建/初始化文件系统时,如果以交互式方式运行,cppcryptfsctl 会提示输入密码和重复密码,且不会回显输入内容。如果其标准输入被重定向,那么它将从标准输入读取密码,而不会进行提示。 要获取 cppcryptfsctl 的版本,你必须指定初始化选项和 -v。例如,使用 cppcryptfsctl -I -v,否则它将尝试获取并打印正在运行的 cppcryptfs 实例的版本。 有些选项在初始化和挂载时都通用(--config 和 --reverse)。 注意:当使用选项的短格式时,在选项和其参数之间不应该使用等号。当使用选项的长格式时,等号是可选的。例如,以下这些用法都是可行的。 此外,如果你打算将卷挂载到一个盘符,那么在盘符选项的参数中不应该包含反斜杠字符(\\)。例如,如果你想挂载到盘符 “r:”,应使用 “-dr:”,而不是 “-dr:\\”。 ``` cppcryptfs -m c:\tmp\test -d k -p XYZ cppcryptfs --mount=c:\tmp\test --drive=k --password=XYZ cppcryptfs --mount c:\tmp\test --drive k --password XYZ ``` --list 选项有一个可选参数。如果未提供参数,那么它会列出盘符,并显示已挂载文件系统中加密文件系统根目录的路径。 list 命令也接受一个完整路径作为可选参数。该路径应该是包含盘符的文件或目录的未加密名称。如果参数是一个文件,那么 cppcryptfs 会在左侧打印未加密的文件路径,在右侧打印加密后的路径。如果参数是一个目录,那么 cppcryptfs 会在左侧打印文件的未加密名称,在右侧打印加密后的名称。 由于可选参数的处理方式,如果你使用 list 开关的短格式(-l),那么你必须在 -l 之后紧接着放置路径,中间不留空格。而如果你使用长格式(--list),那么你必须使用 “=” 符号。例如: ``` cppcryptfs -lk:\foo cppcryptfs --list=k:\foo ``` 在任何时候,cppcryptfs 只能有一个实例在运行。 当调用 cppcryptfs 时,它会检查是否有另一个实例正在运行。如果有,那么如果没有命令行选项,第二个 cppcryptfs 实例将直接退出。如果没有其他实例正在运行,那么它将处理命令行选项(如果有的话),并且会继续运行,除非指定了 --exit 选项且没有已挂载的驱动器。 因此,如果你计划在批处理文件中使用 cppcryptfs 或 cppcryptfsctl,你需要首先在后台启动一个实例。然后你应该在前台进行其他操作,这样它们会一直阻塞直到操作完成。 如果你在后台启动 “cppcryptfs --tray”,那么如果已经有一个正在运行的实例,该实例将被要求隐藏到系统托盘中。如果没有正在运行的实例,那么你将启动一个隐藏在系统托盘中并在后台运行的 cppcryptfs 实例。 以下是一个使用 cppcryptfs 的 Windows cmd 批处理文件示例。 ``` @rem ==================================================== @rem 在后台运行cppcryptfs,并给它一些时间来启动 @rem ==================================================== start cppcryptfs.exe --tray timeout /t 1 >nul @rem ==================================================== @rem 挂载到驱动器 U: @rem ==================================================== cppcryptfs.exe --mount=d:\TestCppCryptFS --drive=u --password=PASSWORD --tray --exit @rem ==================================================== @rem 挂载到驱动器 V: @rem ==================================================== cppcryptfs.exe --mount=d:\TestCppCryptFS2 --drive=v --password=PASSWORD --tray --exit @rem ==================================================== @rem 使用已挂载的驱动器运行任何命令 @rem ==================================================== copy C:\test.txt U:\test.txt copy C:\test.txt V:\test.txt ``` 以下是一个示例 Cygwin bash 脚本。请注意,在 bash 中,你需要在挂载路径中使用双反斜杠。 ``` #!/bin/bash # 在后台启动 cppcryptfs 并将其隐藏在系统托盘中 /cygdrive/c/bin/cppcryptfs -t & # 给它一些时间进行初始化 sleep 1 # 挂载一个文件系统并等待挂载操作完成 /cygdrive/c/bin/cppcryptfs --mount c:\\tmp\\test -d k -p XYZ # 执行备份操作 rsync ..... # 卸载所有驱动器并退出 /cygdrive/c/bin/cppcryptfs -u all -x ``` scryptn ------ `--scryptn` 用于控制解密存储在 `gocryptfs.conf` 中的密码所需的随机存取存储器(RAM)量。默认值为 16,这意味着解密大约需要 2^16 * 1024 = 64 兆字节的 RAM。 开放 Web 应用安全项目(OWASP.org)目前建议使用 17(128MB)这个值,以进一步减缓攻击者的破解速度。不过,由于这是 gocryptfs 的默认设置,所以 16 仍为默认值。 `scryptn` 支持的值范围是从 10(1MB)到 20(1GB)。gocryptfs 允许的值最高可达 28,但在开发者装有 16GB RAM 的 Windows 电脑上,任何超过 20 的值都会导致程序运行失败。 修改密码 ------ `cppcryptfsctl` 具备修改配置文件(通常为 `gocryptfs.conf` 或 `.gocryptfs.reverse.conf`)中保护主密钥的密码的功能。 此功能主要适用于那些想更换密码的用户。但如果密码已泄露,这并非一个好的解决办法。 修改密码仅仅是改变用于挂载文件系统的密码,并不会改变用于加密数据的加密密钥。这是因为用于加密数据的密钥是使用从密码派生而来的密钥进行加密,并存储在配置文件中的。所以,密码仅用于解密实际的加密密钥。 因此,如果有人获取了你的密码和旧配置文件的副本,那么即便你修改了密码,他们仍然能够解密已有数据以及你后续添加或修改的数据。 如果你认为自己的密码已泄露,并且觉得有人可能已经拿到了你的配置文件,那么最好的做法是使用新密码创建一个新的文件系统,将其挂载,同时挂载旧的文件系统,然后把数据从旧文件系统的未加密视图复制到新文件系统的未加密视图中。 如果你指定了 `--scryptn`,那么在修改密码的同时也可以更改 `scryptn` 的值。 找回丢失的密码 ----------- 只有在你打印并保存了未加密的主密钥的情况下,才有可能找回丢失的密码。 如果你运行以下命令: `cppcryptfsctl --printmasterkey PATH`(加密文件系统目录或配置文件的路径) 它会以人类可读的形式打印出未加密的主密钥。例如,你可以将其打印出来并保存在带锁的抽屉里。 如果你忘记了密码,可以运行: `cppcryptfsctl --recover PATH` 它会提示你输入主密钥,然后提示你输入新密码并确认新密码。 此操作会覆盖目标配置文件中的主密钥。在执行此操作之前,它会对配置文件进行备份,备份文件的名称是在原配置文件名称后加上 `.bak`。如果 `.bak` 文件已经存在,它会提示你删除现有的 `.bak` 文件或将其移走。 如果你指定了 `--scryptn`,那么在恢复文件系统的同时也可以更改 `scryptn` 的值。 恢复丢失或损坏的配置文件 ----------- 只有在你拥有未加密的主密钥的情况下,才有可能恢复丢失或损坏的配置文件。 `cppcryptfsctl --printmasterkey PATH`(加密文件系统目录或配置文件的路径) 这会以人类可读的形式打印出未加密的主密钥。如果你执行了此操作并保存了密钥,那么就可以利用它来恢复丢失或损坏的配置文件。 具体步骤如下(假设你在需要恢复之前已经打印并保存了主密钥): 1. 你需要创建一个新的文件系统,除路径外,使用与你尝试恢复的文件系统创建时相同的参数(例如,数据加密方法、文件名加密方法、长文件名支持等)。 使用什么密码并不重要。 2. 使用 `cppcryptfsctl --recover PATH` 将旧文件系统的主密钥放入新的配置文件中。 这会用你输入的主密钥替换该配置文件中的主密钥,并使用你选择的新密码对其进行加密。 3. 尝试挂载旧文件系统,指定新配置文件的路径,查看是否能够正常工作(确保你可以从中读取数据)。 4. 如果可以正常工作,你可以根据需要将恢复后的配置文件放置在加密文件系统的根目录下。 这里唯一需要注意的是,如果你有一个使用 2017 年 4 月/5 月之前发布的 gocryptfs 或 cppcryptfs 版本创建的文件系统,那么在使用 HKDF 和 Raw64 时可能会遇到问题。现在这些是默认设置,而且无法创建不包含它们的配置文件。 所以,如果你正在恢复一个旧的文件系统,但无法正常工作,那么可以尝试编辑你为恢复而创建的配置文件,删除包含 ``` "HKDF", "Raw64", ``` 然后看看这样是否可行。 文件名和路径长度限制 ------ 如果在创建文件系统时指定了“长文件名”(默认设置),或者使用了纯文本文件名,并且底层文件系统是比较新的(例如 NTFS/exFAT/FAT32),那么文件或目录名最长可达 255 个字符,完整路径大约可以长达 32000 个字符。 如果没有指定“长文件名”且未使用纯文本文件名,那么文件或目录名的最大长度为 160 个字符。但完整路径的限制仍然大约是 32000 个字符(假设底层文件系统是 NTFS/exFAT/FAT32)。 当一个文件名被加密时,它会从 UNICODE-16 转换为 UTF-8,根据语言的不同,这可能会导致字符数量增加。然后对其进行加密,这会使其填充最多 16 个字节。接着进行 base64 编码,这通常会使长度增加 33%。因此,加密后的文件名可能会比未加密的文件名长得多。 此外,加密文件系统所在目录的路径必须添加到加密文件名的路径前面。 较旧的文件系统,如 FAT16,会将总路径长度限制为 259 个字符。 因此,强烈建议尽可能使用像 NTFS、exFAT 或 FAT32 这样的现代文件系统。 许多 Windows 程序,包括 Windows 自带的文件资源管理器,对于超过旧的 259 字符限制的路径都会有问题,无论使用的是哪种底层文件系统。如果你使用加密文件名,那么如果你想移动加密文件系统的根目录,可能需要使用一个能够处理长文件路径的第三方文件管理器。复制文件然后删除旧文件是个好主意,而不是直接移动,以防你的文件管理器出现问题。 大小写敏感性 ----- Windows API 在文件名方面不区分大小写,但 Windows 文件系统(NTFS 和 FAT32)会保留文件名的大小写。 在 Windows 中,如果你创建一个名为“Foo.txt”的文件,然后尝试以“foo.txt”打开它,是可以打开的。 大多数(但不是所有)软件在打开文件时使用的大小写与创建文件时的大小写相同。 如果使用了加密文件名,cppcryptfs 最初在任何情况下都是区分大小写的。这也是 gocryptfs 的工作方式。 所以,如果使用了加密文件名,当创建一个名为“Foo.txt”的文件后,若尝试打开“foo.txt”,则会找不到该文件。 现在 cppcryptfs 有一个“不区分大小写”的设置,即使使用了加密文件名,它也能表现出不区分大小写的行为,但仅在正向(正常)模式下有效。 在反向模式下,如果使用了加密文件名,无论“不区分大小写”的设置如何,文件名总是区分大小写的。这是一项必要的预防措施,因为如果加密文件名的大小写发生了变化(例如,在备份文件系统时),那么如果随后以正向模式挂载文件系统的副本,文件名将无法正确解密。 如果使用纯文本文件名,那么无论“不区分大小写”的设置如何,在正向和反向模式下文件名总是不区分大小写的。 性能 ------ 以下是一些基准测试结果。测试是在运行于英特尔 i5-4200U 处理器且配备 Crucial M500 240GB 固态硬盘的 Windows 10 64 位系统下,使用 Cygwin 工具进行的。对于 cppcryptfs,使用 AES256-GCM 来加密文件数据和加密文件名,并且使用了长文件名。 在测试期间,Windows Defender 的实时扫描功能被禁用了,因为它会严重降低 Cygwin tar 的速度。在启用实时扫描的情况下,在原生 NTFS 上解压 linux-3.0.tar.gz 花费了 2 分 43.600 秒。 cppcryptfs 的性能与 Dokany 中不进行加密的镜像示例程序大致相同。该固态硬盘的顺序写入性能额定为 250 MB/秒。 ``` cppcryptfs 原生 NTFS Dokany 镜像 顺序写入 168 MB/秒 224 MB/秒 181 MB/秒 解压linux-3.0.tar.gz 1 分 36.412 秒 0 分 21.291 秒 1 分 34.125 秒 递归列出linux-3.0 1 分 1.979 秒 0 分 2.983 秒 1 分 11.618 秒 删除 linux-3.0 1 分 28.749 秒 0 分 10.144 秒 1 分 24.677 秒 ``` 上述基准测试是很久以前进行的。gocryptfs 的开发者最近发布了类似的基准测试,比较了 cppcryptfs 与 Windows 上其他加密文件系统的性能。 https://nuetzlich.net/gocryptfs/comparison/#performance-on-windows 部分测试结果比上述基准测试更快,但大多数更慢。 这可能是因为在测试期间 Windows Defender 实时保护处于开启状态。所有被测试的加密文件系统似乎都受到了同样的影响。 与 gocryptfs 的兼容性 ------ cppcryptfs 可以挂载由 gocryptfs v0.7 及更高版本创建的所有文件系统。同样,由 cppcryptfs 在“长文件名 = 关闭”的情况下创建的文件系统可以由 gocryptfs v0.7 及更高版本挂载。“长文件名 = 开启”的文件系统可以由 gocryptfs v0.9 及更高版本挂载。 gocryptfs [兼容性矩阵](https://github.com/rfjakob/gocryptfs/wiki/Compatibility) 提供了更多详细信息。cppcryptfs *要求*具备 DirIV、EMENames(如果使用加密文件名而非明文文件名)和 GCMIV128 功能标志。它*支持*长文件名,并且可以创建开启或关闭该标志的文件系统。 注意:现在 cppcryptfs 与 gocryptfs 保持版本号一致,以表明其与 gocryptfs 的兼容性。现在 cppcryptfs 的版本是 1.4,应该能够挂载由 gocryptfs 1.4 创建的所有文件系统。