Skip to content
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

Adjusted to Hub 1.3.x API #3041

Merged
merged 28 commits into from
Oct 20, 2023
Merged

Adjusted to Hub 1.3.x API #3041

merged 28 commits into from
Oct 20, 2023

Conversation

overheadhunter
Copy link
Member

@overheadhunter overheadhunter commented Jul 28, 2023

This PR contains adjustments required to ensure compatibility with upcoming changes to Hub (probably version 1.3.0):

  • adjusted device registration workflow
  • adjusted unlock workflow

At the same time, Cryptomator stays compatible with older Hub versions.

old Hub new Hub
old Desktop register device: Error 400
unlock: 200 (via legacy access tokens) or 403
new Desktop register (legacy): ✓
unlock (legacy): ✓

Unlock

Caution

The following information are outdated. See #3287 for details.

With this change, Cryptomator attempts to GET /api/vaults/{vaultId}/access-token, which will result in a error 404 on old Hub instances, which will trigger the legacy mechanism:

Otherwise, the encrypted vault key is returned from Hub. This can be decrypted using the user's private key, which in its encrypted form is part of the JSON returned by GET /api/devices/{deviceId}.

The full workflow is shown here:

Unlock Workflow

Device Registration

The device registration uses the same API endpoint as before (PUT /api/devices/{deviceId}), however the JSON has new fields, most notably the userPrivateKey:

private record CreateDeviceDto(@JsonProperty(required = true) String id, //
@JsonProperty(required = true) String name, //
@JsonProperty(required = true) String publicKey, //
@JsonProperty(required = true, defaultValue = "DESKTOP") String type, //
@JsonProperty(required = true) String userPrivateKey, //
@JsonProperty(required = true) String creationTime) {}

Due to userPrivateKey being a required field in the new Hub version, old Cryptomator clients will fail with Error 400 on an attempt to register to new Hub instances.

In order to encrypt the user's private key for the new device, we require a two-step operation:

  1. GET /api/users/me to access a PBES-encrypted JWE containing the user key. The Setup Code is required for decryption.
  2. Next, ECDH-ES-encrypt this user key as a JWE for this device's public key.
sequenceDiagram
    actor User
    participant Client
    participant Hub
    User ->>+ Client: Enter Setup Code 
    Client ->>+ Hub: GET /api/users/me
    Hub -->>- Client: encrypted user key
    activate Client
    Client ->> Client: derive key from Setup Code<br/>and decrypt User Key
    Client ->> Client: generate Device Key Pair<br/>and encrypt User Key for Device
    deactivate Client
    Client ->>+ Hub: PUT /api/devices/{deviceId}
    Hub -->>- Client: 201
    Client -->>- User: done
Loading

Future Compatibility Improvements

  • In b2a184b we already prepared Cryptomator to deal with unknown content in vault.cryptomator files created by future Hub versions.
  • Add some way to check Hub's API version. If newer than expected, ask the user to update Cryptomator. If older than expected show an corresponding message as well. Edit: Will become a separate PR, should we need to distinguish API Levels
  • Add some "API base URL" to vault.cryptomator

Test Checklist

  • check whether old Cryptomator fails to register on new Hub
  • check whether new Cryptomator can still register on old Hub
  • check whether old Cryptomator can still unlock via the legacy mechanism after updating Hub (assuming access was granted before the update)

Copy link
Member

@infeo infeo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add some screenshots of the new added/altered screens (/src/main/resoruces/fxml/hub_setup_device.fxml).

.thenApply(response -> {
if (response.statusCode() == 200) {
var dto = fromJson(response.body());
return Objects.requireNonNull(dto, "null or empty response body");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this sanity check is not bad, is it necessary? The documention of fasterxmls ObjectReader.read(String, Class) does not mention to return null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bad documentation then. I did encounter null here, when the response body is null or empty.

@overheadhunter overheadhunter marked this pull request as ready for review October 18, 2023 09:31
Copy link
Member

@infeo infeo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also tested old Hub against this Cryptomator branch and device registration, unlocking and unlocking archived showed the expected results

@infeo infeo added this to the 1.11.0 milestone Oct 19, 2023
Copy link
Member

@infeo infeo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class org.cryptomator.ui.keyloading.hub.HttpHelper seems to be unused. If that is true, remove it.

@overheadhunter overheadhunter merged commit 8dd8b93 into develop Oct 20, 2023
6 checks passed
@overheadhunter overheadhunter deleted the feature/new-hub-keyloading branch October 20, 2023 09:55
@overheadhunter overheadhunter added the type:enhancement Improvements on an existing feature label Oct 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:enhancement Improvements on an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants