We explain how CryFS works and why it is secure.
The description can be a bit technical in some points. If you're rather interested in using CryFS, take a look at the CryFS Tutorial.
The goal of CryFS is not only to keep file contents, but also file sizes, metadata and directory structure confidential.
To hide file sizes, CryFS splits the content of a file into same-size blocks and encrypts these blocks individually. A tree structure is used to remember how the blocks belong together to form a file. This tree structure has very little overhead and itself is also stored using encrypted same-size blocks. To hide file metadata and directory structure, they are also represented using encrypted same-size blocks.
Each encrypted block is stored as a file in the base directory, using a random ID as filename. The base directory can then be set up to be synchronized with a cloud provider like Dropbox. An attacker with access to the base directory can only see a set of same-size ciphertext blocks and can't see contents, file sizes, metadata or directory structure of your data.
The blocks are encrypted using a block cipher chosen by the user. A random encryption key is generated when the filesystem is created. This key is stored in a configuration file, which is then encrypted using the password chosen by the user. Since it is encrypted, it can be stored together with the ciphertext blocks in the cloud, which is the default. If you want to use an insecure (e.g. empty) password or don't trust the scrypt algorithm used for encrypting the configuration file, you can also keep the configuration file locally.
The base directory also contains a configuration file with the information CryFS needs to decrypt it. This configuration file is encrypted and integrity-checked using the password chosen by the user, so an attacker cannot read or modify it.
The information stored in the configuration file includes the following.
The configuration file is encrypted twice, once with aes-256-gcm and once with the cipher chosen by the user. This way, if the user doesn't trust aes-256-gcm for some reason, they can choose another cipher and still be secure. The keys for both encryption layers are generated from the user-chosen password using scrypt.
In detail, CryFS generates two keys outer_key and inner_key using scrypt and the user password. It encrypts the configuration file using the user cipher and inner_key. To the ciphertext, it prepends the name of the user cipher (so it knows how to decrypt it later) and encrypts the result using aes-256-gcm and outer_key. This way, an attacker cannot see or manipulate which cipher is used. As a last step, the scrypt configuration parameters are prepended, so CryFS knows how to configure scrypt when decrypting the filesystem. When decrypting the configuration file, CryFS first reads the scrypt parameters and regenerates both keys from the user password. Then, it decrypts the first layer and reads the cipher chosen by the user. Using this cipher, it decrypts the second layer and reads the configuration values.
The integrity of the configuration file depends on aes-256-gcm. This cipher is a standard cipher and believed to be very secure. If, however, you don't trust the integrity of aes-256-gcm and want to use another cipher instead, we recommend adding the --cipher xxx parameter each time you mount the filesystem. This way, CryFS can check that the cipher used by the filesystem is the one you actually specified and you don't have to rely on the aes-256-gcm integrity verification step.
Alternatively, you can store the configuration file outside of the base directory and not upload it into the cloud. This is possible using the --config parameter when calling CryFS.
The security of CryFS has been proven in a master's thesis using a game-based security approach. The thesis also contains a detailed description of the inner workings of CryFS.
The current version meets all security goals regarding confidentiality of file contents, size, metadata and directory structure. The integrity goals mentioned in the thesis are not fully implemented yet. The current version protects the encrypted blocks from being modified by an attacker, since it uses an authenticated encryption scheme like aes-256-gcm. However, it doesn't prevent an attacker yet from rolling back the filesystem by replacing blocks with an earlier valid version of the same block. This issue will be addressed in future versions.