Cryptomator logo


Free client-side AES encryption for your cloud files. Open source software: No backdoors, no registration.

Free Download iOS Beta Invite
Two Finder windows, one of them showing a Dropbox folder containing encrypted files, the second one showing the Cryptomator drive.
Windows logo

Cryptomator for Windows

(For 32 bit systems)


(For 64 bit systems)


Minimum: Windows Vista SP2

Finder logo

Cryptomator for Mac OS X



Minimum: OS X 10.8.3


Cryptomator for Linux

For Debian-based OS


See detailed system requirements

Java icon

Generic JAR-File

Available on GitHub

Requires JRE 8 + optional JCE unlimited strength policy files

Creating new vaults


You can create as many encrypted directories as you like. Two in Dropbox, one in OneDrive, one on your flash drive.

Unlocking vaults


Enter your password and start access your files. Wasn't that easy?

Using vaults


Every unlocked vault is accessible as a virtual hard drive in your operating system. Want to transfer files from one vault to another? No problem.


Cryptomator encrypts your files' contents and names using AES with up to 256 bit keylength. Scrypt hardens your key against bruteforcing.


Your applications can work with encrypted files without even noticing. Cryptomator will make your encrypted folder available as a virtual hard drive.


Cryptomator doesn't flood your computer with funny support files or even drivers. Also Cryptomator's internals are very simple. We believe, that complexity kills security.


Choose a password and continue working normally on your files. No configuration needed. No accounts required.


Cryptomator is secure. Ever read this sentence before? Well in this case you don't need to trust us. You can control us. Cryptomator is completely open source software.


Cryptomator doesn't need your cloud passwords. It works on your local machine and doesn't care about the accounts you use.


Dropbox, OneDrive, Google Drive, ...? Cryptomator works with every single cloud storage provider, as long as your files are sync'ed to your computer.


Cryptomator is based on Java technology and runs on all major desktop operating systems. Smartphone apps will follow.

Free and open source

Other than most cloud encryption tools, Cryptomator doesn't cost a penny. You don't even need to create an account! It is open source software licensed under the MIT X Consortium license, so you will never stand in front of locked doors in the future.

Key Derivation and Masterkey Decryption

Each vault has its own masterkey and HMAC key used for all cryptographic operations on its files and folders. The masterkey as well as the HMAC key are, depending on strength policy files, up to 256 bit long sequence of random data. They are generated using cryptographically secure PRNGs.

Both keys are encrypted using RFC 3394 key wrapping with a key encrypting key derived from the user's password using Scrypt (fixed parallelization parameter of 1).

kek := scrypt(password, scryptSalt, scryptCostParam, scryptBlockSize)
primaryMasterKey := createRandomBytes(32)
hmacMasterKey := createRandomBytes(32)
cipheredPrimaryMasterKey := aesKeyWrap(primaryMasterKey, kek)
cipheredHmacMasterKey := aesKeyWrap(hmacMasterKey, kek)

The wrapped keys and the parameters needed to derive the KEK are then stored as integers or Base64 strings in a JSON file named "masterkey.cryptomator", which is located in the root directory of the vault.

When unlocking a vault the KEK is used to unwrap (i.e. decrypt) the stored masterkeys.

  "version": 2, /* vault version for checking software compatibility */
  "scryptSalt": "wRo...c3M=",
  "scryptCostParam": 16384,
  "scryptBlockSize": 8,
  "keyLength": 256,
  "primaryMasterKey": "fKJgb...Roi3M=" /* cipheredPrimaryMasterKey */
  "hmacMasterKey": "uBaO8...16HWw=" /* cipheredHmacMasterKey */

File Header Encryption

Each file consists of a 104 byte header and the encrypted content padded by random data. The header carries the following information:

  • 128 bit random initialization vector.
  • 64 bit nonce. Both IV and nonce must be changed on each update of the file. Thus no partial updates are possible.
  • Three AES-CBC encrypted blocks using PKCS#5 padding. The plaintext contains:
    • One 64 bit long integer (big-endian), which stores the actual file size in bytes.
    • One 256 bit long random key. This key must also be changed on each update of the file.
  • A 256 bit MAC of the previous 64 bytes of this header.

Starting with the 105th byte follows the encrypted content using AES-CTR. Counter mode allows random access to large files like videos (that's why the second part of the initialization vector is a long integer).

iv := createRandomBytes(16)
nonce := createRandomBytes(8)
fileKey := createRandomBytes(32)
fileSize := length(plaintext)
encryptedHeaderData := encryptAesCbc(fileSize || fileKey, primaryMasterKey, PKCS5_PADDING)
headerMac := hmacSha256(iv || encryptedFileLength, hmacMasterKey)
header := iv || nonce || encryptedHeaderData || headerMac

File Content Encryption

Before encrypting, the plaintext is augmented by a random length random padding to obfuscate the actual file size. Then the plaintext is broken down into multiple chunks, each up to 32 KiB.

Each chunk is then encrypted separately using AES-CTR with the unique key and nonce taken from the file's header.

Afterwards a HMAC checksum is appended to the encrypted chunk. Additionally to the encrypted chunk the MAC is calculated over the header's IV as well as the chunk number to ensure chunks are in the correct order in the correct file.

randomPaddingLength := random() * min(max(fileSize * 10%, 4KiB), 16MiB)
arbitraryPadding := createRandomBytes(randomPaddingLength)
paddedPlaintext := plaintext || arbitraryPadding
plaintextChunks[] := split(paddedPlaintext, 32KiB)
encryptedChunks[] := encryptAesCtr(plaintextChunks[], fileKey, nonce)
foreach (encryptedChunk) {
  mac := hmacSha256(iv || numberOf(encryptedChunk) || encryptedChunk, hmacMasterKey)
  append(encryptedChunk, mac)
encryptedFileContent := join(encryptedChunk[])

In order to decrypt only the plaintext (without the padding), the fileSize contained in the file header must be decrypted first.

File Path Encryption and Directory Flattening

Before a encrypted file is moved to the d/ directory inside a vault, its file path gets encrypted too. This is done in two steps:

  • Encryption and hashing of the directory path (anything before the last path separator)
  • Encryption of the filename (anything after the last path separator)

Hashing is not an additional level of security, but shortens the encrypted path dramatically. The encrypted-and-hashed directory name doesn't tell you anything about the number of directory levels in the plaintext path, which helps obfuscating directory structures.

encryptedDirPath := sha256(encryptAesSiv(plaintextDirPath, primaryMasterKey, hmacMasterKey))
encryptedFilename := encryptAesSiv(plaintextFilename, primaryMasterKey, hmacMasterKey) || ".file"
encryptedPath := "d/" || substring(encryptedDirPath, 0, 2) || "/" || substring(encryptedDirPath, 2, 32) || "/" || encryptedFilename

Encrypted filenames are Base32 encoded (to support case-insensitive file systems).

Filename Length Limiting

The length of the encrypted name will be longer than the plaintext one. This is due to the 1.6x blow factor of Base32, the IV prefix and the file extension.

For long filenames exceeding 136 characters, a supporting metadata file located in the m/ directory of a vault is used to map the encrypted name to a shorter equivalent: Therefore a so-called groupPrefix is created from the first 8 chars of the original encrypted filename. A short filename consisting of the prefix followed by an UUID is used instead of the original encrypted filename. A metadata file contains a mapping dictionary between short and long encrypted filenames.

groupPrefix := substring(encryptedFilename, 0, 8)
uniqueShortName := groupPrefix || generateUuid() || ".lng.file"
correspondingMetadataFile := groupPrefix || ".meta"
metadataPath := "m/" || substring(correspondingMetadataFile, 0, 2) || "/" || correspondingMetadataFile(2, 8)

  "encryptedFilenames": {
    /* uuid: encryptedFilename */
    "5f6...98b": "WB7LC...HV32=="

Filenames may of course share the same metadata file. But as collisions of the prefix happen rarely, we reduce the risk of concurrent I/O attempts.