From ebd767595bf6a264c908d04f33e7cbd7ac0c8c61 Mon Sep 17 00:00:00 2001 From: Jan-Peter Klein Date: Mon, 17 Mar 2025 18:39:17 +0100 Subject: [PATCH] get cipherCombo while key validation --- .../org/cryptomator/common/RecoverUtil.java | 35 +++++++++++++------ .../ui/convertvault/ConvertVaultModule.java | 2 +- .../ui/recoverykey/RecoveryKeyModule.java | 12 +++++-- .../RecoveryKeyResetPasswordController.java | 6 +++- .../RecoveryKeyValidateController.java | 19 ++++++---- 5 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/cryptomator/common/RecoverUtil.java b/src/main/java/org/cryptomator/common/RecoverUtil.java index 86d8aa4af..13244e071 100644 --- a/src/main/java/org/cryptomator/common/RecoverUtil.java +++ b/src/main/java/org/cryptomator/common/RecoverUtil.java @@ -125,20 +125,41 @@ public class RecoverUtil { return masterkeyFileAccess.load(masterkeyFilePath, password); } - public static boolean validateRecoveryKey(RecoveryKeyFactory recoveryKeyFactory, Vault vault, StringProperty recoveryKey, MasterkeyFileAccess masterkeyFileAccess) { + public static void initializeCryptoFileSystem(Path recoveryPath, Masterkey masterkey, IntegerProperty shorteningThreshold, CryptorProvider.Scheme combo) throws IOException, CryptoException { + MasterkeyLoader loader = ignored -> masterkey.copy(); + CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(combo).withKeyLoader(loader).withShorteningThreshold(shorteningThreshold.get()).build(); + CryptoFileSystemProvider.initialize(recoveryPath, fsProps, DEFAULT_KEY_ID); + } + + public static Optional getCipherCombo(Path vaultPath, Masterkey masterkey) { + try { + return Optional.of(RecoverUtil.detectCipherCombo(masterkey.getEncoded(), vaultPath)); + } catch (Exception e) { + LOG.warn("Failed to detect cipher combo", e); + return Optional.empty(); + } + } + + public static Optional validateRecoveryKeyAndGetCombo( + RecoveryKeyFactory recoveryKeyFactory, + Vault vault, + StringProperty recoveryKey, + MasterkeyFileAccess masterkeyFileAccess) { + Path tempRecoveryPath = null; CharSequence tmpPass = "asdasdasd"; + try { tempRecoveryPath = createRecoveryDirectory(vault.getPath()); createNewMasterkeyFile(recoveryKeyFactory, tempRecoveryPath, recoveryKey.get(), tmpPass); Path masterkeyFilePath = tempRecoveryPath.resolve(MASTERKEY_FILENAME); + try (Masterkey masterkey = loadMasterkey(masterkeyFileAccess, masterkeyFilePath, tmpPass)) { - initializeCryptoFileSystem(tempRecoveryPath, vault.getPath(), masterkey, new SimpleIntegerProperty(CreateNewVaultExpertSettingsController.MAX_SHORTENING_THRESHOLD)); - return true; + return getCipherCombo(vault.getPath(), masterkey); } } catch (IOException | CryptoException e) { LOG.warn("Recovery key validation failed", e); - return false; + return Optional.empty(); } finally { if (tempRecoveryPath != null) { deleteRecoveryDirectory(tempRecoveryPath); @@ -146,12 +167,6 @@ public class RecoverUtil { } } - public static void initializeCryptoFileSystem(Path recoveryPath, Path vaultPath, Masterkey masterkey, IntegerProperty shorteningThreshold) throws IOException, CryptoException { - var combo = RecoverUtil.detectCipherCombo(masterkey.getEncoded(), vaultPath); - MasterkeyLoader loader = ignored -> masterkey.copy(); - CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(combo).withKeyLoader(loader).withShorteningThreshold(shorteningThreshold.get()).build(); - CryptoFileSystemProvider.initialize(recoveryPath, fsProps, DEFAULT_KEY_ID); - } public static void moveRecoveredFiles(Path recoveryPath, Path vaultPath) throws IOException { Files.move(recoveryPath.resolve(MASTERKEY_FILENAME), vaultPath.resolve(MASTERKEY_FILENAME), StandardCopyOption.REPLACE_EXISTING); diff --git a/src/main/java/org/cryptomator/ui/convertvault/ConvertVaultModule.java b/src/main/java/org/cryptomator/ui/convertvault/ConvertVaultModule.java index aa290b621..36ba14cab 100644 --- a/src/main/java/org/cryptomator/ui/convertvault/ConvertVaultModule.java +++ b/src/main/java/org/cryptomator/ui/convertvault/ConvertVaultModule.java @@ -123,7 +123,7 @@ abstract class ConvertVaultModule { @IntoMap @FxControllerKey(RecoveryKeyValidateController.class) static FxController bindRecoveryKeyValidateController(@ConvertVaultWindow Vault vault, @ConvertVaultWindow VaultConfig.UnverifiedVaultConfig vaultConfig, @ConvertVaultWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory) { - return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, new SimpleObjectProperty<>(RecoverUtil.Type.CONVERT_VAULT),null); + return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, new SimpleObjectProperty<>(RecoverUtil.Type.CONVERT_VAULT),null,null); } } diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java index 08c23a0db..3c2f6d132 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyModule.java @@ -8,6 +8,7 @@ import org.cryptomator.common.Nullable; import org.cryptomator.common.RecoverUtil; import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptofs.VaultConfig; +import org.cryptomator.cryptolib.api.CryptorProvider; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.ui.addvaultwizard.CreateNewVaultExpertSettingsController; import org.cryptomator.ui.common.DefaultSceneFactory; @@ -161,6 +162,13 @@ abstract class RecoveryKeyModule { return new SimpleObjectProperty<>(RecoverUtil.Type.RESTORE_MASTERKEY); } + @Provides + @Named("cipherCombo") + @RecoveryKeyScoped + static ObjectProperty provideCipherCombo() { + return new SimpleObjectProperty<>(); + } + @Binds @IntoMap @FxControllerKey(RecoveryKeyExpertSettingsController.class) @@ -194,8 +202,8 @@ abstract class RecoveryKeyModule { @Provides @IntoMap @FxControllerKey(RecoveryKeyValidateController.class) - static FxController bindRecoveryKeyValidateController(@RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, @Named("recoverType") ObjectProperty recoverType, @Nullable MasterkeyFileAccess masterkeyFileAccess) { - return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, recoverType, masterkeyFileAccess); + static FxController bindRecoveryKeyValidateController(@RecoveryKeyWindow Vault vault, @RecoveryKeyWindow @Nullable VaultConfig.UnverifiedVaultConfig vaultConfig, @RecoveryKeyWindow StringProperty recoveryKey, RecoveryKeyFactory recoveryKeyFactory, @Named("recoverType") ObjectProperty recoverType, @Named("cipherCombo") ObjectProperty cipherCombo, @Nullable MasterkeyFileAccess masterkeyFileAccess) { + return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, recoverType, cipherCombo, masterkeyFileAccess); } @Provides diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java index bf301c57b..d2bc329c8 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyResetPasswordController.java @@ -5,6 +5,7 @@ import org.cryptomator.common.RecoverUtil; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; import org.cryptomator.cryptolib.api.CryptoException; +import org.cryptomator.cryptolib.api.CryptorProvider; import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.ui.changepassword.NewPasswordController; @@ -51,6 +52,7 @@ public class RecoveryKeyResetPasswordController implements FxController { private final VaultListManager vaultListManager; private final IntegerProperty shorteningThreshold; private final ObjectProperty recoverType; + private final ObjectProperty cipherCombo; private final ResourceBundle resourceBundle; private final StringProperty buttonText = new SimpleStringProperty(); @@ -70,6 +72,7 @@ public class RecoveryKeyResetPasswordController implements FxController { VaultListManager vaultListManager, // @Named("shorteningThreshold") IntegerProperty shorteningThreshold, // @Named("recoverType") ObjectProperty recoverType, + @Named("cipherCombo") ObjectProperty cipherCombo,// ResourceBundle resourceBundle) { this.window = window; this.vault = vault; @@ -83,6 +86,7 @@ public class RecoveryKeyResetPasswordController implements FxController { this.masterkeyFileAccess = masterkeyFileAccess; this.vaultListManager = vaultListManager; this.shorteningThreshold = shorteningThreshold; + this.cipherCombo = cipherCombo; this.recoverType = recoverType; this.resourceBundle = resourceBundle; @@ -116,7 +120,7 @@ public class RecoveryKeyResetPasswordController implements FxController { Path masterkeyFilePath = recoveryPath.resolve(MASTERKEY_FILENAME); try (Masterkey masterkey = RecoverUtil.loadMasterkey(masterkeyFileAccess, masterkeyFilePath, newPasswordController.passwordField.getCharacters())) { - RecoverUtil.initializeCryptoFileSystem(recoveryPath, vault.getPath(), masterkey, shorteningThreshold); + RecoverUtil.initializeCryptoFileSystem(recoveryPath,masterkey,shorteningThreshold,cipherCombo.get()); } RecoverUtil.moveRecoveredFiles(recoveryPath, vault.getPath()); diff --git a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java index 6472d3849..c0a898c54 100644 --- a/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java +++ b/src/main/java/org/cryptomator/ui/recoverykey/RecoveryKeyValidateController.java @@ -10,6 +10,7 @@ import org.cryptomator.common.vaults.Vault; import org.cryptomator.cryptofs.VaultConfig; import org.cryptomator.cryptofs.VaultConfigLoadException; import org.cryptomator.cryptofs.VaultKeyInvalidException; +import org.cryptomator.cryptolib.api.CryptorProvider; import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.ui.common.FxController; import org.slf4j.Logger; @@ -39,6 +40,7 @@ public class RecoveryKeyValidateController implements FxController { private final ObservableValue recoveryKeyInvalid; private final RecoveryKeyFactory recoveryKeyFactory; private final ObjectProperty recoveryKeyState; + private final ObjectProperty cipherCombo; private final AutoCompleter autoCompleter; private final ObjectProperty recoverType; private final MasterkeyFileAccess masterkeyFileAccess; @@ -52,6 +54,7 @@ public class RecoveryKeyValidateController implements FxController { StringProperty recoveryKey, // RecoveryKeyFactory recoveryKeyFactory, // @Named("recoverType") ObjectProperty recoverType, // + @Named("cipherCombo") ObjectProperty cipherCombo,// MasterkeyFileAccess masterkeyFileAccess) { this.vault = vault; this.unverifiedVaultConfig = vaultConfig; @@ -63,6 +66,7 @@ public class RecoveryKeyValidateController implements FxController { this.recoveryKeyWrong = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.WRONG::equals, false); this.recoveryKeyInvalid = ObservableUtil.mapWithDefault(recoveryKeyState, RecoveryKeyState.INVALID::equals, false); this.recoverType = recoverType; + this.cipherCombo = cipherCombo; this.masterkeyFileAccess = masterkeyFileAccess; } @@ -133,20 +137,20 @@ public class RecoveryKeyValidateController implements FxController { var valid = false; switch (recoverType.get()) { case RESTORE_VAULT_CONFIG -> { - try{ - valid = RecoverUtil.validateRecoveryKey(recoveryKeyFactory, vault, recoveryKey, masterkeyFileAccess); - } - catch (IllegalStateException e){ + try { + var combo = RecoverUtil.validateRecoveryKeyAndGetCombo(recoveryKeyFactory, vault, recoveryKey, masterkeyFileAccess); + valid = combo.isPresent(); + combo.ifPresent(cipherCombo::set); + } catch (IllegalStateException e) { isWrongKey = true; - } - catch (IllegalArgumentException e){ + } catch (IllegalArgumentException e) { isWrongKey = false; } } case RESTORE_MASTERKEY, RESET_PASSWORD, SHOW_KEY, CONVERT_VAULT -> { valid = recoveryKeyFactory.validateRecoveryKey(recoveryKey.get(), unverifiedVaultConfig != null ? this::checkKeyAgainstVaultConfig : null); } - }; + } if (valid) { recoveryKeyState.set(RecoveryKeyState.CORRECT); } else if (isWrongKey) { //set via side effect in checkKeyAgainstVaultConfig() @@ -156,6 +160,7 @@ public class RecoveryKeyValidateController implements FxController { } } + /* Getter/Setter */ public Vault getVault() {