mirror of
https://github.com/cryptomator/cryptomator.git
synced 2024-11-23 12:09:45 +00:00
add first draft for hub+http
/ hub+https
keyloading scheme
This commit is contained in:
parent
2952733a11
commit
b21ea61342
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="~/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" -Dcryptomator.p12Path="~/.config/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="~/.config/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/.local/share/Cryptomator/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" -Dcryptomator.showTrayIcon=true -Xss20m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Linux Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="~/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Djdk.gtk.version=2 -Duser.language=en -Dcryptomator.settingsPath="~/.config/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="~/.config/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="~/.config/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/.local/share/Cryptomator-Dev/logs" -Dcryptomator.mountPointsDir="~/.local/share/Cryptomator-Dev/mnt" -Dcryptomator.showTrayIcon=true -Dfuse.experimental="true" -Xss20m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" -Dcryptomator.p12Path="~/AppData/Roaming/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<configuration default="false" name="Cryptomator Windows Dev" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="~/AppData/Roaming/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/AppData/Roaming/Cryptomator-Dev" -Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator-Dev/keychain.json" -Dcryptomator.mountPointsDir="~/Cryptomator-Dev" -Dfuse.experimental="true" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.ipcSocketPath="~/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.p12Path="~/Library/Application Support/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="~/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="~/Library/Logs/Cryptomator" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.ipcSocketPath="~/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<option name="VM_PARAMETERS" value="-Duser.language=en -Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator-Dev/settings.json" -Dcryptomator.p12Path="~/Library/Application Support/Cryptomator-Dev/key.p12" -Dcryptomator.ipcSocketPath="~/Library/Application Support/Cryptomator-Dev/ipc.socket" -Dcryptomator.logDir="~/Library/Logs/Cryptomator-Dev" -Dcryptomator.showTrayIcon=true -Xss2m -Xmx512m -ea" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
19
src/main/resources/fxml/hub_p12.fxml
Normal file
19
src/main/resources/fxml/hub_p12.fxml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.keyloading.hub.P12Controller"
|
||||
minWidth="400"
|
||||
maxWidth="400"
|
||||
minHeight="145"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<fx:include source="hub_p12_load.fxml" visible="${controller.p12Present}" managed="${controller.p12Present}"/>
|
||||
<fx:include source="hub_p12_create.fxml" visible="${!controller.p12Present}" managed="${!controller.p12Present}"/>
|
||||
</children>
|
||||
</VBox>
|
39
src/main/resources/fxml/hub_p12_create.fxml
Normal file
39
src/main/resources/fxml/hub_p12_create.fxml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.keyloading.hub.P12CreateController"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<HBox spacing="12" VBox.vgrow="ALWAYS">
|
||||
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" smooth="true" cache="true" visible="false">
|
||||
<Image url="@../img/bot/bot.png"/>
|
||||
</ImageView>
|
||||
<fx:include fx:id="newPassword" source="new_password.fxml" disable="${controller.userInteractionDisabled}"/>
|
||||
</HBox>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CO">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel" disable="${controller.userInteractionDisabled}"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="OK_DONE" defaultButton="true" onAction="#create" contentDisplay="${controller.unlockButtonContentDisplay}" disable="${!controller.readyToCreate || controller.userInteractionDisabled}">
|
||||
<graphic>
|
||||
<FontAwesome5Spinner glyphSize="12"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
48
src/main/resources/fxml/hub_p12_load.fxml
Normal file
48
src/main/resources/fxml/hub_p12_load.fxml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
|
||||
<?import org.cryptomator.ui.controls.NiceSecurePasswordField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ButtonBar?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Hyperlink?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns:fx="http://javafx.com/fxml"
|
||||
xmlns="http://javafx.com/javafx"
|
||||
fx:controller="org.cryptomator.ui.keyloading.hub.P12LoadController"
|
||||
spacing="12">
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="12"/>
|
||||
</padding>
|
||||
<children>
|
||||
<HBox spacing="12" VBox.vgrow="ALWAYS">
|
||||
<ImageView VBox.vgrow="ALWAYS" fitWidth="64" preserveRatio="true" smooth="true" cache="true" visible="false">
|
||||
<Image url="@../img/bot/bot.png"/>
|
||||
</ImageView>
|
||||
<VBox spacing="6" HBox.hgrow="ALWAYS">
|
||||
<Label text="TODO: Please enter your device secret to start communicating with Cryptomator Hub"/>
|
||||
<NiceSecurePasswordField fx:id="passwordField" disable="${controller.userInteractionDisabled}"/>
|
||||
<CheckBox fx:id="savePasswordCheckbox" text="TODO save password" disable="${controller.userInteractionDisabled}"/>
|
||||
<Hyperlink text="TODO: Click to reset your device secret (you need to re-apply for vault access)"/>
|
||||
</VBox>
|
||||
</HBox>
|
||||
|
||||
<VBox alignment="BOTTOM_CENTER" VBox.vgrow="ALWAYS">
|
||||
<ButtonBar buttonMinWidth="120" buttonOrder="+CO">
|
||||
<buttons>
|
||||
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#cancel" disable="${controller.userInteractionDisabled}"/>
|
||||
<Button text="%generic.button.next" ButtonBar.buttonData="OK_DONE" defaultButton="true" onAction="#load" contentDisplay="${controller.unlockButtonContentDisplay}" disable="${controller.userInteractionDisabled}">
|
||||
<graphic>
|
||||
<FontAwesome5Spinner glyphSize="12"/>
|
||||
</graphic>
|
||||
</Button>
|
||||
</buttons>
|
||||
</ButtonBar>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
Loading…
Reference in New Issue
Block a user