mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
handle password key derivation in separate tasks
This commit is contained in:
parent
b52a7137c3
commit
2acc922b06
7 changed files with 285 additions and 112 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit d2bd335e76a6a18634d033b49bf2d36c2494d9cf
|
||||
Subproject commit 06de1d7e1458cb00cc242025c5e0d536633083a0
|
|
@ -11,6 +11,8 @@ import com.sparrowwallet.drongo.protocol.ScriptType;
|
|||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTParseException;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
import com.sparrowwallet.drongo.wallet.MnemonicException;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.control.*;
|
||||
import com.sparrowwallet.sparrow.event.*;
|
||||
|
@ -20,6 +22,10 @@ import com.sparrowwallet.sparrow.io.Storage;
|
|||
import com.sparrowwallet.sparrow.transaction.TransactionController;
|
||||
import com.sparrowwallet.sparrow.wallet.WalletController;
|
||||
import com.sparrowwallet.sparrow.wallet.WalletForm;
|
||||
import javafx.animation.Animation;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
|
@ -30,6 +36,8 @@ import javafx.scene.input.TransferMode;
|
|||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
import org.controlsfx.control.StatusBar;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
|
@ -52,11 +60,16 @@ public class AppController implements Initializable {
|
|||
@FXML
|
||||
private TabPane tabs;
|
||||
|
||||
@FXML
|
||||
private StatusBar statusBar;
|
||||
|
||||
private Timeline statusTimeline;
|
||||
|
||||
public static boolean showTxHexProperty;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
EventManager.get().register(this);
|
||||
}
|
||||
|
||||
void initializeView() {
|
||||
|
@ -234,12 +247,12 @@ public class AppController implements Initializable {
|
|||
File file = fileChooser.showOpenDialog(window);
|
||||
if(file != null) {
|
||||
try {
|
||||
Wallet wallet;
|
||||
CharSequence password = null;
|
||||
Storage storage = new Storage(file);
|
||||
FileType fileType = IOUtils.getFileType(file);
|
||||
if(FileType.JSON.equals(fileType)) {
|
||||
wallet = storage.loadWallet();
|
||||
Wallet wallet = storage.loadWallet();
|
||||
Tab tab = addWalletTab(storage, wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
} else if(FileType.BINARY.equals(fileType)) {
|
||||
WalletPasswordDialog dlg = new WalletPasswordDialog(WalletPasswordDialog.PasswordRequirement.LOAD);
|
||||
Optional<SecureString> optionalPassword = dlg.showAndWait();
|
||||
|
@ -247,18 +260,79 @@ public class AppController implements Initializable {
|
|||
return;
|
||||
}
|
||||
|
||||
password = optionalPassword.get();
|
||||
wallet = storage.loadWallet(password);
|
||||
SecureString password = optionalPassword.get();
|
||||
Storage.LoadWalletService loadWalletService = new Storage.LoadWalletService(storage, password);
|
||||
loadWalletService.setOnSucceeded(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Done"));
|
||||
Storage.WalletAndKey walletAndKey = loadWalletService.getValue();
|
||||
try {
|
||||
restorePublicKeysFromSeed(walletAndKey.wallet, walletAndKey.key);
|
||||
Tab tab = addWalletTab(storage, walletAndKey.wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
} catch(MnemonicException e) {
|
||||
showErrorDialog("Error Opening Wallet", e.getMessage());
|
||||
} finally {
|
||||
walletAndKey.key.clear();
|
||||
}
|
||||
});
|
||||
loadWalletService.setOnFailed(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Failed"));
|
||||
Throwable exception = loadWalletService.getException();
|
||||
if(exception instanceof InvalidPasswordException) {
|
||||
showErrorDialog("Invalid Password", "The wallet password was invalid.");
|
||||
} else {
|
||||
showErrorDialog("Error Opening Wallet", exception.getMessage());
|
||||
}
|
||||
});
|
||||
loadWalletService.start();
|
||||
EventManager.get().post(new TimedWorkerEvent("Decrypting wallet...", 1000));
|
||||
} else {
|
||||
throw new IOException("Unsupported file type");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
showErrorDialog("Error Opening Wallet", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tab tab = addWalletTab(storage, wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
} catch (InvalidPasswordException e) {
|
||||
showErrorDialog("Invalid Password", "The password was invalid.");
|
||||
} catch (Exception e) {
|
||||
showErrorDialog("Error opening wallet", e.getMessage());
|
||||
private void restorePublicKeysFromSeed(Wallet wallet, Key key) throws MnemonicException {
|
||||
if(wallet.containsSeeds()) {
|
||||
//Derive xpub and master fingerprint from seed, potentially with passphrase
|
||||
Wallet copy = wallet.copy();
|
||||
for(Keystore copyKeystore : copy.getKeystores()) {
|
||||
if(copyKeystore.hasSeed()) {
|
||||
if(copyKeystore.getSeed().needsPassphrase()) {
|
||||
KeystorePassphraseDialog passphraseDialog = new KeystorePassphraseDialog(copyKeystore);
|
||||
Optional<String> optionalPassphrase = passphraseDialog.showAndWait();
|
||||
if(optionalPassphrase.isPresent()) {
|
||||
copyKeystore.getSeed().setPassphrase(optionalPassphrase.get());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
copyKeystore.getSeed().setPassphrase("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(wallet.isEncrypted()) {
|
||||
if(key == null) {
|
||||
throw new IllegalStateException("Wallet was not encrypted, but seed is");
|
||||
}
|
||||
|
||||
copy.decrypt(key);
|
||||
}
|
||||
|
||||
for(int i = 0; i < wallet.getKeystores().size(); i++) {
|
||||
Keystore keystore = wallet.getKeystores().get(i);
|
||||
if(keystore.hasSeed()) {
|
||||
Keystore copyKeystore = copy.getKeystores().get(i);
|
||||
Keystore derivedKeystore = Keystore.fromSeed(copyKeystore.getSeed(), copyKeystore.getKeyDerivation().getDerivation());
|
||||
keystore.setKeyDerivation(derivedKeystore.getKeyDerivation());
|
||||
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
|
||||
keystore.getSeed().setPassphrase(copyKeystore.getSeed().getPassphrase());
|
||||
copyKeystore.getSeed().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +492,6 @@ public class AppController implements Initializable {
|
|||
@Subscribe
|
||||
public void tabSelected(TabSelectedEvent event) {
|
||||
Tab selectedTab = event.getTab();
|
||||
String tabType = (String)selectedTab.getUserData();
|
||||
|
||||
String tabName = selectedTab.getText();
|
||||
if(tabs.getScene() != null) {
|
||||
|
@ -426,4 +499,28 @@ public class AppController implements Initializable {
|
|||
tabStage.setTitle("Sparrow - " + tabName);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void timedWorker(TimedWorkerEvent event) {
|
||||
if(statusTimeline != null && statusTimeline.getStatus() == Animation.Status.RUNNING) {
|
||||
if(event.getTimeMills() == 0) {
|
||||
statusTimeline.stop();
|
||||
statusBar.setText("");
|
||||
statusBar.setProgress(0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
statusBar.setText(event.getStatus());
|
||||
statusTimeline = new Timeline(
|
||||
new KeyFrame(Duration.ZERO, new KeyValue(statusBar.progressProperty(), 0)),
|
||||
new KeyFrame(Duration.millis(event.getTimeMills()), e -> {
|
||||
statusBar.setText("");
|
||||
statusBar.setProgress(0);
|
||||
}, new KeyValue(statusBar.progressProperty(), 1))
|
||||
);
|
||||
statusTimeline.setCycleCount(1);
|
||||
statusTimeline.play();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package com.sparrowwallet.sparrow.control;
|
|||
import com.sparrowwallet.drongo.SecureString;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.event.TimedWorkerEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletExportEvent;
|
||||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
import com.sparrowwallet.sparrow.io.WalletExport;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
|
@ -55,22 +57,31 @@ public class FileWalletExportPane extends TitledDescriptionPane {
|
|||
WalletPasswordDialog dlg = new WalletPasswordDialog(WalletPasswordDialog.PasswordRequirement.LOAD);
|
||||
Optional<SecureString> password = dlg.showAndWait();
|
||||
if(password.isPresent()) {
|
||||
copy.decrypt(password.get());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(copy, password.get());
|
||||
decryptWalletService.setOnSucceeded(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Done"));
|
||||
Wallet decryptedWallet = decryptWalletService.getValue();
|
||||
try {
|
||||
OutputStream outputStream = new FileOutputStream(file);
|
||||
exporter.exportWallet(copy, outputStream);
|
||||
EventManager.get().post(new WalletExportEvent(copy));
|
||||
exporter.exportWallet(decryptedWallet, outputStream);
|
||||
EventManager.get().post(new WalletExportEvent(decryptedWallet));
|
||||
} catch(Exception e) {
|
||||
String errorMessage = e.getMessage();
|
||||
if(e.getCause() != null && e.getCause().getMessage() != null && !e.getCause().getMessage().isEmpty()) {
|
||||
errorMessage = e.getCause().getMessage();
|
||||
}
|
||||
setError("Export Error", errorMessage);
|
||||
} finally {
|
||||
decryptedWallet.clearPrivate();
|
||||
}
|
||||
});
|
||||
decryptWalletService.setOnFailed(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Failed"));
|
||||
setError("Export Error", decryptWalletService.getException().getMessage());
|
||||
});
|
||||
decryptWalletService.start();
|
||||
EventManager.get().post(new TimedWorkerEvent("Decrypting wallet...", 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
public class TimedWorkerEvent {
|
||||
private final String status;
|
||||
private final int timeMills;
|
||||
|
||||
public TimedWorkerEvent(String status) {
|
||||
this.status = status;
|
||||
this.timeMills = 0;
|
||||
}
|
||||
|
||||
public TimedWorkerEvent(String status, int timeMills) {
|
||||
this.status = status;
|
||||
this.timeMills = timeMills;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int getTimeMills() {
|
||||
return timeMills;
|
||||
}
|
||||
}
|
|
@ -2,12 +2,12 @@ package com.sparrowwallet.sparrow.io;
|
|||
|
||||
import com.google.gson.*;
|
||||
import com.sparrowwallet.drongo.ExtendedKey;
|
||||
import com.sparrowwallet.drongo.SecureString;
|
||||
import com.sparrowwallet.drongo.Utils;
|
||||
import com.sparrowwallet.drongo.crypto.*;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
import com.sparrowwallet.drongo.wallet.MnemonicException;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.control.KeystorePassphraseDialog;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
|
||||
|
@ -18,7 +18,6 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
import java.util.zip.*;
|
||||
|
||||
import static com.sparrowwallet.drongo.crypto.Argon2KeyDeriver.SPRW1_PARAMETERS;
|
||||
|
@ -68,12 +67,10 @@ public class Storage {
|
|||
Wallet wallet = gson.fromJson(reader, Wallet.class);
|
||||
reader.close();
|
||||
|
||||
restorePublicKeysFromSeed(wallet, null);
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public Wallet loadWallet(CharSequence password) throws IOException, MnemonicException, StorageException {
|
||||
public WalletAndKey loadWallet(CharSequence password) throws IOException, MnemonicException, StorageException {
|
||||
InputStream fileStream = new FileInputStream(walletFile);
|
||||
ECKey encryptionKey = getEncryptionKey(password, fileStream);
|
||||
|
||||
|
@ -83,52 +80,9 @@ public class Storage {
|
|||
reader.close();
|
||||
|
||||
Key key = new Key(encryptionKey.getPrivKeyBytes(), keyDeriver.getSalt(), EncryptionType.Deriver.ARGON2);
|
||||
restorePublicKeysFromSeed(wallet, key);
|
||||
|
||||
encryptionPubKey = ECKey.fromPublicOnly(encryptionKey);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
private void restorePublicKeysFromSeed(Wallet wallet, Key key) throws MnemonicException {
|
||||
if(wallet.containsSeeds()) {
|
||||
//Derive xpub and master fingerprint from seed, potentially with passphrase
|
||||
Wallet copy = wallet.copy();
|
||||
for(Keystore copyKeystore : copy.getKeystores()) {
|
||||
if(copyKeystore.hasSeed()) {
|
||||
if(copyKeystore.getSeed().needsPassphrase()) {
|
||||
KeystorePassphraseDialog passphraseDialog = new KeystorePassphraseDialog(copyKeystore);
|
||||
Optional<String> optionalPassphrase = passphraseDialog.showAndWait();
|
||||
if(optionalPassphrase.isPresent()) {
|
||||
copyKeystore.getSeed().setPassphrase(optionalPassphrase.get());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
copyKeystore.getSeed().setPassphrase("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(wallet.isEncrypted()) {
|
||||
if(key == null) {
|
||||
throw new IllegalStateException("Wallet was not encrypted, but seed is");
|
||||
}
|
||||
|
||||
copy.decrypt(key);
|
||||
}
|
||||
|
||||
for(int i = 0; i < wallet.getKeystores().size(); i++) {
|
||||
Keystore keystore = wallet.getKeystores().get(i);
|
||||
if(keystore.hasSeed()) {
|
||||
Keystore copyKeystore = copy.getKeystores().get(i);
|
||||
Keystore derivedKeystore = Keystore.fromSeed(copyKeystore.getSeed(), copyKeystore.getKeyDerivation().getDerivation());
|
||||
keystore.setKeyDerivation(derivedKeystore.getKeyDerivation());
|
||||
keystore.setExtendedPublicKey(derivedKeystore.getExtendedPublicKey());
|
||||
keystore.getSeed().setPassphrase(copyKeystore.getSeed().getPassphrase());
|
||||
copyKeystore.getSeed().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return new WalletAndKey(wallet, key);
|
||||
}
|
||||
|
||||
public void storeWallet(Wallet wallet) throws IOException {
|
||||
|
@ -316,11 +270,44 @@ public class Storage {
|
|||
}
|
||||
}
|
||||
|
||||
public static class WalletAndKey {
|
||||
public final Wallet wallet;
|
||||
public final Key key;
|
||||
|
||||
public WalletAndKey(Wallet wallet, Key key) {
|
||||
this.wallet = wallet;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LoadWalletService extends Service<WalletAndKey> {
|
||||
private final Storage storage;
|
||||
private final SecureString password;
|
||||
|
||||
public LoadWalletService(Storage storage, SecureString password) {
|
||||
this.storage = storage;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<WalletAndKey> createTask() {
|
||||
return new Task<>() {
|
||||
protected WalletAndKey call() throws IOException, StorageException, MnemonicException {
|
||||
try {
|
||||
return storage.loadWallet(password);
|
||||
} finally {
|
||||
password.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyDerivationService extends Service<ECKey> {
|
||||
private final Storage storage;
|
||||
private final String password;
|
||||
private final SecureString password;
|
||||
|
||||
public KeyDerivationService(Storage storage, String password) {
|
||||
public KeyDerivationService(Storage storage, SecureString password) {
|
||||
this.storage = storage;
|
||||
this.password = password;
|
||||
}
|
||||
|
@ -329,7 +316,35 @@ public class Storage {
|
|||
protected Task<ECKey> createTask() {
|
||||
return new Task<>() {
|
||||
protected ECKey call() throws IOException, StorageException {
|
||||
try {
|
||||
return storage.getEncryptionKey(password);
|
||||
} finally {
|
||||
password.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class DecryptWalletService extends Service<Wallet> {
|
||||
private final Wallet wallet;
|
||||
private final SecureString password;
|
||||
|
||||
public DecryptWalletService(Wallet wallet, SecureString password) {
|
||||
this.wallet = wallet;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<Wallet> createTask() {
|
||||
return new Task<>() {
|
||||
protected Wallet call() throws IOException, StorageException {
|
||||
try {
|
||||
wallet.decrypt(password);
|
||||
return wallet;
|
||||
} finally {
|
||||
password.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
|||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||
import com.sparrowwallet.sparrow.control.WalletPasswordDialog;
|
||||
import com.sparrowwallet.sparrow.event.SettingsChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.TimedWorkerEvent;
|
||||
import com.sparrowwallet.sparrow.event.WalletChangedEvent;
|
||||
import com.sparrowwallet.sparrow.io.Storage;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
@ -158,18 +159,9 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
});
|
||||
|
||||
apply.setOnAction(event -> {
|
||||
try {
|
||||
Optional<ECKey> optionalPubKey = requestEncryption(walletForm.getStorage().getEncryptionPubKey());
|
||||
if(optionalPubKey.isPresent()) {
|
||||
walletForm.getStorage().setEncryptionPubKey(optionalPubKey.get());
|
||||
walletForm.save();
|
||||
revert.setDisable(true);
|
||||
apply.setDisable(true);
|
||||
EventManager.get().post(new WalletChangedEvent(walletForm.getWallet(), walletForm.getWalletFile()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
AppController.showErrorDialog("Error saving file", e.getMessage());
|
||||
}
|
||||
saveWallet();
|
||||
});
|
||||
|
||||
setFieldsFromWallet(walletForm.getWallet());
|
||||
|
@ -256,7 +248,9 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
}
|
||||
}
|
||||
|
||||
private Optional<ECKey> requestEncryption(ECKey existingPubKey) {
|
||||
private void saveWallet() {
|
||||
ECKey existingPubKey = walletForm.getStorage().getEncryptionPubKey();
|
||||
|
||||
WalletPasswordDialog.PasswordRequirement requirement;
|
||||
if(existingPubKey == null) {
|
||||
requirement = WalletPasswordDialog.PasswordRequirement.UPDATE_NEW;
|
||||
|
@ -270,26 +264,58 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
Optional<SecureString> password = dlg.showAndWait();
|
||||
if(password.isPresent()) {
|
||||
if(password.get().length() == 0) {
|
||||
return Optional.of(Storage.NO_PASSWORD_KEY);
|
||||
try {
|
||||
walletForm.getStorage().setEncryptionPubKey(Storage.NO_PASSWORD_KEY);
|
||||
walletForm.save();
|
||||
EventManager.get().post(new WalletChangedEvent(walletForm.getWallet(), walletForm.getWalletFile()));
|
||||
} catch (IOException e) {
|
||||
AppController.showErrorDialog("Error saving wallet", e.getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
}
|
||||
} else {
|
||||
Storage.KeyDerivationService keyDerivationService = new Storage.KeyDerivationService(walletForm.getStorage(), password.get());
|
||||
keyDerivationService.setOnSucceeded(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Done"));
|
||||
ECKey encryptionFullKey = keyDerivationService.getValue();
|
||||
Key key = null;
|
||||
|
||||
try {
|
||||
ECKey encryptionFullKey = walletForm.getStorage().getEncryptionKey(password.get());
|
||||
ECKey encryptionPubKey = ECKey.fromPublicOnly(encryptionFullKey);
|
||||
|
||||
if(existingPubKey != null && !Storage.NO_PASSWORD_KEY.equals(existingPubKey) && !existingPubKey.equals(encryptionPubKey)) {
|
||||
AppController.showErrorDialog("Incorrect Password", "The password was incorrect.");
|
||||
return Optional.empty();
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Key key = new Key(encryptionFullKey.getPrivKeyBytes(), walletForm.getStorage().getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
||||
key = new Key(encryptionFullKey.getPrivKeyBytes(), walletForm.getStorage().getKeyDeriver().getSalt(), EncryptionType.Deriver.ARGON2);
|
||||
walletForm.getWallet().encrypt(key);
|
||||
return Optional.of(encryptionPubKey);
|
||||
} catch (Exception e) {
|
||||
AppController.showErrorDialog("Wallet File Invalid", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
walletForm.getStorage().setEncryptionPubKey(encryptionPubKey);
|
||||
walletForm.save();
|
||||
EventManager.get().post(new WalletChangedEvent(walletForm.getWallet(), walletForm.getWalletFile()));
|
||||
} catch (Exception e) {
|
||||
AppController.showErrorDialog("Error saving wallet", e.getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
} finally {
|
||||
encryptionFullKey.clear();
|
||||
if(key != null) {
|
||||
key.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
keyDerivationService.setOnFailed(workerStateEvent -> {
|
||||
EventManager.get().post(new TimedWorkerEvent("Failed"));
|
||||
AppController.showErrorDialog("Error saving wallet", keyDerivationService.getException().getMessage());
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(false);
|
||||
});
|
||||
keyDerivationService.start();
|
||||
EventManager.get().post(new TimedWorkerEvent("Encrypting wallet...", 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,6 @@
|
|||
<TabPane fx:id="tabs" />
|
||||
</StackPane>
|
||||
|
||||
<StatusBar text=""/>
|
||||
<StatusBar fx:id="statusBar" text=""/>
|
||||
</children>
|
||||
</VBox>
|
||||
|
|
Loading…
Reference in a new issue