/** * Work out which restore method to use, depending on if it is a Trezor wallet or not and what * backups there are */ public void calculateRestoreMethod() { Optional<HardwareWalletService> hardwareWalletService = CoreServices.getOrCreateHardwareWalletService(); // User has selected restore wallet - see if wallet is hard Trezor wallet // If so no need to enter a seed phrase - use the rootNode from the master public key to work // out the wallet id HardwareWalletContext context = hardwareWalletService.get().getContext(); // Create a wallet id from the rootNode to work out the wallet root directory if (context.getDeterministicKey().isPresent()) { walletId = Optional.of(new WalletId(context.getDeterministicKey().get().getIdentifier())); String walletRoot = WalletManager.createWalletRoot(walletId.get()); log.debug("Hardware wallet root : {}", walletRoot); } // Ensure Trezor is cancelled hardwareWalletService.get().requestCancel(); restoreMethod = RESTORE_WALLET_HARD_TREZOR; if (!isLocalZipBackupPresent()) { // Next ask for the cloud backup location state = RESTORE_WALLET_SELECT_BACKUP_LOCATION; } else { // Next select one of the local backups state = RESTORE_WALLET_SELECT_BACKUP; } }
/** * Create a Trezor hard wallet from a backup summary, decrypting it with a password created from * the Trezor supplied entropy */ private boolean createTrezorHardWallet() { // Get the model that contains the selected wallet backup to use SelectBackupSummaryModel selectedBackupSummaryModel = getWizardModel().getSelectBackupSummaryModel(); if (selectedBackupSummaryModel == null || selectedBackupSummaryModel.getValue() == null || selectedBackupSummaryModel.getValue().getFile() == null) { log.debug("No wallet backup to use from the model"); return false; } log.debug( "Loading hard wallet backup '" + selectedBackupSummaryModel.getValue().getFile() + "'"); try { // For Trezor hard wallets the backups are encrypted with the entropy derived password String walletPassword = null; Optional<HardwareWalletService> hardwareWalletService = CoreServices.getOrCreateHardwareWalletService(); if (hardwareWalletService.isPresent() && hardwareWalletService.get().getContext().getEntropy().isPresent()) { walletPassword = Hex.toHexString(hardwareWalletService.get().getContext().getEntropy().get()); } // Check there is a wallet password - if not then cannot decrypt backup if (walletPassword == null) { log.debug( "Cannot work out the password to decrypt the backup - there is no entropy from the Trezor"); return false; } KeyParameter backupAESKey = AESUtils.createAESKey( walletPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); WalletId loadedWalletId = BackupManager.INSTANCE.loadZipBackup( selectedBackupSummaryModel.getValue().getFile(), backupAESKey); // Attempt to open the wallet final Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.openWalletFromWalletId( InstallationManager.getOrCreateApplicationDataDirectory(), loadedWalletId, walletPassword); // If the wallet is present then it was opened successfully return walletSummaryOptional.isPresent(); } catch (Exception e) { log.error("Failed to restore Trezor hard wallet.", e); } // Must have failed to be here return false; }
/** Create a wallet from a seed phrase and a backup summary (chosen by the user) */ private boolean createWalletFromSeedPhrase(List<String> seedPhrase) { if (!verifySeedPhrase(seedPhrase)) { return false; } // Get the model that contains the selected wallet backup to use SelectBackupSummaryModel selectedBackupSummaryModel = getWizardModel().getSelectBackupSummaryModel(); if (selectedBackupSummaryModel == null || selectedBackupSummaryModel.getValue() == null || selectedBackupSummaryModel.getValue().getFile() == null) { log.debug("No wallet backup to use from the model"); return false; } log.debug( "Loading soft wallet backup '" + selectedBackupSummaryModel.getValue().getFile() + "'"); try { WalletId loadedWalletId = BackupManager.INSTANCE.loadZipBackup( selectedBackupSummaryModel.getValue().getFile(), seedPhrase); // Locate the installation directory File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); // Work out what the wallet credentials was from the encrypted value stored in the // WalletSummary SeedPhraseGenerator seedPhraseGenerator = new Bip39SeedPhraseGenerator(); byte[] seed = seedPhraseGenerator.convertToSeed(seedPhrase); String walletRoot = applicationDataDirectory.getAbsolutePath() + File.separator + WalletManager.createWalletRoot(loadedWalletId); WalletSummary walletSummary = WalletManager.getOrCreateWalletSummary(new File(walletRoot), loadedWalletId); KeyParameter backupAESKey = AESUtils.createAESKey(seed, WalletManager.scryptSalt()); byte[] decryptedPaddedWalletPasswordBytes = org.multibit.commons.crypto.AESUtils.decrypt( walletSummary.getEncryptedPassword(), backupAESKey, WalletManager.aesInitialisationVector()); byte[] decryptedWalletPasswordBytes = WalletManager.unpadPasswordBytes(decryptedPaddedWalletPasswordBytes); String decryptedWalletPassword = new String(decryptedWalletPasswordBytes, "UTF8"); // Attempt to open the wallet final Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.openWalletFromWalletId( InstallationManager.getOrCreateApplicationDataDirectory(), loadedWalletId, decryptedWalletPassword); // If the wallet is present then it was opened successfully return walletSummaryOptional.isPresent(); } catch (Exception e) { log.error("Failed to restore wallet from seed phrase.", e); } // Must have failed to be here return false; }