Skip to content

Commit 2bb87df

Browse files
Merge branch 'release/1.2.0' into develop
# Conflicts: # main/ant-kit/pom.xml # main/commons-test/pom.xml # main/commons/pom.xml # main/filesystem-api/pom.xml # main/filesystem-charsets/pom.xml # main/filesystem-crypto-integration-tests/pom.xml # main/filesystem-crypto/pom.xml # main/filesystem-inmemory/pom.xml # main/filesystem-invariants-tests/pom.xml # main/filesystem-nameshortening/pom.xml # main/filesystem-nio/pom.xml # main/filesystem-stats/pom.xml # main/frontend-api/pom.xml # main/frontend-webdav/pom.xml # main/jacoco-report/pom.xml # main/keychain/pom.xml # main/pom.xml # main/uber-jar/pom.xml # main/ui/pom.xml
2 parents 2fa04d7 + 84ac6d8 commit 2bb87df

File tree

24 files changed

+483
-50
lines changed

24 files changed

+483
-50
lines changed

main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/CryptorImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void readKeysFromMasterkeyFile(byte[] masterkeyFileContents, CharSequence
109109
assert keyFile != null;
110110

111111
// check version
112-
if (CURRENT_VAULT_VERSION != keyFile.getVersion()) {
112+
if (!CURRENT_VAULT_VERSION.equals(keyFile.getVersion())) {
113113
throw new UnsupportedVaultFormatException(keyFile.getVersion(), CURRENT_VAULT_VERSION);
114114
}
115115

main/filesystem-crypto/src/main/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImpl.java

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ public FileContentDecryptorImpl(SecretKey headerKey, SecretKey macKey, ByteBuffe
5454
this.header = FileHeader.decrypt(headerKey, hmacSha256, header);
5555
this.authenticate = authenticate;
5656
this.chunkNumber = firstCiphertextByte / CHUNK_SIZE; // floor() by int-truncation
57+
58+
// vault version 5 and onwards should have filesize: -1
59+
if (this.header.getPayload().getFilesize() != -1l) {
60+
throw new UncheckedIOException(new IOException("Attempted to decrypt file with invalid header (probably from previous vault version)"));
61+
}
5762
}
5863

5964
@Override

main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/FileContentDecryptorImplTest.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public void testDecryption() throws InterruptedException {
4545
final byte[] keyBytes = new byte[32];
4646
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
4747
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
48-
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJA==");
48+
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJg==");
4949
final byte[] content = Base64.decode("AAAAAAAAAAAAAAAAAAAAALTwrBTNYP7m3yTGKlhka9WPvX1Lpn5EYfVxlyX1ISgRXtdRnivM7r6F3Og=");
5050

5151
try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, true)) {
@@ -68,7 +68,7 @@ public void testManipulatedHeaderDecryption() throws InterruptedException {
6868
final byte[] keyBytes = new byte[32];
6969
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
7070
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
71-
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJa==");
71+
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJG==");
7272

7373
try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, true)) {
7474

@@ -80,7 +80,7 @@ public void testManipulatedContentDecryption() throws InterruptedException {
8080
final byte[] keyBytes = new byte[32];
8181
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
8282
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
83-
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJA==");
83+
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJg==");
8484
final byte[] content = Base64.decode("aAAAAAAAAAAAAAAAAAAAALTwrBTNYP7m3yTGKlhka9WPvX1Lpn5EYfVxlyX1ISgRXtdRnivM7r6F3Og=");
8585

8686
try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, true)) {
@@ -101,7 +101,7 @@ public void testManipulatedDecryptionWithSuppressedAuthentication() throws Inter
101101
final byte[] keyBytes = new byte[32];
102102
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
103103
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
104-
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJA==");
104+
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJg==");
105105
final byte[] content = Base64.decode("AAAAAAAAAAAAAAAAAAAAALTwrBTNYP7m3yTGKlhka9WPvX1Lpn5EYfVxlyX1ISgRXtdRnivM7r6F3OG=");
106106

107107
try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, false)) {
@@ -124,7 +124,7 @@ public void testPassthroughException() throws InterruptedException {
124124
final byte[] keyBytes = new byte[32];
125125
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
126126
final SecretKey macKey = new SecretKeySpec(keyBytes, "AES");
127-
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJA==");
127+
final byte[] header = Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJg==");
128128

129129
try (FileContentDecryptor decryptor = new FileContentDecryptorImpl(headerKey, macKey, ByteBuffer.wrap(header), 0, true)) {
130130
decryptor.cancelWithException(new IOException("can not do"));

main/filesystem-crypto/src/test/java/org/cryptomator/crypto/engine/impl/FileHeaderTest.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,26 @@ public void testEncryption() {
5353

5454
@Test
5555
public void testDecryption() {
56+
final byte[] keyBytes = new byte[32];
57+
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
58+
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
59+
final ByteBuffer headerBuf = ByteBuffer.wrap(Base64.decode("AAAAAAAAAAAAAAAAAAAAACNqP4ddv3Z2rUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga24VjC86+zlHN49BfMdzvHF3f9EE0LSnRLSsu6ps3IRcJg=="));
60+
final FileHeader header = FileHeader.decrypt(headerKey, new ThreadLocalMac(macKey, "HmacSHA256"), headerBuf);
61+
62+
Assert.assertEquals(-1l, header.getPayload().getFilesize());
63+
Assert.assertArrayEquals(new byte[16], header.getIv());
64+
Assert.assertArrayEquals(new byte[32], header.getPayload().getContentKey().getEncoded());
65+
}
66+
67+
@Test
68+
public void testDecryptionOfOldHeader() {
5669
final byte[] keyBytes = new byte[32];
5770
final SecretKey headerKey = new SecretKeySpec(keyBytes, "AES");
5871
final SecretKey macKey = new SecretKeySpec(keyBytes, "HmacSHA256");
5972
final ByteBuffer headerBuf = ByteBuffer.wrap(Base64.decode("AAAAAAAAAAAAAAAAAAAAANyVwHiiQImjrUiiFJKEIIdTD4r7x0U2ualjtPHEy3OLzqdAPU1ga26lJzstK9RUv1hj5zDC4wC9FgMfoVE1mD0HnuENuYXkJA=="));
6073
final FileHeader header = FileHeader.decrypt(headerKey, new ThreadLocalMac(macKey, "HmacSHA256"), headerBuf);
6174

62-
Assert.assertEquals(42, header.getPayload().getFilesize());
75+
Assert.assertEquals(42l, header.getPayload().getFilesize());
6376
Assert.assertArrayEquals(new byte[16], header.getIv());
6477
Assert.assertArrayEquals(new byte[32], header.getPayload().getContentKey().getEncoded());
6578
}

main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ void setVault(Vault vault) {
124124
// trigger "default" change to refresh key bindings:
125125
changePasswordButton.setDefaultButton(false);
126126
changePasswordButton.setDefaultButton(true);
127+
messageText.setText(null);
127128
}
128129

129130
// ****************************************
@@ -144,7 +145,7 @@ private void didClickChangePasswordButton(ActionEvent event) {
144145
downloadsPageLink.setVisible(false);
145146
try {
146147
vault.changePassphrase(oldPasswordField.getCharacters(), newPasswordField.getCharacters());
147-
messageText.setText(localization.getString("changePassword.infoMessage.success"));
148+
messageText.setText(null);
148149
listener.ifPresent(this::invokeListenerLater);
149150
} catch (InvalidPassphraseException e) {
150151
messageText.setText(localization.getString("changePassword.errorMessage.wrongPassword"));

main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ void setVault(Vault vault) {
178178

179179
@FXML
180180
public void didClickDownloadsLink(ActionEvent event) {
181-
app.getHostServices().showDocument("https://cryptomator.org/downloads/");
181+
app.getHostServices().showDocument("https://cryptomator.org/downloads/#allVersions");
182182
}
183183

184184
// ****************************************
@@ -311,11 +311,15 @@ private void unlock(CharSequence password) {
311311
});
312312
} catch (UnsupportedVaultFormatException e) {
313313
Platform.runLater(() -> {
314-
downloadsPageLink.setVisible(true);
315314
if (e.isVaultOlderThanSoftware()) {
315+
// whitespace after localized text used as separator between text and hyperlink
316316
messageText.setText(localization.getString("unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware") + " ");
317+
downloadsPageLink.setVisible(true);
317318
} else if (e.isSoftwareOlderThanVault()) {
318319
messageText.setText(localization.getString("unlock.errorMessage.unsupportedVersion.softwareOlderThanVault") + " ");
320+
downloadsPageLink.setVisible(true);
321+
} else if (e.getDetectedVersion() == Integer.MAX_VALUE) {
322+
messageText.setText(localization.getString("unlock.errorMessage.unauthenticVersionMac"));
319323
}
320324
});
321325
} catch (FrontendCreationFailedException | CommandFailedException e) {

main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategy.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,15 @@ public void upgrade(Vault vault, CharSequence passphrase) throws UpgradeFailedEx
5757
Files.write(masterkeyFileAfterUpgrade, upgradedMasterkeyFileContents, StandardOpenOption.TRUNCATE_EXISTING);
5858
} catch (InvalidPassphraseException e) {
5959
throw new UpgradeFailedException(localization.getString("unlock.errorMessage.wrongPassword"));
60-
} catch (IOException | UnsupportedVaultFormatException e) {
60+
} catch (UnsupportedVaultFormatException e) {
61+
if (e.getDetectedVersion() == Integer.MAX_VALUE) {
62+
LOG.warn("Version MAC authentication error in vault {}", vault.path().get());
63+
throw new UpgradeFailedException(localization.getString("unlock.errorMessage.unauthenticVersionMac"));
64+
} else {
65+
LOG.warn("Upgrade failed.", e);
66+
throw new UpgradeFailedException("Upgrade failed. Details in log message.");
67+
}
68+
} catch (IOException e) {
6169
LOG.warn("Upgrade failed.", e);
6270
throw new UpgradeFailedException("Upgrade failed. Details in log message.");
6371
} finally {

main/ui/src/main/java/org/cryptomator/ui/model/Vault.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ private Map<MountParam, Optional<String>> getMountParams(Settings settings) {
168168
);
169169
}
170170

171-
public void reveal() throws CommandFailedException {
171+
public synchronized void reveal() throws CommandFailedException {
172172
Optionals.ifPresent(filesystemFrontend.get(), Frontend::reveal);
173173
}
174174

@@ -190,7 +190,7 @@ public boolean shouldSkipAuthentication(String cleartextPath) {
190190
// Getter/Setter
191191
// *******************************************************************************/
192192

193-
public String getWebDavUrl() {
193+
public synchronized String getWebDavUrl() {
194194
return filesystemFrontend.get().map(Frontend::getWebDavUrl).orElseThrow(IllegalStateException::new);
195195
}
196196

main/ui/src/main/resources/localization/de.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,10 @@ main.directoryList.remove.confirmation.title = Tresor entfernen
8282
main.directoryList.remove.confirmation.header = Möchten Sie diesen Tresor wirklich entfernen?
8383
main.directoryList.remove.confirmation.content = Dieser Tresor wird nur aus der Liste entfernt. Um den Tresor unwiderruflich zu löschen, entfernen Sie bitte die Dateien aus Ihrem Dateisystem.
8484
upgrade.version3to4.msg = Dieser Tresor muss auf ein neueres Format aktualisiert werden.\nVerschlüsselte Ordnernamen werden dabei aktualisiert.\nStellen Sie bitte sicher, dass derzeit keine Synchronisation stattfindet.
85-
upgrade.version3to4.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen.\nWeitere Informationen in der Log-Datei.
85+
upgrade.version3to4.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen.\nWeitere Informationen in der Log-Datei.
86+
settings.prefGvfsScheme.label = WebDAV Schema
87+
# upgrade.fxml
88+
upgrade.confirmation.label = Ja, die Synchronisation ist abgeschlossen
89+
initialize.messageLabel.notEmpty = Tresor ist nicht leer
90+
unlock.label.savePassword = Passwort speichern
91+
unlock.errorMessage.unauthenticVersionMac = Versions-MAC konnte nicht authentifiziert werden.

main/ui/src/main/resources/localization/en.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ unlock.errorMessage.wrongPassword=Wrong password
6363
unlock.errorMessage.mountingFailed=Mounting failed. See log file for details.
6464
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware=Unsupported vault. This vault has been created with an older version of Cryptomator.
6565
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault=Unsupported vault. This vault has been created with a newer version of Cryptomator.
66+
unlock.errorMessage.unauthenticVersionMac=Could not authenticate version MAC.
6667
unlock.messageLabel.startServerFailed=Starting WebDAV server failed.
6768

6869
# change_password.fxml
@@ -73,7 +74,6 @@ changePassword.label.downloadsPageLink=All Cryptomator versions
7374
changePassword.button.change=Change password
7475
changePassword.errorMessage.wrongPassword=Wrong password
7576
changePassword.errorMessage.decryptionFailed=Decryption failed
76-
changePassword.infoMessage.success=Password changed
7777

7878
# unlocked.fxml
7979
unlocked.button.lock=Lock vault

main/ui/src/main/resources/localization/es.txt

+8-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ initialize.label.password = Contraseña
1414
initialize.label.retypePassword = Reintroduzca contraseña
1515
initialize.button.ok = Crear caja fuerte
1616
initialize.messageLabel.alreadyInitialized = Caja fuerte ya está inicializado
17-
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
17+
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
1818
# notfound.fxml
1919
notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar?
2020
# upgrade.fxml
@@ -83,4 +83,10 @@ main.directoryList.remove.confirmation.title = Borrar caja fuerte
8383
main.directoryList.remove.confirmation.header = ¿Quieres de verdad borrar este caja fuerte?
8484
main.directoryList.remove.confirmation.content = La caja fuerte solo se borra de la lista. Para eliminarla permanente por favor elimina los datos de tú sistema de archivos.
8585
upgrade.version3to4.msg = Este caja fuerte se debe migrar a un formato más reciente.\nLos nombres de las carpetas cifradas se actualizan.\nPor favor asegurarse de que la sincronización ha terminado antes de seguir.
86-
upgrade.version3to4.err.io = Migración ha fallado por causa de una excepción I/O. Para detalles revisa el archivo de registro.
86+
upgrade.version3to4.err.io = Migración ha fallado por causa de una excepción I/O. Para detalles revisa el archivo de registro.
87+
settings.prefGvfsScheme.label = WebDAV scheme
88+
# upgrade.fxml
89+
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
90+
initialize.messageLabel.notEmpty = Vault not empty
91+
unlock.label.savePassword = Save password
92+
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.

main/ui/src/main/resources/localization/fr.txt

+8-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,16 @@ initialize.messageLabel.passwordStrength.0 = Très faible
7878
initialize.messageLabel.passwordStrength.1 = Faible
7979
initialize.messageLabel.passwordStrength.2 = Raisonnable
8080
initialize.messageLabel.passwordStrength.3 = Fort
81-
initialize.messageLabel.passwordStrength.4 = Très fort\n
81+
initialize.messageLabel.passwordStrength.4 = Très fort
8282
initialize.label.doNotForget = ATTENTION \: Si vous oubliez votre mot de passe, il n'y aura aucun moyen de récupérer vos données.
8383
main.directoryList.remove.confirmation.title = Retirer un coffre
8484
main.directoryList.remove.confirmation.header = Voulez-vous vraiment retirer ce coffre ?
8585
main.directoryList.remove.confirmation.content = Le coffre sera simplement retiré de la liste. Pour le supprimer complètement, supprimez les fichiers depuis votre système de fichiers.
8686
upgrade.version3to4.msg = Ce coffre doit être converti dans un nouveau format. Les noms de dossiers chiffrés seront mis à jour.\nMerci de vous assurer que la procédure de synchronisation est terminée avant de continuer.
87-
upgrade.version3to4.err.io = La migration a échoué à cause d'une erreur d'entrée/sortie. Référez-vous au fichier log pour plus de détails.
87+
upgrade.version3to4.err.io = La migration a échoué à cause d'une erreur d'entrée/sortie. Référez-vous au fichier log pour plus de détails.
88+
settings.prefGvfsScheme.label = Schéma d'URI WebDAV
89+
# upgrade.fxml
90+
upgrade.confirmation.label = Oui, je suis certain que la synchronisation est finie
91+
initialize.messageLabel.notEmpty = Vault not empty
92+
unlock.label.savePassword = Save password
93+
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.

main/ui/src/main/resources/localization/hu.txt

+9-1
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,12 @@ initialize.messageLabel.passwordStrength.4 = Nagyon erős
7979
initialize.label.doNotForget = FONTOS\: Ha elfelejted a jelszavadat, akkor nincs lehetőség az adataid visszaállítására.
8080
main.directoryList.remove.confirmation.title = Széf eltávolítása
8181
main.directoryList.remove.confirmation.header = Tényleg törölni akarod ezt a széfet?
82-
main.directoryList.remove.confirmation.content = A széf csak a listából lesz eltávolítva. Végleges törléshez kérlek töröld a merevlemezen tárolt fájlokat.
82+
main.directoryList.remove.confirmation.content = A széf csak a listából lesz eltávolítva. Végleges törléshez kérlek töröld a merevlemezen tárolt fájlokat.
83+
upgrade.version3to4.msg = Ennek a széfnek egy újabb formátumra való migrációja szükséges. A titkosított könyvtárnevek frissítve lesznek. Kérlek, győződj meg a szinkronizáció befejeztéről mielőtt továbblépnél.
84+
upgrade.version3to4.err.io = Migráció meghíusúlt egy I/O kivétel miatt. Kérlek nézd meg a naplófájlt a további részletekért.
85+
settings.prefGvfsScheme.label = WebDAV séma
86+
# upgrade.fxml
87+
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
88+
initialize.messageLabel.notEmpty = Vault not empty
89+
unlock.label.savePassword = Save password
90+
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.

0 commit comments

Comments
 (0)