CLI tool
cryfs/cryfs avatar
cryfs/cryfs

CryFS 2.0: a cloud-encryption filesystem rewritten in Rust, on an alpha branch

Cryptographic filesystem for the cloud

2,307 stars171 forksRustLGPL-3.0

At a glance

What is it?
CryFS encrypts files for Dropbox, iCloud and OneDrive in blocks so that file sizes, directory structure and metadata are hidden too, and version 2.0 is a from-scratch Rust rewrite. The default branch carries 2.0.0-alpha3 while the newest release tag is 1.0.3 from December 2025, the project states plainly that you will lose data, and there is no recovery tool.
Who is it for?
Use CryFS 1.0.3 if you need encrypted cloud storage today, because it is the newest release, it runs on Linux, macOS and Windows, and the documentation for it is on cryfs.org. Do not use the 2.0 alpha for anything you have not backed up elsewhere, since the project says in its own words that you WILL lose your data, names three specific ways that happens, and offers no recovery tool for a corrupted filesystem.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The default branch is the alpha, the newest tag is 1.0.3

The single most important fact about this repository is a mismatch between its default branch and its release history, and it is the kind that produces support tickets.

The README on the main branch is titled CryFS 2.0 (Alpha) and opens with a warning that 2.0-alpha is experimental software and that you WILL lose your data. The workspace manifest agrees:

toml
[workspace]
  members = ["crates/*"]
  resolver = "3"

  [workspace.package]
  edition = "2024"
  license = "LGPL-3.0-or-later"
  rust-version = "1.95"
  version = "2.0.0-alpha3"

And the three most recent releases are 1.0.3 tagged 2025-12-21, 1.0.2 tagged 2025-12-21, and 2.0.0-alpha3 tagged 2025-12-11.

So the branch you get by default is version 2.0.0-alpha3, while the newest thing anyone can download from a release page is 1.0.3, released about ten days later on the 1.0 line. Two patch releases of the stable version were cut on the same afternoon, 1.0.2 at 15:56 and 1.0.3 at 22:39, which is what a fix-and-repackage looks like, and then the main branch has had commits since with no further release. The last push was on 2026-09-28.

The mechanism behind the discrepancy is visible in the dependencies. The manifest includes git2version at version 0.5.0, a crate that computes a version string from git tags at build time. So the version in Cargo.toml is derived from the repository's own history rather than typed by hand, and building main gives you 2.0.0-alpha3 because that is what the tags on that branch say. It also means the two LICENSE lines and the readme key in that same block are the parts a human maintains.

The practical guidance is in the README's first paragraph: for stable CryFS, use CryFS 1.0, on the release/1.0 branch, with installation instructions at cryfs.org. Anyone evaluating this project has two different pieces of software in front of them and the README on the default branch describes the one that is not for production. That is an honest choice, and it is a documentation hazard.

Two unfinished items in the manifest reinforce the impression. There is a TODO to set categories, keywords, documentation and description, with a note to make sure the crates/*/Cargo.toml files link to it, and a second TODO asking whether they want to add badges. So the crates.io metadata for the individual crates is incomplete, which matters if you are deciding whether to depend on a crate rather than install a binary.

Blocks are the design, and that is what hides file sizes

CryFS encrypts files so they can be stored in cloud services like Dropbox, iCloud or OneDrive, and the design decision that separates it from per-file encryption tools is stated in one sentence in the README.

Unlike other encryption tools that encrypt files individually, CryFS encrypts your files in a way that also hides file sizes, directory structure, and metadata.

That single difference accounts for most of what the tool is and most of its costs. Encrypting each file independently leaks its size, because ciphertext length tracks plaintext length for a stream or AEAD cipher with no padding, and a folder of files leaking their sizes is a folder of files leaking its structure. It also leaks names, because a filename has to survive into the ciphertext somehow for the filesystem to find it, which means the name is either in the clear or in every block. And it leaks the modification time, because the filesystem needs it to order things.

Block-level encryption fixes all three by cutting the data into fixed-size blocks, which is what the --blocksize option is for, and encrypting each block independently with the file's structure held in a separate encrypted index. The size of a block is constant regardless of the size of the file, the directory structure lives in a structure file rather than in a directory listing, and the metadata is inside the encrypted index rather than in the ciphertext headers.

The cost is that the whole file has to be rewritten when its size changes, which is the classic block-ciphertext problem and the reason the tool is described as slower than alternatives for workloads that rewrite files constantly. Version 2.0 is slower still. The Known Issues section says 2.0-alpha is currently slower than 1.0 due to lack of optimizations, with performance improvements planned for future releases.

The dependency list shows how the pieces fit. aead at 0.5.2 is the abstract authenticated-encryption interface, with chacha20poly1305 and aes-gcm as the two concrete back ends, which matches the two supported ciphers exactly. lzzzz at 2.0.0 is LZ4, a fast compressor, so blocks are compressed before encryption. binary-layout and binrw are the binary serialisation libraries, so on-disk structures are described declaratively rather than parsed by hand. scrypt, from the rust-argon2 line of dependencies visible in the ecosystem, is the password derivation function, and the README confirms scrypt parameters are configurable when creating a new filesystem so you can trade memory for time deliberately rather than accepting a fixed cost.

Local state files do not sync between 1.0 and 2.0

The compatibility section of the README is unusually precise, and the one entry marked partially compatible is the most interesting line in it.

File systems are described as fully forward and backward compatible between CryFS 1.0 and 2.0. The compatible list covers file systems created with the XChaCha20 cipher, which is the default in both versions, file systems created with AES-256-GCM, and integrity checks using block versioning. Then there is the caveat.

Local state files. The filesystem ID verification, described in the README as protection against filesystem replacement attacks, uses separate local state files in 1.0 versus 2.0. Both versions perform this check, but they do not sync with each other.

That is a security-relevant detail and it deserves unpacking. A filesystem replacement attack works like this: an attacker who can write to your storage directory substitutes a different encrypted filesystem, you mount it, you enter your password, and your files are replaced by an attacker-controlled set. The defence is to record an identifier for the filesystem somewhere local, outside the storage directory, and refuse to mount if the identifier does not match. It is a good defence, and it depends entirely on that local record.

If the local record is per-version and the two versions do not sync, then the guarantee is only as good as the version you mounted with. Someone who mounts the same storage directory first with 1.0 and then with 2.0 gets two independent records, and the replacement check is not being cross-validated. In practice this matters if you have a mixed environment, for example a Linux machine running 1.0 and a test machine running the 2.0 alpha against the same synced directory. It is not a vulnerability, and it is not a claim the project makes otherwise, but it is the kind of thing an evaluator should know before running both.

The genuinely incompatible list is short and honest. File systems created with other ciphers, Twofish and Serpent named as examples, are not accessible in CryFS 2.0. And the reason given is not a security judgement: there are no plans to add all ciphers from CryFS 1.0 to the Rust version because many are outdated and do not have an implementation that can be called from Rust easily. The rewrite constrained the cipher set, and the constraint came from the language choice rather than from cryptography. Anyone whose 1.0 filesystem uses one of the dropped ciphers has no upgrade path at all.

No recovery tool, and three named ways to lose data

The Known Issues section is the most valuable part of this README, and the reason is that it names specific failure modes rather than gesturing at stability.

It says that as alpha software you should expect bugs and potential data loss, and then lists three. Filesystem corruption if the process is interrupted during writes. Data loss if the disk runs out of space during write operations. And corruption if the filesystem is accessed from multiple devices simultaneously without proper synchronization.

Each of those is a mechanism, not a mood. The first follows from block-level encryption: an interrupted write leaves a partially written block and an index that does not match the blocks on disk, and without a journal or a transaction log there is nothing to roll back to. The second is the same failure arriving from a different direction, and it is worth dwelling on because it is the one people do not expect. Running out of space is not normally a data-loss event. Here it is, because a block allocation that fails partway through a write is indistinguishable from an interrupted one.

The third is the one that interacts with the tool's purpose. CryFS is designed to live in a cloud storage directory, and cloud storage directories are synchronised. Two devices syncing the same encrypted block store without coordination will interleave block writes, and the index that describes the blocks is exactly as vulnerable as the blocks themselves. The README's warning is not that the encryption is weak but that the consistency model is single-writer.

Then the Recovery section, which is one sentence and is the reason to read all of the above carefully: there is currently no filesystem recovery tool for corrupted CryFS filesystems, and you should back up your data regularly.

Combined with the alpha warning that you WILL lose your data, this is an unusually complete statement of risk. Most projects give you one of the two halves, the loud warning or the specific mechanism. CryFS gives both, and then declines to offer a repair path. For a tool whose job is to hold files that also exist on someone else's servers, that is a defensible position only if you understand it: the encrypted directory is not the backup, and nothing in the design makes it one.

The same reasoning applies to the cloud premise in the other direction. CryFS makes Dropbox, iCloud or OneDrive unable to read your files, which is the point. It also means those services cannot recover your files for you, because they never had the key.

No password rotation, and two ciphers because Rust could not call the others

Two operational constraints in the Security Notes section will affect how you plan to use this, and neither is a bug.

The first is password changes. The README says that if your password is compromised, creating a new filesystem and migrating your data is strongly recommended, as CryFS does not support secure password rotation.

The reasoning is visible once you know the design. Every block is encrypted with a key derived from your password, so changing the password means re-encrypting every block. A scheme that supported rotation would have to re-wrap a content key rather than derive directly from the password, and CryFS does not do that. The consequence is concrete: a compromised password means a new encrypted directory and a full migration, on a tool whose blocks all have to be rewritten anyway. For a large library in a cloud directory, that is a long operation with the old password still in use until it completes.

The second is cipher selection, and the list is short. CryFS 2.0 supports XChaCha20-Poly1305, which is the default and the recommendation, and AES-256-GCM. XChaCha is recommended for new file systems due to its strong security properties and performance characteristics.

Two ciphers for a tool that shipped more is worth understanding rather than accepting, and the compatibility section explains it: the dropped ciphers, Twofish and Serpent named as examples, were dropped because there is no easily callable Rust implementation, not because they were judged insecure. The rewrite constrained the choice, and for authenticated encryption the two survivors are the sensible ones. XChaCha20 has a larger nonce, which matters when nonces have to be generated without coordination, and it avoids AES hardware paths whose side-channel behaviour differs across platforms. Neither argument is made in the README, which only says performance characteristics, so this is inference from the design rather than a claim the project makes.

The third security item is scrypt. CryFS 2.0 lets you configure scrypt parameters when creating a new filesystem so you can adjust the time and memory tradeoffs for password derivation based on your needs, with the stated trade that larger parameters are more secure but mean the filesyst, and the sentence is cut off in the documentation at that point. Being able to set the cost at creation time rather than accepting a compiled-in constant is the right design, and the fact that the parameters are not changeable afterwards is implied by the same key-derivation structure that rules out password rotation.

Building on Linux, and what a pure-Rust FUSE binding costs elsewhere

The build instructions are short, complete for Linux, and the dependency list explains why the other two platforms are harder.

On Ubuntu or Debian the build dependencies are:

bash
sudo apt install build-essential pkg-config libssl-dev

On Fedora it is fuse3-devel, and on Arch it is fuse3. Then the build itself is four commands:

bash
git clone https://github.com/cryfs/cryfs
cd cryfs
cargo build --release
sudo cp target/release/cryfs /usr/local/bin/

The libssl-dev dependency on Debian-family systems is a leftover from the C++ implementation, or a transitive requirement of something in the tree, and it is worth noting because the 1.0 source is still present in the repository under an old-cpp/ directory. Keeping the previous C++ implementation alongside the Rust rewrite is unusual and genuinely useful: it means the compatibility claims in the README can be checked against real code rather than taken on trust, and it means the last version that supported Twofish and Serpent is available to read.

The FUSE layer is what makes the platform table short. The dependencies include fuser at 0.17, a pure-Rust FUSE binding, and fuse_mt at 0.6.3 for multi-threaded request handling. Because the FUSE interface is a Linux-shaped kernel interface, Linux is the platform where this is straightforward. macOS needs a FUSE shim, and the README says 2.0 is untested on macOS and may work if you have macFUSE installed, with no guarantees, while giving umount as the unmount command rather than fusermount. Windows has no equivalent kernel interface at all, and the platform table states that Windows support is not yet available in CryFS 2.0.

So the platform support is not three rows of a compatibility matrix, it is one platform where the design fits, one where a shim is required, and one where the whole approach has to be reimplemented. That is a better reason to read the table than the word untested is.

Two runtime details are worth knowing. The unmount command on Linux is fusermount -u on the mountpoint, and the tool supports automatic unmount after a period of inactivity through --unmount-idle, which in 2.0 requires a unit suffix. The 1.0 to 2.0 command line changes table is a list of four specific breaks: --unmount-idle 10 becomes --unmount-idle 10m, --blocksize 16384 becomes --blocksize 16KiB, --logfile becomes --log with a file: prefix, and the double-dash before -o is removed so that cryfs vaultdir mountdir -o allow_other replaces the old form. The set of FUSE options accepted after -o is also narrowed to those known to work well with CryFS, with the full list behind cryfs --help. Every one of these is a reasonable change and every one of them is a script that stops working.

Editorial conclusion

Use CryFS 1.0.3 if you need encrypted cloud storage today, because it is the newest release, it runs on Linux, macOS and Windows, and the documentation for it is on cryfs.org. Do not use the 2.0 alpha for anything you have not backed up elsewhere, since the project says in its own words that you WILL lose your data, names three specific ways that happens, and offers no recovery tool for a corrupted filesystem. Do not plan a password change onto existing data either, because CryFS does not support secure password rotation and the documented remedy is a new filesystem and a migration. Verify five things. Check which branch you are reading, because the main branch is 2.0.0-alpha3 while the release/1.0 branch is the stable line and the two have different command line syntax. Confirm your filesystem was created with XChaCha20 or AES-256-GCM, since filesystems using Twofish or Serpent cannot be opened by 2.0 at all. If you use both versions against the same directory, know that the filesystem ID check uses separate local state files that do not sync between them. Confirm your platform, since 2.0 lists Linux as working, macOS as untested and Windows as unsupported, and the FUSE layer is a pure-Rust binding. And test your restore path before you need it, because there is no filesystem recovery tool. The deciding fact is that CryFS 2.0 trades maturity for memory safety and has not yet repaid that trade.

Frequently asked questions

What is the difference between CryFS 1.0 and CryFS 2.0?

CryFS 2.0 is a complete rewrite from scratch in Rust, bringing improved memory safety. File systems are forward and backward compatible when created with the XChaCha20 or AES-256-GCM ciphers, and block versioning integrity checks are compatible, but filesystems using other ciphers such as Twofish or Serpent cannot be opened by 2.0.

Is CryFS 2.0 safe to use for important data?

No, on the project's own account. The README says 2.0-alpha is experimental software and that you WILL lose your data, listing filesystem corruption if the process is interrupted during writes, data loss if the disk runs out of space during writes, and corruption from simultaneous multi-device access. There is currently no filesystem recovery tool for corrupted CryFS filesystems.

How do I build CryFS 2.0 on Linux?

Install the build dependencies, which are build-essential, pkg-config and libssl-dev on Ubuntu and Debian, fuse3-devel on Fedora or fuse3 on Arch, then run git clone, cd cryfs, cargo build --release and copy target/release/cryfs into /usr/local/bin/. The toolchain requirements are edition 2024 and rust-version 1.95.

Which platforms does CryFS 2.0 support?

Linux is listed as working. macOS is untested and may work if macFUSE is installed, with no guarantees. Windows is not yet supported in CryFS 2.0. The FUSE layer is a pure-Rust binding built on fuser, which is why Linux is the straightforward case and the other two are not.

Can I change my CryFS password?

Not in place. The README states that if your password is compromised, creating a new filesystem and migrating your data is strongly recommended, because CryFS does not support secure password rotation. The same derivation structure is why scrypt cost parameters are set at filesystem creation and not adjustable afterwards.

What command line options changed between CryFS 1.0 and 2.0?

Four documented breaks: --unmount-idle 10 becomes --unmount-idle 10m, --blocksize 16384 becomes --blocksize 16KiB, --logfile /path becomes --log file:/path, and the double-dash before FUSE options is removed so it is cryfs vaultdir mountdir -o allow_other. The set of accepted -o options is also narrowed to those known to work well with CryFS.

Official sources

  1. cryfs/cryfs on GitHub
  2. License: LGPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cryfs-cryfs.svg)](https://hysenlabs.com/projects/cryfs-cryfs)