get cipherCombo while key validation

This commit is contained in:
Jan-Peter Klein
2025-03-17 18:39:17 +01:00
parent 6231c5b8b3
commit ebd767595b
5 changed files with 53 additions and 21 deletions

View File

@@ -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<CryptorProvider.Scheme> 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<CryptorProvider.Scheme> 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);

View File

@@ -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);
}
}

View File

@@ -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<CryptorProvider.Scheme> 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<RecoverUtil.Type> 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<RecoverUtil.Type> recoverType, @Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> cipherCombo, @Nullable MasterkeyFileAccess masterkeyFileAccess) {
return new RecoveryKeyValidateController(vault, vaultConfig, recoveryKey, recoveryKeyFactory, recoverType, cipherCombo, masterkeyFileAccess);
}
@Provides

View File

@@ -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<RecoverUtil.Type> recoverType;
private final ObjectProperty<CryptorProvider.Scheme> 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<RecoverUtil.Type> recoverType,
@Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> 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());

View File

@@ -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<Boolean> recoveryKeyInvalid;
private final RecoveryKeyFactory recoveryKeyFactory;
private final ObjectProperty<RecoveryKeyState> recoveryKeyState;
private final ObjectProperty<CryptorProvider.Scheme> cipherCombo;
private final AutoCompleter autoCompleter;
private final ObjectProperty<RecoverUtil.Type> recoverType;
private final MasterkeyFileAccess masterkeyFileAccess;
@@ -52,6 +54,7 @@ public class RecoveryKeyValidateController implements FxController {
StringProperty recoveryKey, //
RecoveryKeyFactory recoveryKeyFactory, //
@Named("recoverType") ObjectProperty<RecoverUtil.Type> recoverType, //
@Named("cipherCombo") ObjectProperty<CryptorProvider.Scheme> 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() {