mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-07-30 20:12:38 +00:00
add first draft for hub+http / hub+https keyloading scheme
This commit is contained in:
@@ -47,6 +47,7 @@ module org.cryptomator.desktop {
|
||||
opens org.cryptomator.ui.forgetPassword to javafx.fxml;
|
||||
opens org.cryptomator.ui.fxapp to javafx.fxml;
|
||||
opens org.cryptomator.ui.health to javafx.fxml;
|
||||
opens org.cryptomator.ui.keyloading.hub to javafx.fxml;
|
||||
opens org.cryptomator.ui.keyloading.masterkeyfile to javafx.fxml;
|
||||
opens org.cryptomator.ui.mainwindow to javafx.fxml;
|
||||
opens org.cryptomator.ui.migration to javafx.fxml;
|
||||
|
||||
@@ -33,6 +33,7 @@ public class Environment {
|
||||
LOG.debug("user.region: {}", System.getProperty("user.region"));
|
||||
LOG.debug("logback.configurationFile: {}", System.getProperty("logback.configurationFile"));
|
||||
LOG.debug("cryptomator.settingsPath: {}", System.getProperty("cryptomator.settingsPath"));
|
||||
LOG.debug("cryptomator.p12Path: {}", System.getProperty("cryptomator.p12Path"));
|
||||
LOG.debug("cryptomator.ipcSocketPath: {}", System.getProperty("cryptomator.ipcSocketPath"));
|
||||
LOG.debug("cryptomator.keychainPath: {}", System.getProperty("cryptomator.keychainPath"));
|
||||
LOG.debug("cryptomator.logDir: {}", System.getProperty("cryptomator.logDir"));
|
||||
@@ -51,6 +52,10 @@ public class Environment {
|
||||
return getPaths("cryptomator.settingsPath");
|
||||
}
|
||||
|
||||
public Stream<Path> getP12Path() {
|
||||
return getPaths("cryptomator.p12Path");
|
||||
}
|
||||
|
||||
public Stream<Path> ipcSocketPath() {
|
||||
return getPaths("cryptomator.ipcSocketPath");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public enum FxmlFile {
|
||||
HEALTH_START("/fxml/health_start.fxml"), //
|
||||
HEALTH_START_FAIL("/fxml/health_start_fail.fxml"), //
|
||||
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
|
||||
HUB_P12("/fxml/hub_p12.fxml"), //
|
||||
LOCK_FORCED("/fxml/lock_forced.fxml"), //
|
||||
LOCK_FAILED("/fxml/lock_failed.fxml"), //
|
||||
MAIN_WINDOW("/fxml/main_window.fxml"), //
|
||||
|
||||
@@ -82,6 +82,10 @@ public class NiceSecurePasswordField extends StackPane {
|
||||
return passwordField.textProperty();
|
||||
}
|
||||
|
||||
public char[] copyChars() {
|
||||
return passwordField.copyChars();
|
||||
}
|
||||
|
||||
public CharSequence getCharacters() {
|
||||
return passwordField.getCharacters();
|
||||
}
|
||||
|
||||
@@ -194,6 +194,15 @@ public class SecurePasswordField extends TextField {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a copy of the password characters. This copy needs to be wiped by the caller when done.
|
||||
*
|
||||
* @return A copy of the password
|
||||
*/
|
||||
public char[] copyChars() {
|
||||
return Arrays.copyOf(content, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a CharSequence by wrapping the password characters.
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.cryptomator.cryptofs.VaultConfig.UnverifiedVaultConfig;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.keyloading.hub.HubKeyLoadingModule;
|
||||
import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingModule;
|
||||
|
||||
import javax.inject.Provider;
|
||||
@@ -16,7 +17,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@Module(includes = {MasterkeyFileLoadingModule.class})
|
||||
@Module(includes = {MasterkeyFileLoadingModule.class, HubKeyLoadingModule.class})
|
||||
abstract class KeyLoadingModule {
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import dagger.multibindings.IntoMap;
|
||||
import dagger.multibindings.StringKey;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.FxControllerKey;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.NewPasswordController;
|
||||
import org.cryptomator.ui.common.PasswordStrengthUtil;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import java.security.KeyPair;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Module
|
||||
public abstract class HubKeyLoadingModule {
|
||||
|
||||
public enum P12KeyLoading {
|
||||
LOADED,
|
||||
CREATED,
|
||||
CANCELED
|
||||
}
|
||||
|
||||
@Provides
|
||||
@KeyLoadingScoped
|
||||
static AtomicReference<KeyPair> provideKeyPair() {
|
||||
return new AtomicReference<>();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@KeyLoadingScoped
|
||||
static UserInteractionLock<P12KeyLoading> provideP12KeyLoadingLock() {
|
||||
return new UserInteractionLock<>(null);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@KeyLoadingScoped
|
||||
@StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTP)
|
||||
abstract KeyLoadingStrategy bindHubKeyLoadingStrategyToHubHttp(HubKeyLoadingStrategy strategy);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@KeyLoadingScoped
|
||||
@StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)
|
||||
abstract KeyLoadingStrategy bindHubKeyLoadingStrategyToHubHttps(HubKeyLoadingStrategy strategy);
|
||||
|
||||
@Provides
|
||||
@FxmlScene(FxmlFile.HUB_P12)
|
||||
@KeyLoadingScoped
|
||||
static Scene provideHubP12LoadingScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
|
||||
return fxmlLoaders.createScene(FxmlFile.HUB_P12);
|
||||
}
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(P12Controller.class)
|
||||
abstract FxController bindP12Controller(P12Controller controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(P12LoadController.class)
|
||||
abstract FxController bindP12LoadController(P12LoadController controller);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FxControllerKey(P12CreateController.class)
|
||||
abstract FxController bindP12CreateController(P12CreateController controller);
|
||||
|
||||
@Provides
|
||||
@IntoMap
|
||||
@FxControllerKey(NewPasswordController.class)
|
||||
static FxController provideNewPasswordController(ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater) {
|
||||
return new NewPasswordController(resourceBundle, strengthRater);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import dagger.Lazy;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.cryptolib.api.Masterkey;
|
||||
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlScene;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingStrategy;
|
||||
import org.cryptomator.ui.unlock.UnlockCancelledException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.KeyPair;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@KeyLoading
|
||||
public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
|
||||
|
||||
static final String SCHEME_HUB_HTTP = "hub+http";
|
||||
static final String SCHEME_HUB_HTTPS = "hub+https";
|
||||
private static final String SCHEME_HTTP = "http";
|
||||
private static final String SCHEME_HTTPS = "https";
|
||||
|
||||
private final Vault vault;
|
||||
private final Stage window;
|
||||
private final Lazy<Scene> p12LoadingScene;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock;
|
||||
private final AtomicReference<KeyPair> keyPairRef;
|
||||
|
||||
@Inject
|
||||
public HubKeyLoadingStrategy(@KeyLoading Vault vault, @KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_P12) Lazy<Scene> p12LoadingScene, UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock, AtomicReference<KeyPair> keyPairRef) {
|
||||
this.vault = vault;
|
||||
this.window = window;
|
||||
this.p12LoadingScene = p12LoadingScene;
|
||||
this.p12LoadingLock = p12LoadingLock;
|
||||
this.keyPairRef = keyPairRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
|
||||
return switch (keyId.getScheme().toLowerCase()) {
|
||||
case SCHEME_HUB_HTTP -> loadKey(keyId, SCHEME_HTTP);
|
||||
case SCHEME_HUB_HTTPS -> loadKey(keyId, SCHEME_HTTPS);
|
||||
default -> throw new IllegalArgumentException("Only supports keys with schemes " + SCHEME_HUB_HTTP + " or " + SCHEME_HUB_HTTPS);
|
||||
};
|
||||
}
|
||||
|
||||
private Masterkey loadKey(URI keyId, String adjustedScheme) {
|
||||
try {
|
||||
var foo = new URI(adjustedScheme, keyId.getSchemeSpecificPart(), keyId.getFragment());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalStateException("URI known to be valid, if old URI was valid", e);
|
||||
}
|
||||
|
||||
try {
|
||||
loadP12();
|
||||
LOG.info("keypair loaded {}", keyPairRef.get().getPublic());
|
||||
throw new UnlockCancelledException("not yet implemented"); // TODO
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new UnlockCancelledException("Loading interrupted", e);
|
||||
}
|
||||
}
|
||||
|
||||
private HubKeyLoadingModule.P12KeyLoading loadP12() throws InterruptedException {
|
||||
Platform.runLater(() -> {
|
||||
window.setScene(p12LoadingScene.get());
|
||||
window.show();
|
||||
Window owner = window.getOwner();
|
||||
if (owner != null) {
|
||||
window.setX(owner.getX() + (owner.getWidth() - window.getWidth()) / 2);
|
||||
window.setY(owner.getY() + (owner.getHeight() - window.getHeight()) / 2);
|
||||
} else {
|
||||
window.centerOnScreen();
|
||||
}
|
||||
});
|
||||
return p12LoadingLock.awaitInteraction();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
||||
import org.cryptomator.cryptolib.common.Destroyables;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.NewPasswordController;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.controls.NiceSecurePasswordField;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.binding.ObjectExpression;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.WindowEvent;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@KeyLoadingScoped
|
||||
public class P12Controller implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(P12Controller.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Environment env;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock;
|
||||
|
||||
@Inject
|
||||
public P12Controller(@KeyLoading Stage window, Environment env, AtomicReference<KeyPair> keyPairRef, UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock) {
|
||||
this.window = window;
|
||||
this.env = env;
|
||||
this.p12LoadingLock = p12LoadingLock;
|
||||
this.window.setOnHiding(this::windowClosed);
|
||||
}
|
||||
|
||||
private void windowClosed(WindowEvent windowEvent) {
|
||||
// if not already interacted, mark this workflow as cancelled:
|
||||
if (p12LoadingLock.awaitingInteraction().get()) {
|
||||
LOG.debug("P12 loading canceled by user.");
|
||||
p12LoadingLock.interacted(HubKeyLoadingModule.P12KeyLoading.CANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public boolean isP12Present() {
|
||||
return env.getP12Path().anyMatch(Files::isRegularFile);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.cryptolib.common.Destroyables;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.NewPasswordController;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import javafx.beans.binding.ObjectExpression;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@KeyLoadingScoped
|
||||
public class P12CreateController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(P12LoadController.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Environment env;
|
||||
private final AtomicReference<KeyPair> keyPairRef;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock;
|
||||
private final BooleanProperty userInteractionDisabled = new SimpleBooleanProperty();
|
||||
private final ObjectBinding<ContentDisplay> unlockButtonContentDisplay = Bindings.createObjectBinding(this::getUnlockButtonContentDisplay, userInteractionDisabled);
|
||||
private final BooleanProperty readyToCreate = new SimpleBooleanProperty();
|
||||
|
||||
public NewPasswordController newPasswordController;
|
||||
|
||||
|
||||
@Inject
|
||||
public P12CreateController(@KeyLoading Stage window, Environment env, AtomicReference<KeyPair> keyPairRef, UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock) {
|
||||
this.window = window;
|
||||
this.env = env;
|
||||
this.keyPairRef = keyPairRef;
|
||||
this.p12LoadingLock = p12LoadingLock;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
readyToCreate.bind(newPasswordController.goodPasswordProperty());
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void create() {
|
||||
Preconditions.checkState(newPasswordController.goodPasswordProperty().get());
|
||||
char[] pw = newPasswordController.passwordField.copyChars();
|
||||
try {
|
||||
Path p12File = env.getP12Path().findFirst().orElseThrow(IllegalStateException::new);
|
||||
var keyPair = P12AccessHelper.createNew(p12File, pw);
|
||||
setKeyPair(keyPair);
|
||||
LOG.debug("Created .p12 file {}", p12File);
|
||||
p12LoadingLock.interacted(HubKeyLoadingModule.P12KeyLoading.CREATED);
|
||||
window.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to load .p12 file.", e);
|
||||
// TODO
|
||||
} finally {
|
||||
Arrays.fill(pw, '\0');
|
||||
newPasswordController.passwordField.wipe();
|
||||
newPasswordController.reenterField.wipe();
|
||||
}
|
||||
}
|
||||
|
||||
private void setKeyPair(KeyPair keyPair) {
|
||||
var oldKeyPair = keyPairRef.getAndSet(keyPair);
|
||||
if (oldKeyPair != null) {
|
||||
Destroyables.destroySilently(oldKeyPair.getPrivate());
|
||||
}
|
||||
}
|
||||
/* Getter/Setter */
|
||||
|
||||
|
||||
public BooleanExpression userInteractionDisabledProperty() {
|
||||
return userInteractionDisabled;
|
||||
}
|
||||
|
||||
public boolean isUserInteractionDisabled() {
|
||||
return userInteractionDisabled.get();
|
||||
}
|
||||
|
||||
public ObjectExpression<ContentDisplay> unlockButtonContentDisplayProperty() {
|
||||
return unlockButtonContentDisplay;
|
||||
}
|
||||
|
||||
public ContentDisplay getUnlockButtonContentDisplay() {
|
||||
return userInteractionDisabled.get() ? ContentDisplay.LEFT : ContentDisplay.TEXT_ONLY;
|
||||
}
|
||||
|
||||
public BooleanProperty readyToCreateProperty() {
|
||||
return readyToCreate;
|
||||
}
|
||||
|
||||
public boolean isReadyToCreate() {
|
||||
return readyToCreate.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.cryptomator.ui.keyloading.hub;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.cryptolib.api.InvalidPassphraseException;
|
||||
import org.cryptomator.cryptolib.common.Destroyables;
|
||||
import org.cryptomator.ui.common.Animations;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.common.UserInteractionLock;
|
||||
import org.cryptomator.ui.controls.NiceSecurePasswordField;
|
||||
import org.cryptomator.ui.keyloading.KeyLoading;
|
||||
import org.cryptomator.ui.keyloading.KeyLoadingScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import javafx.beans.binding.ObjectExpression;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.stage.Stage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyPair;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@KeyLoadingScoped
|
||||
public class P12LoadController implements FxController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(P12LoadController.class);
|
||||
|
||||
private final Stage window;
|
||||
private final Environment env;
|
||||
private final AtomicReference<KeyPair> keyPairRef;
|
||||
private final UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock;
|
||||
private final BooleanProperty userInteractionDisabled = new SimpleBooleanProperty();
|
||||
private final ObjectBinding<ContentDisplay> unlockButtonContentDisplay = Bindings.createObjectBinding(this::getUnlockButtonContentDisplay, userInteractionDisabled);
|
||||
|
||||
public NiceSecurePasswordField passwordField;
|
||||
|
||||
@Inject
|
||||
public P12LoadController(@KeyLoading Stage window, Environment env, AtomicReference<KeyPair> keyPairRef, UserInteractionLock<HubKeyLoadingModule.P12KeyLoading> p12LoadingLock) {
|
||||
this.window = window;
|
||||
this.env = env;
|
||||
this.keyPairRef = keyPairRef;
|
||||
this.p12LoadingLock = p12LoadingLock;
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
window.close();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void load() {
|
||||
char[] pw = passwordField.copyChars();
|
||||
try {
|
||||
Path p12File = env.getP12Path().filter(Files::isRegularFile).findFirst().orElseThrow(IllegalStateException::new);
|
||||
var keyPair = P12AccessHelper.loadExisting(p12File, pw);
|
||||
setKeyPair(keyPair);
|
||||
LOG.debug("Loaded .p12 file {}", p12File);
|
||||
p12LoadingLock.interacted(HubKeyLoadingModule.P12KeyLoading.LOADED);
|
||||
window.close();
|
||||
} catch (InvalidPassphraseException e) {
|
||||
LOG.warn("Invalid passphrase entered for .p12 file");
|
||||
Animations.createShakeWindowAnimation(window).playFromStart();
|
||||
// TODO
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to load .p12 file.", e);
|
||||
// TODO
|
||||
} finally {
|
||||
Arrays.fill(pw, '\0');
|
||||
passwordField.wipe();
|
||||
}
|
||||
}
|
||||
|
||||
private void setKeyPair(KeyPair keyPair) {
|
||||
var oldKeyPair = keyPairRef.getAndSet(keyPair);
|
||||
if (oldKeyPair != null) {
|
||||
Destroyables.destroySilently(oldKeyPair.getPrivate());
|
||||
}
|
||||
}
|
||||
|
||||
/* Getter/Setter */
|
||||
|
||||
public BooleanExpression userInteractionDisabledProperty() {
|
||||
return userInteractionDisabled;
|
||||
}
|
||||
|
||||
public boolean isUserInteractionDisabled() {
|
||||
return userInteractionDisabled.get();
|
||||
}
|
||||
|
||||
public ObjectExpression<ContentDisplay> unlockButtonContentDisplayProperty() {
|
||||
return unlockButtonContentDisplay;
|
||||
}
|
||||
|
||||
public ContentDisplay getUnlockButtonContentDisplay() {
|
||||
return userInteractionDisabled.get() ? ContentDisplay.LEFT : ContentDisplay.TEXT_ONLY;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user