Security Architecture ===================== .. _security/architecture/virtual-filesystem: Virtual Filesystem ------------------ Cryptomator provides a virtual drive. Add, edit, remove files as you're used to with just any disk drive. Files are transparently en- and decrypted. There are no unencrypted copies on your hard disk drive. With every access on your files inside the virtual drive, Cryptomator will en- and decrypt these files on-the-fly. Currently WinFsp (on Windows) and macFUSE (on macOS) and FUSE (Linux) are our frontends of choice. If they're not available on your system, Cryptomator will fall back on WebDAV, as it is supported on every major operating system. WebDAV is an HTTP-based protocol and Cryptomator acts as a WebDAV server accepting so-called loopback connections on your local machine only. Whenever your file manager accesses files through this virtual drive, Cryptomator will process this request via the following layers. .. _security/architecture/vault-configuration: Vault Configuration ------------------- Every vault must have a vault configuration file named ``vault.cryptomator`` in the root directory of the vault. It is a JWT containing basic information about the vault and specification what key to use. The JWT is signed using the 512 bit raw masterkey. This is an example of an encoded vault configuration file: .. code-block:: console eyJraWQiOiJtYXN0ZXJrZXlmaWxlOm1hc3RlcmtleS5jcnlwdG9tYXRvciIsInR5cCI6IkpXVCIsImFsZyI6IkhTMjU2In0.eyJmb3JtYXQiOjgsInNob3J0ZW5pbmdUaHJlc2hvbGQiOjIyMCwianRpIjoiY2U5NzZmN2EtN2I5Mi00Y2MwLWI0YzEtYzc0YTZhYTE3Y2Y1IiwiY2lwaGVyQ29tYm8iOiJTSVZfQ1RSTUFDIn0.IJlu4dHb3fqB2fAk9lf8G8zyEXc7OLB-5m9aNxOEXIQ The decoded header: .. code-block:: js { "kid": "masterkeyfile:masterkey.cryptomator", /* URI of where to get the key */ "typ": "JWT", "alg": "HS256" /* current implementations also support HS384 and HS512 */ } The decoded payload: .. code-block:: js { "format": 8, /* vault format for checking software compatibility */ "shorteningThreshold": 220, /* how many characters in ciphertext filenames before shortening */ "jti": "ce976f7a-7b92-4cc0-b4c1-c74a6aa17cf5", /* random UUID to uniquely identify the vault */ "cipherCombo": "SIV_GCM" /* mode of operation for the block cipher. Other possible values are "SIV_CTRMAC" */ } When opening a vault, the following steps have to be followed: #. Decode ``vault.cryptomator`` without verification. #. Read ``kid`` header and, depending on its value, retrieve the masterkey from the specified location. #. Verify the JWT signature using the masterkey. #. Make sure ``format`` and ``cipherCombo`` are supported. .. _security/architecture/masterkey: Masterkey --------- Each vault has its own 256 bit encryption as well as MAC masterkey used for encryption of file specific keys and file authentication, respectively. All key material is generated by a :abbr:`CSPRNG (Cryptographically secure pseudorandom number generator)`. * In Java (Desktop, Android App), we use `SecureRandom `_ with SHA1PRNG, seeded with 440 bits from ``SecureRandom.getInstanceStrong()``. * In Javascript (Cryptomator Hub), we rely on `crypto.subtle.generateKey() `_. * In Swift (iOS App), we use `SecRandomCopyBytes `_ with ``kSecRandomDefault``. These keys are themselves protected and can be retrieved using, either of the following methods, depending on the use case: .. _security/architecture/masterkey-hub: Using Cryptomator Hub ^^^^^^^^^^^^^^^^^^^^^ When using :ref:`Cryptomator Hub `, the encrypted raw masterkey can be retrieved from a the server component. .. note:: If a vault is managed by Cryptomator Hub, the ``vault.cryptomator``'s ``kid`` field will point to the resource URI of said vault on the corresponding Hub instance, prefixed by ``hub+``. Example: ``"kid": "hub+https://hub.example.com/api/vaults/bb36d67c"`` Every Cryptomator Hub user who is authorized to access this vault will retrieve an individual ciphertext from the vault's ``/access-token`` sub-resource. This ciphertext is formatted as a `JWE `_ and can be decrypted using `ECDH-ES `_ and the :ref:`user's static private key `. The JWE's decoded header looks something like this: .. code-block:: js { "alg": "ECDH-ES", "enc": "A256GCM", "epk": { "crv": "P-384", "kty": "EC", "x": "p1J...g", "y": "8Il...H" } "apu": "", "apv": "" } The JWE's decrypted payload holds a single value, which can then be consumed by Cryptomator to unlock the vault: .. code-block:: js { "key": "H7u...o==" /* 512 bit raw masterkey */ } .. _security/architecture/masterkey-file: Masterkey File ^^^^^^^^^^^^^^ Alternatively, for normal password-protected vaults, Cryptomator will derive a :abbr:`KEK (Key-encryption key)` via `scrypt `_, encrypt the masterkeys using `AES Key Wrap (RFC 3394) `_, and store the results together with the key derivation parameters in a JSON file: .. code-block:: console encryptionMasterKey := createRandomBytes(32) macMasterKey := createRandomBytes(32) kek := scrypt(password, scryptSalt, scryptCostParam, scryptBlockSize) wrappedEncryptionMasterKey := aesKeyWrap(encryptionMasterKey, kek) wrappedMacMasterKey := aesKeyWrap(macMasterKey, kek) .. image:: ../img/security/key-derivation@2x.png :alt: KEK Derivation :width: 336px :align: center The wrapped keys and the parameters needed to derive the KEK are then stored as integers or Base64-encoded strings in a JSON file named ``masterkey.cryptomator``, which is located in the root directory of the vault. .. code-block:: js { "version": 999, /* deprecated, vault format is now specified in the vault configuration */ "scryptSalt": "QGk...jY=", "scryptCostParam": 32768, "scryptBlockSize": 8, "primaryMasterKey": "QDi...Q==", /* wrappedEncryptionMasterKey */ "hmacMasterKey": "L83...Q==", /* wrappedMacMasterKey */ "versionMac": "3/U...9Q=" /* HMAC-256 of vault version to prevent undetected downgrade attacks */ } When unlocking a vault the KEK is used to unwrap (i.e. decrypt) the stored masterkeys. .. image:: ../img/security/masterkey-decryption@2x.png :alt: Masterkey Decryption :width: 440px :align: center