- 
                Notifications
    
You must be signed in to change notification settings  - Fork 41
 
Initial version key uvf documentation. #55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Draft
      
      
            chenkins
  wants to merge
  15
  commits into
  cryptomator:develop
  
    
      
        
          
  
    
      Choose a base branch
      
     
    
      
        
      
      
        
          
          
        
        
          
            
              
              
              
  
           
        
        
          
            
              
              
           
        
       
     
  
        
          
            
          
            
          
        
       
    
      
from
chenkins:feature/uvf
  
      
      
   
  
    
  
  
  
 
  
      
    base: develop
Could not load branches
            
              
  
    Branch not found: {{ refName }}
  
            
                
      Loading
              
            Could not load tags
            
            
              Nothing to show
            
              
  
            
                
      Loading
              
            Are you sure you want to change the base?
            Some commits from the old base branch may be removed from the timeline,
            and old review comments may become outdated.
          
          
  
     Draft
                    Changes from 5 commits
      Commits
    
    
            Show all changes
          
          
            15 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      dcece52
              
                Initial version key uvf documentation.
              
              
                chenkins 4530bc6
              
                Add diagrams and describe key rotation steps.
              
              
                chenkins 00f1747
              
                Update source/security/uvf.rst
              
              
                chenkins a533c8d
              
                Update source/security/uvf.rst
              
              
                chenkins 6d24faf
              
                Update source/security/uvf.rst
              
              
                chenkins c96a339
              
                Update source/security/uvf.rst
              
              
                chenkins 06d6b25
              
                Update source/security/uvf.rst
              
              
                chenkins 64fd5c7
              
                Update source/security/uvf.rst
              
              
                chenkins dbf6c1c
              
                Apply suggestions from code review
              
              
                chenkins c97196e
              
                Update source/security/architecture.rst
              
              
                chenkins e30010a
              
                Update source/security/architecture.rst
              
              
                chenkins ea058ff
              
                Update source/security/uvf.rst
              
              
                chenkins 0052574
              
                Fix broken sentence.
              
              
                chenkins cdfb79f
              
                Merge branch 'main' into feature/uvf
              
              
                overheadhunter 74d4585
              
                Merge branch 'develop' into feature/uvf
              
              
                tobihagemann File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
      
      Loading
      
  Sorry, something went wrong. Reload?
      Sorry, we cannot display this file.
      Sorry, this file is invalid so it cannot be displayed.
      
    
      
      Loading
      
  Sorry, something went wrong. Reload?
      Sorry, we cannot display this file.
      Sorry, this file is invalid so it cannot be displayed.
      
    
      
      Loading
      
  Sorry, something went wrong. Reload?
      Sorry, we cannot display this file.
      Sorry, this file is invalid so it cannot be displayed.
      
    
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -160,4 +160,53 @@ When unlocking a vault the KEK is used to unwrap (i.e. decrypt) the stored maste | |
| .. image:: ../img/security/[email protected] | ||
| :alt: Masterkey Decryption | ||
| :width: 440px | ||
| :align: center | ||
| :align: center | ||
| 
     | 
||
| 
     | 
||
| Key Rotation: Multiple Masterkey Generations using Cryptomator Hub with Universal Vault Format | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| 
     | 
||
| `Unified Vault Format (uvf) <https://github.com/encryption-alliance/unified-vault-format>`_ | ||
| defines a common vendor-independent standard based on `Vault Format 8 <https://docs.cryptomator.org/en/latest/misc/vault-format-history/>`_. | ||
| 
     | 
||
| The uvf metadata file ``vault.uvf`` replaces the ``vault.cryptomator`` file. | ||
| It is both stored in the vault as file and uploaded to hub. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| It can contain many key generations - only the latest generation is used for data encryption. | ||
| The older generations are used to read the older data encrypted with previous generation keys. | ||
| See :ref:`Key Rotation <security/uvf/key-rotation>` for more details. | ||
| 
     | 
||
| Cryptomator hub `1.3.0 <https://github.com/cryptomator/hub/releases/tag/1.3.0>`_) introduced user-specific vault access token JWE containing the vault masterkey for data encryption. | ||
| In the uvf setting, the uvf metadata (with the current and older (master)key generations. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| Instead, it will contain a Vault Member key, which allows to decrypt the ``vault.uvf`` metadata. | ||
| Specifically, a Vault Owner will have an access token under ``/access-token`` sub-resource of the form | ||
| 
     | 
||
| .. code-block:: json | ||
| 
     | 
||
| { | ||
| "key": "{memberkey}", | ||
| "recoveryKey": "{recovery key}", | ||
| } | ||
| 
     | 
||
| Non-owner Vault Members will not have the ``recoveryKey`` shared with them, the JWE will only contain the ``key`` element. | ||
| Vault members can decrypt their access token using their private user key. | ||
| See :ref:`User Key Pair <security/hub/keys/user-keys>`. | ||
| 
     | 
||
| Upon Vault creation, a new memberkey and an asymmetric recovery key pair are generated. The public recovery key and the ``vault.uvf`` JWE are uploaded to Cryptomator hub. | ||
| 
     | 
||
| .. image:: ../img/security/uvf_vault_creation.drawio.png | ||
| :alt: uvf Vault Creation | ||
| :width: 700px | ||
| :align: center | ||
| 
     | 
||
| See :ref:`Key Rotation <security/uvf/key-rotation>` for more details on key rotation and ``vault.uvf``. | ||
| 
     | 
||
| Vault sharing is the same as with access tokens introduced in Cryptomator hub `1.3.0 <https://github.com/cryptomator/hub/releases/tag/1.3.0>`_. | ||
| 
     | 
||
| Only the payload's ``key`` field contains the latest member key (instead of the masterkey) and the ``recoverKey`` (Vault Owners only). | ||
| 
     | 
||
| .. image:: ../img/security/uvf_vault_sharing.drawio.png | ||
| :alt: uvf Vault Sharing | ||
| :width: 550px | ||
| :align: center | ||
| 
     | 
||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,246 @@ | ||
| Vault Cryptography with Universal Vault Format | ||
| ============================================== | ||
| 
     | 
||
| In the mid-term, we want to support Key Rotation. | ||
| After Key Rotation, new data will be encrypted with new keys. | ||
| This will allow to retract access from vault members, | ||
| cryptographically ensuring they can never decrypt new data. | ||
| 
     | 
||
| `Unified Vault Format (uvf) <https://github.com/encryption-alliance/unified-vault-format>`_ | ||
| defines a common vendor-independent standard. It is close to `Vault Format 8 <https://docs.cryptomator.org/en/latest/misc/vault-format-history/>`_, | ||
| and will allow to support key rotation in the future. | ||
| Key rotation is not implemented yet, though. | ||
| Users will need to decide at vault creation time whether to use the new format. | ||
| 
     | 
||
| .. warning:: | ||
| New vaults will be created in the new uvf format. | ||
| There is no automatic migration plan for Vault Format 8 and below as data needs to be re-encrypted. | ||
| Users will need to create a new vault (in the new uvf format) and to upload the data again. | ||
| Clients and hub will be backwards-compatible. | ||
| 
     | 
||
| 
     | 
||
| .. _security/uvf/key-rotation: | ||
| 
     | 
||
| Key Rotation | ||
| ------------ | ||
| If a member (assume it's Bob) is removed from a vault, we need to replace the existing keys. | ||
| Theoretically, we could re-encrypt the whole data. However, this is time- and resource-consuming (I/O). And Bob may have made a backup copy of the data anyway. | ||
| Therefore, key rotation aims at enrypting new data - Bob must not be able to decrypt the new data with his old key, even if he still has access to the new ciphertext. | ||
| 
     | 
||
| The uvf metadata file replaces the masterkey file (or the user-specific JWE containing the masterkey introduced in Cryptomator hub `1.3.0 <https://github.com/cryptomator/hub/releases/tag/1.3.0>`_). | ||
| It can contain many key generations - only the latest generation is used for data encryption. | ||
| The older generations are used to read the older data encrypted with previous generation keys. | ||
| 
     | 
||
| Here's an example of the uvf metadata payload with different key generations in the ``seeds`` field and the ``latestFileKey`` pointing to the current key: | ||
| 
     | 
||
| .. code-block:: json | ||
| { | ||
| "fileFormat": "AES-256-GCM-32k", | ||
| "nameFormat": "AES-256-SIV", | ||
| "seeds": { | ||
| "HDm38i": "ypeBEsobvcr6wjGzmiPcTaeG7/gUfE5yuYB3ha/uSLs=", | ||
| "gBryKw": "PiPoFgA5WUoziU9lZOGxNIu9egCI1CxKy3PurtWcAJ0=", | ||
| "QBsJFo": "Ln0sA6lQeuJl7PW1NWiFpTOTogKdJBOUmXJloaJa78Y=" | ||
| }, | ||
| "latestFileKey": "QBsJFo", | ||
| "nameKey": "HDm38i", | ||
| "kdf": "HKDF-SHA512", | ||
| "kdfSalt": "NIlr89R7FhochyP4yuXZmDqCnQ0dBB3UZ2D+6oiIjr8=", | ||
| "org.example.customfield": 42 | ||
| } | ||
| When a new generation of keys is added to the metadata file, it must be re-encrypted as well - Bob, with his old key, must not be able to decrypt data encrypted later. | ||
| 
     | 
||
| Furthermore, for technical reasons (which will become clear below), the above payload needs to be shared with several ``recipients``. | ||
| More precisely, we use different Key Encapsulation methods to encrypt the payload for multiple recipients (a ``recipient`` being identified by their key ID ``kid``). | ||
| This is done in two steps: | ||
| 
     | 
||
| - The payload is encrypted only once with the same (shared) Content Encryption Key (CEK). The encrypted payload is stored in the ``ciphertext`` field of the encrypted metadata file. | ||
| - The CEK is then encrypted specifically for each recipient with their key and method, and the resulting encrypted key is stored in the ``encrypted_key`` field of the encrypted metadata file. | ||
| 
     | 
||
| Here's an example of an (encrypted) metadata file (JWE in JSON serialization, see `RFC 7516 <https://www.rfc-editor.org/rfc/rfc7516.html>`_) with two recipients (``org.cryptomator.hub.memberkey`` and ``org.cryptomator.hub.recoverykey``): | ||
| 
     | 
||
| .. code-block:: json | ||
| { | ||
| "protected": "eyJlbmMiOiJBMjU2R0NNIiwiamt1IjogImZvby9iYXIva2V5cy5qd2tzIn0", | ||
| "recipients": [ | ||
| { | ||
| "header": { | ||
| "alg": "A256KW", | ||
| "kid": "org.cryptomator.hub.memberkey" | ||
| }, | ||
| "encrypted_key": "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ" | ||
| }, | ||
| { | ||
| "header": { | ||
| "alg": "ECDH-ES+A256KW", | ||
| "kid": "org.cryptomator.hub.recoverykey.{keyhash}", | ||
| "epk": { | ||
| "kty": "EC", | ||
| "crv": "P-384", | ||
| "x": "z7S-cEoCC0J0H42jocPnEgMr8pr0wyIZgaMvzu4We8B_nQkF1zpYSGZRcD9wI3hA", | ||
| "y": "PlaiCkoGadNfVFi2ju-Dr19CewL-kjvXI8ibFOWaKizPh5gWjm9BFvx9Ox41Ka8x" | ||
| } | ||
| }, | ||
| "encrypted_key": "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ" | ||
| } | ||
| ], | ||
| "iv": "48V1_ALb6US04U3b", | ||
| "ciphertext": "5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6jiSdiwkIr3ajwQzaBtQD_A", | ||
| "tag": "XFBoMYUZodetZdvTiFvSkQ" | ||
| } | ||
| The `tag` field contains the `MAC <https://en.wikipedia.org/wiki/Message_authentication_code>`_ which allows to verify message authentication and integrigy checking, i.e. | ||
| verify that the message can only come from someone having access to the CEK and not being tampered with. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| Note that he recipient headers are authenticated as well. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| .. image:: ../img/security/uvf_key_rotation.drawio.png | ||
| :alt: uvf Key Rotation | ||
| :width: 700px | ||
| :align: center | ||
| 
     | 
||
| 
     | 
||
| 
     | 
||
| Vault Members | ||
| ------------- | ||
| All vault members share the same vault member key to access the vault metadata. | ||
| 
     | 
||
| The shared vault member key is a 256 bit AES Key. It is used for AES Key Wrap (``"alg": "A256KW"``) to enrypt/decrypt the metadata CEK. | ||
| The wrapped CEK is stored as ``encrypted_key`` for the ``org.cryptomator.hub.memberkey`` recipient. | ||
| 
     | 
||
| The vault member key in turn is stored for each user separately in the hub in the form of a JWE encrypted with user's public user key. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| Upon key rotation, the JWE for each user needs to be updated by using the public user key of each vault member. | ||
| 
     | 
||
| 
     | 
||
| 
     | 
||
| 
     | 
||
| Recovery Key | ||
| ------------ | ||
| Recovery keys are supposed to be long-living (print out human-readable and store offline) and should not be known by every vault member (only members with access to the private recovery key). | ||
| 
     | 
||
| In the key rotation setting, symmetric keys cannot be used for recovery key encryption. | ||
| Not only vault members with access to the recovery key, but any vault member must be able to carry out key rotation. | ||
| However, in symmetric cryptography, the same key is used for encryption and decryption. | ||
| Key rotation mast be carried out by a vault member as only vault members must know the metadata containing the CEK generations so far. | ||
| 
     | 
||
| Vault members may also be notified by an external event (e.g. person leaving an organisation), share the new metadata after key rotation with a restricted member set only. | ||
| 
     | 
||
| 
     | 
||
| Therefore, we use an ECDH key pair for each ``org.cryptomator.hub.recoverykey.{keyhash}`` recipient. Here's an example of such a key pair: | ||
| 
     | 
||
| .. code-block:: json | ||
| { | ||
| "kty": "EC", | ||
| "crv": "P-384", | ||
| "d": "cMyQpw7YIGjop48z1fh9fekbjwVvCThhC0Owumzv_hTHkljBAG8bnMUSbts55Vy6", | ||
| "x": "BzMNrgLiKSi9-gJ944_u7YgdXk5UfzGzSFlbDmuQS49LgVc8JpMAm1rAYhrLV9zi", | ||
| "y": "X9rATILnkQNx33tIjVwkgVZj1E7r69ZN1K4QHvhjO3tgoBGiIbvf2D14CaFPnvM9" | ||
| } | ||
| The private key is the part that can be printed out at vault creation time. | ||
| That's the ``d`` parameter above, which is a short bit of information that can be easily encoded in a human-readable way. | ||
| All the other parts form the public key. | ||
| During key rotation, only the public key needs to be known. | ||
| The public key is used to encrypt the new CEK, and the recipient in the metadata is updated with the new ``encrypted_key``. | ||
| The public key can be retrieved from the hub for key rotation with the vault's ID. | ||
| 
     | 
||
| The API returns a JWK Set, containing the public key for the vault recovery key ``org.cryptomator.hub.recoverykey.{keyhash}`` | ||
| (currently, the JWK set will only contain the vault recovery key, but could be used for further keys in the future): | ||
| 
     | 
||
| .. code-block:: json | ||
| { | ||
| "keys": [ | ||
| { | ||
| "kid": "org.cryptomator.hub.recoverykey.{keyhash}", | ||
| "kty": "EC", | ||
| "crv": "P-384", | ||
| "x": "BzMNrgLiKSi9-gJ944_u7YgdXk5UfzGzSFlbDmuQS49LgVc8JpMAm1rAYhrLV9zi", | ||
| "y": "X9rATILnkQNx33tIjVwkgVZj1E7r69ZN1K4QHvhjO3tgoBGiIbvf2D14CaFPnvM9", | ||
| "use": "enc", | ||
| "key_ops": ["deriveKey"] | ||
| } | ||
| ] | ||
| } | ||
| The following rules need to be respected upon encrypting the CEK for vault recovery key: | ||
| 
     | 
||
| .. csv-table:: Recovery Key JWE verification | ||
| :header: "verify", "protection against" | ||
| 
     | 
||
| 
     | 
||
| "relative URL", "implantation of untrusted URLs " | ||
| "JWE signature", "JWE manipulation" | ||
| "public key hash", "implantation of new public key at server side" | ||
| 
     | 
||
| Only URLs relative to the trusted hub must be followed, absolute URLs must not be followed in order for not retrieve the public recovery key from an untrusted source. | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| JWE signature verification makes sure the JWE comes from someone having access to the CEK, i.e. from a vault member (having access to CEK via memberkey or recoverykey). | ||
| A technical admin of the managed server cannot implant public keys at the server side unnoticed without being a vault member, as the keyhash is authenticated by the `tag` as well. | ||
| 
     | 
||
| 
     | 
||
| .. warning:: | ||
| Vault owners must be careful not to share vaults with technical hub admins. | ||
| Only a technical hub admin who is also a Vault Member, could sneak in a new recovery key pair (and thereby gain access to future data). | ||
| A technical hub admin of the managed server who is not Vault Member cannot perform this forgery. | ||
| This ensures Zero Knowledge for Managed Servers. | ||
| 
     | 
||
| .. warning:: | ||
| A malicious technical hub admin could still do some sort of "phishing" attack by "emptying" the vault, i.e. uploading a new memberkey (or also recoverykey). | ||
| Vault members not paying attention could upload files and the malicious technical hub admin would then have access to the new data. | ||
| This kind of attack would be noticed only if there is data in the storage for which the seeds have been removed from the metadata file or | ||
| if a vault owner cannot use their locally stored recovery key any more. | ||
| 
     | 
||
| 
     | 
||
| Look Ahead: Key Rotation | ||
| ------------------------ | ||
| Although actual rotation of keys is not implemented yet, we give a sketch of the future implementation. | ||
| To ensure Zero Knowledge, key rotation is not performed in the server, but on a vault member's machine in the client code. | ||
| Only the encrypted data is then uploaded to the hub. | ||
| Even a technical admin with access to the DB cannot gain access to the key material and, therefore, not decrypt the data even with access to the cloud storage. | ||
| 
     | 
||
| Key rotation will comprise the following steps: | ||
| 
     | 
||
| - get mutex for vault key rotation from hub (avoid concurrent key rotation for the same vault, lock at server) | ||
| - generate new memberkey | ||
| - encrypt new memberkey for all members with their public user key and update their vault access token | ||
| - generate new CEK | ||
| - generate new seed for data encryption and add to `seeds` of new metadata payload | ||
| - encrypt payload with CEK for `ciphertext` of new metadata JWE | ||
| - encrypt CEK with new memberkey and public recovery key into corresponding `encrypted_key` new metadata JWE | ||
                
      
                  chenkins marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| - upload new metadata JWE | ||
| - return mutex for vault key rotation to hub | ||
| 
     | 
||
| 
     | 
||
| File Header Encryption | ||
| ---------------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
| 
     | 
||
| File Content Encryption | ||
| ----------------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
| 
     | 
||
| Directory Ids | ||
| ------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
| 
     | 
||
| Filename Encryption | ||
| ------------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
| 
     | 
||
| Name Shortening | ||
| --------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
| 
     | 
||
| Backup Directory Ids | ||
| -------------------- | ||
| .. warning:: | ||
| TODO: Differences to Vault8? | ||
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.