Generate recovery key during vault creation

This commit is contained in:
Sebastian Stenzel
2019-10-08 16:26:57 +02:00
parent 08d9beb6b8
commit f7630c28d6
9 changed files with 135 additions and 26 deletions

View File

@@ -65,6 +65,7 @@ public abstract class AddVaultModule {
}
@Provides
@Named("vaultName")
@AddVaultWizardScoped
static StringProperty provideVaultName() {
return new SimpleStringProperty("");
@@ -77,6 +78,13 @@ public abstract class AddVaultModule {
return new SimpleObjectProperty<>();
}
@Provides
@Named("recoveryKey")
@AddVaultWizardScoped
static StringProperty provideRecoveryKey() {
return new SimpleStringProperty();
}
// ------------------
@Provides
@@ -114,6 +122,13 @@ public abstract class AddVaultModule {
return fxmlLoaders.createScene("/fxml/addvault_new_password.fxml");
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY)
@AddVaultWizardScoped
static Scene provideCreateNewVaultRecoveryKeyScene(@AddVaultWizardWindow FXMLLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene("/fxml/addvault_new_recoverykey.fxml");
}
@Provides
@FxmlScene(FxmlFile.ADDVAULT_SUCCESS)
@AddVaultWizardScoped
@@ -152,4 +167,9 @@ public abstract class AddVaultModule {
@IntoMap
@FxControllerKey(AddVaultSuccessController.class)
abstract FxController bindAddVaultSuccessController(AddVaultSuccessController controller);
@Binds
@IntoMap
@FxControllerKey(CreateNewVaultRecoveryKeyController.class)
abstract FxController bindCreateNewVaultRecoveryKeyController(CreateNewVaultRecoveryKeyController controller);
}

View File

@@ -23,6 +23,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
@@ -58,7 +59,7 @@ public class CreateNewVaultLocationController implements FxController {
public RadioButton customRadioButton;
@Inject
CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy<Scene> choosePasswordScene, LocationPresets locationPresets, ObjectProperty<Path> vaultPath, StringProperty vaultName, ResourceBundle resourceBundle) {
CreateNewVaultLocationController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_NAME) Lazy<Scene> chooseNameScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_PASSWORD) Lazy<Scene> choosePasswordScene, LocationPresets locationPresets, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
this.window = window;
this.chooseNameScene = chooseNameScene;
this.choosePasswordScene = choosePasswordScene;

View File

@@ -16,6 +16,7 @@ import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Inject;
import javax.inject.Named;
import java.nio.file.Path;
import java.util.ResourceBundle;
import java.util.regex.Pattern;
@@ -36,7 +37,7 @@ public class CreateNewVaultNameController implements FxController {
private final StringBinding warningText;
@Inject
CreateNewVaultNameController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, ObjectProperty<Path> vaultPath, StringProperty vaultName, ResourceBundle resourceBundle) {
CreateNewVaultNameController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_WELCOME) Lazy<Scene> welcomeScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, ObjectProperty<Path> vaultPath, @Named("vaultName") StringProperty vaultName, ResourceBundle resourceBundle) {
this.window = window;
this.welcomeScene = welcomeScene;
this.chooseLocationScene = chooseLocationScene;

View File

@@ -12,7 +12,6 @@ import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
@@ -28,11 +27,13 @@ import org.cryptomator.ui.common.Tasks;
import org.cryptomator.ui.controls.FontAwesome5IconView;
import org.cryptomator.ui.controls.NiceSecurePasswordField;
import org.cryptomator.ui.common.PasswordStrengthUtil;
import org.cryptomator.ui.recoverykey.RecoveryKeyFactory;
import org.fxmisc.easybind.EasyBind;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.channels.WritableByteChannel;
@@ -56,11 +57,13 @@ public class CreateNewVaultPasswordController implements FxController {
private final Stage window;
private final Lazy<Scene> chooseLocationScene;
private final Lazy<Scene> successScene;
private final Lazy<Scene> recoveryKeyScene;
private final ExecutorService executor;
private final StringProperty vaultName;
private final ObjectProperty<Path> vaultPath;
private final ObjectProperty<Vault> vault;
private final RecoveryKeyFactory recoveryKeyFactory;
private final StringProperty vaultNameProperty;
private final ObjectProperty<Path> vaultPathProperty;
private final ObjectProperty<Vault> vaultProperty;
private final StringProperty recoveryKeyProperty;
private final VaultListManager vaultListManager;
private final ResourceBundle resourceBundle;
private final PasswordStrengthUtil strengthRater;
@@ -77,17 +80,18 @@ public class CreateNewVaultPasswordController implements FxController {
public FontAwesome5IconView checkmark;
public FontAwesome5IconView cross;
public Label passwordMatchLabel;
public CheckBox finalConfirmationCheckbox;
@Inject
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, ExecutorService executor, StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, VaultListManager vaultListManager, ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, ReadmeGenerator readmeGenerator) {
CreateNewVaultPasswordController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_NEW_LOCATION) Lazy<Scene> chooseLocationScene, @FxmlScene(FxmlFile.ADDVAULT_NEW_RECOVERYKEY) Lazy<Scene> recoveryKeyScene, ExecutorService executor, RecoveryKeyFactory recoveryKeyFactory, @Named("vaultName") StringProperty vaultName, ObjectProperty<Path> vaultPath, @AddVaultWizardWindow ObjectProperty<Vault> vault, @Named("recoveryKey") StringProperty recoveryKey, VaultListManager vaultListManager, ResourceBundle resourceBundle, PasswordStrengthUtil strengthRater, ReadmeGenerator readmeGenerator) {
this.window = window;
this.chooseLocationScene = chooseLocationScene;
this.successScene = successScene;
this.recoveryKeyScene = recoveryKeyScene;
this.executor = executor;
this.vaultName = vaultName;
this.vaultPath = vaultPath;
this.vault = vault;
this.recoveryKeyFactory = recoveryKeyFactory;
this.vaultNameProperty = vaultName;
this.vaultPathProperty = vaultPath;
this.vaultProperty = vault;
this.recoveryKeyProperty = recoveryKey;
this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle;
this.strengthRater = strengthRater;
@@ -105,7 +109,7 @@ public class CreateNewVaultPasswordController implements FxController {
//binding indicating if the passwords not match
BooleanBinding passwordsMatch = Bindings.createBooleanBinding(() -> CharSequence.compare(passwordField.getCharacters(), reenterField.getCharacters()) == 0, passwordField.textProperty(), reenterField.textProperty());
BooleanBinding reenterFieldNotEmpty = reenterField.textProperty().isNotEmpty();
readyToCreateVault.bind(reenterFieldNotEmpty.and(passwordsMatch).and(finalConfirmationCheckbox.selectedProperty()).and(processing.not()));
readyToCreateVault.bind(reenterFieldNotEmpty.and(passwordsMatch).and(processing.not()));
//make match indicator invisible when passwords do not match or one is empty
passwordMatchBox.visibleProperty().bind(reenterFieldNotEmpty);
checkmark.visibleProperty().bind(passwordsMatch.and(reenterFieldNotEmpty));
@@ -125,7 +129,7 @@ public class CreateNewVaultPasswordController implements FxController {
@FXML
public void next() {
Path pathToVault = vaultPath.get();
Path pathToVault = vaultPathProperty.get();
try {
Files.createDirectory(pathToVault);
@@ -140,8 +144,9 @@ public class CreateNewVaultPasswordController implements FxController {
processing.set(true);
Tasks.create(() -> {
initializeVault(pathToVault, passwordField.getCharacters());
}).onSuccess(() -> {
initializationSucceeded(pathToVault);
return recoveryKeyFactory.createRecoveryKey(pathToVault, passwordField.getCharacters());
}).onSuccess(recoveryKey -> {
initializationSucceeded(pathToVault, recoveryKey);
}).onError(IOException.class, e -> {
// TODO show generic error screen
LOG.error("", e);
@@ -171,11 +176,12 @@ public class CreateNewVaultPasswordController implements FxController {
LOG.info("Created vault at {}", path);
}
private void initializationSucceeded(Path pathToVault) {
private void initializationSucceeded(Path pathToVault, String recoveryKey) {
try {
Vault newVault = vaultListManager.add(pathToVault);
vault.set(newVault);
window.setScene(successScene.get());
vaultProperty.set(newVault);
recoveryKeyProperty.set(recoveryKey);
window.setScene(recoveryKeyScene.get());
} catch (NoSuchFileException e) {
throw new UncheckedIOException(e);
}
@@ -184,11 +190,11 @@ public class CreateNewVaultPasswordController implements FxController {
/* Getter/Setter */
public String getVaultName() {
return vaultName.get();
return vaultNameProperty.get();
}
public StringProperty vaultNameProperty() {
return vaultName;
return vaultNameProperty;
}
public IntegerProperty passwordStrengthProperty() {

View File

@@ -0,0 +1,42 @@
package org.cryptomator.ui.addvaultwizard;
import dagger.Lazy;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxmlFile;
import org.cryptomator.ui.common.FxmlScene;
import javax.inject.Inject;
import javax.inject.Named;
public class CreateNewVaultRecoveryKeyController implements FxController {
private final Stage window;
private final Lazy<Scene> successScene;
private final StringProperty recoveryKeyProperty;
@Inject
CreateNewVaultRecoveryKeyController(@AddVaultWizardWindow Stage window, @FxmlScene(FxmlFile.ADDVAULT_SUCCESS) Lazy<Scene> successScene, @Named("recoveryKey")StringProperty recoveryKey) {
this.window = window;
this.successScene = successScene;
this.recoveryKeyProperty = recoveryKey;
}
@FXML
public void next() {
window.setScene(successScene.get());
}
/* Getter/Setter */
public String getRecoveryKey() {
return recoveryKeyProperty.get();
}
public StringProperty recoveryKeyProperty() {
return recoveryKeyProperty;
}
}

View File

@@ -6,6 +6,7 @@ public enum FxmlFile {
ADDVAULT_NEW_NAME("/fxml/addvault_new_name.fxml"), //
ADDVAULT_NEW_LOCATION("/fxml/addvault_new_location.fxml"), //
ADDVAULT_NEW_PASSWORD("/fxml/addvault_new_password.fxml"), //
ADDVAULT_NEW_RECOVERYKEY("/fxml/addvault_new_recoverykey.fxml"), //
ADDVAULT_SUCCESS("/fxml/addvault_success.fxml"), //
CHANGEPASSWORD("/fxml/changepassword.fxml"), //
FORGET_PASSWORD("/fxml/forget_password.fxml"), //

View File

@@ -10,9 +10,8 @@
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.PasswordStrengthIndicator?>
<?import org.cryptomator.ui.controls.SecurePasswordField?>
<?import org.cryptomator.ui.controls.NiceSecurePasswordField?>
<?import org.cryptomator.ui.controls.PasswordStrengthIndicator?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.addvaultwizard.CreateNewVaultPasswordController"
@@ -41,7 +40,6 @@
<Label fx:id="passwordMatchLabel" styleClass="label-secondary" labelFor="$reenterField"/>
</HBox>
</VBox>
<CheckBox fx:id="finalConfirmationCheckbox" text="%addvaultwizard.new.finalConfirmation" wrapText="true"/>
<Region VBox.vgrow="ALWAYS"/>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.addvaultwizard.CreateNewVaultRecoveryKeyController"
prefWidth="400"
prefHeight="400"
spacing="12"
alignment="CENTER_LEFT">
<padding>
<Insets topRightBottomLeft="24"/>
</padding>
<children>
<Region VBox.vgrow="ALWAYS"/>
<Label text="%addvaultwizard.new.recoveryKeyInstruction" wrapText="true"/>
<!-- TODO use TextArea instead -->
<TextField editable="false" text="${controller.recoveryKey}"/>
<CheckBox fx:id="finalConfirmationCheckbox" text="%addvaultwizard.new.recoveryKeySavedCheckbox" wrapText="true"/>
<Region VBox.vgrow="ALWAYS"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+X">
<buttons>
<Button text="%generic.button.next" ButtonBar.buttonData="NEXT_FORWARD" onAction="#next" defaultButton="true" disable="${!finalConfirmationCheckbox.selected}"/>
</buttons>
</ButtonBar>
</children>
</VBox>

View File

@@ -38,8 +38,9 @@ addvaultwizard.new.invalidName=Invalid vault name. Please consider a regular dir
addvaultwizard.new.reenterPassword=Confirm the password
addvaultwizard.new.passwordsMatch=Passwords match!
addvaultwizard.new.passwordsDoNotMatch=Passwords do not match
addvaultwizard.new.finalConfirmation=I understand that I will not be able to recover my data if I forget my password
addvaultwizard.new.createVaultBtn=Create Vault
addvaultwizard.new.recoveryKeyInstruction=This is your recovery key. Keep it safe, it is your only chance to recover your data if you lose your password.
addvaultwizard.new.recoveryKeySavedCheckbox=Yes, I've made a secure backup of this recovery key
addvault.new.readme.storageLocation.fileName=WHAT IS THIS DIRECTORY.rtf
addvault.new.readme.storageLocation.1=\\fs40\\qc ⚠️ VAULT FILES ⚠️
addvault.new.readme.storageLocation.2=This is your vault's storage location. {\\b DO NOT} alter any files within this directory.