@Test public void testChangePasswordRepeat() throws Exception { log.debug("Start of testChangePassword repeat"); assertThat(walletSummary.getWallet().checkPassword(PASSWORD)).isTrue(); WalletService.changeCurrentWalletPasswordInternal(PASSWORD, CHANGED_PASSWORD1); assertThat(walletSummary.getWallet().checkPassword(CHANGED_PASSWORD1)).isTrue(); WalletService.changeCurrentWalletPasswordInternal(CHANGED_PASSWORD1, CHANGED_PASSWORD2); assertThat(walletSummary.getWallet().checkPassword(CHANGED_PASSWORD2)).isTrue(); WalletService.changeCurrentWalletPasswordInternal(CHANGED_PASSWORD2, PASSWORD); assertThat(walletSummary.getWallet().checkPassword(PASSWORD)).isTrue(); WalletService.changeCurrentWalletPasswordInternal(PASSWORD, CHANGED_PASSWORD3); assertThat(walletSummary.getWallet().checkPassword(CHANGED_PASSWORD3)).isTrue(); }
static void changeCurrentWalletPasswordInternal(final String oldPassword, final String newPassword) { Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.getCurrentWalletSummary(); if (walletSummaryOptional == null || !walletSummaryOptional.isPresent() || walletSummaryOptional.get().getWallet() == null) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{"There is no wallet"})); return; } WalletSummary walletSummary = walletSummaryOptional.get(); Wallet wallet = walletSummary.getWallet(); WalletId walletId = walletSummary.getWalletId(); if (!wallet.checkPassword(oldPassword)) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_WRONG_OLD_PASSWORD, null)); return; } File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); Preconditions.checkState(WalletManager.INSTANCE.getCurrentWalletFile(applicationDataDirectory).isPresent()); File currentWalletSummaryFile = WalletManager.INSTANCE.getCurrentWalletSummaryFile(applicationDataDirectory).get(); List<EncryptedFileListItem> filesToChangePassword = createListOfFilesToChangePassword(applicationDataDirectory, walletId); for (File file : filesToChangePassword) { log.debug("File to change password on {}", file.getAbsolutePath()); } CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); BackupManager.INSTANCE.shutdownNow(); InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); try { byte[] encryptedOldBackupAESKey = walletSummary.getEncryptedBackupKey(); KeyParameter oldWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(oldPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] decryptedOldBackupAESKey = AESUtils.decrypt( encryptedOldBackupAESKey, oldWalletPasswordDerivedAESKey, walletSummary.getInitializationVector()); KeyParameter newWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(newPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] ivBytes = WalletManager.generateRandomIv(); byte[] encryptedNewBackupAESKey = AESUtils.encrypt( decryptedOldBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); byte[] decryptedRebornBackupAESKey = AESUtils.decrypt( encryptedNewBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); if (!Arrays.equals(decryptedOldBackupAESKey, decryptedRebornBackupAESKey)) { throw new IllegalStateException("The encryption of the backup AES key was not reversible. Aborting change of wallet credentials"); } byte[] newPasswordBytes = newPassword.getBytes(Charsets.UTF_8); byte[] paddedNewPassword = WalletManager.padPasswordBytes(newPasswordBytes); byte[] encryptedPaddedNewPassword = AESUtils.encrypt( paddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); byte[] decryptedRebornPaddedNewPassword = AESUtils.decrypt( encryptedPaddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); if (!Arrays.equals(newPasswordBytes, WalletManager.unpadPasswordBytes(decryptedRebornPaddedNewPassword))) { throw new IllegalStateException("The encryption of the new credentials was not reversible. Aborting change of wallet credentials"); } List<EncryptedFileListItem> newFiles = EncryptedFileReaderWriter.changeEncryptionPrepare(filesToChangePassword, oldPassword, newPassword); wallet.decrypt(oldPassword); walletSummary.setWalletPassword(new WalletPassword(newPassword, walletId)); walletSummary.setEncryptedPassword(encryptedPaddedNewPassword); wallet.encrypt(newPassword); walletSummary.setEncryptedBackupKey(encryptedNewBackupAESKey); walletSummary.setInitializationVector(ivBytes); WalletManager.updateWalletSummary(currentWalletSummaryFile, walletSummary); WalletManager.INSTANCE.setCurrentWalletSummary(walletSummary); WalletManager.INSTANCE.saveWallet(); EncryptedFileReaderWriter.changeEncryptionCommit(filesToChangePassword, newFiles); CoreServices.bootstrap(); CoreServices.getOrCreateBackupService(); CoreServices.getOrCreateWalletService(walletId); BitcoinNetworkService bitcoinNetworkService = CoreServices.getOrCreateBitcoinNetworkService(); CoreServices.getOrCreateContactService(new WalletPassword(newPassword, walletId)); bitcoinNetworkService.replayWallet( applicationDataDirectory, Optional.<DateTime>absent(), false, false ); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(true, CoreMessageKey.CHANGE_PASSWORD_SUCCESS, null)); } catch (RuntimeException | NoSuchAlgorithmException | IOException e) { log.error("Failed to change password", e); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{e.getMessage()})); } }
WalletService extends AbstractService { static void changeCurrentWalletPasswordInternal(final String oldPassword, final String newPassword) { Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.getCurrentWalletSummary(); if (walletSummaryOptional == null || !walletSummaryOptional.isPresent() || walletSummaryOptional.get().getWallet() == null) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{"There is no wallet"})); return; } WalletSummary walletSummary = walletSummaryOptional.get(); Wallet wallet = walletSummary.getWallet(); WalletId walletId = walletSummary.getWalletId(); if (!wallet.checkPassword(oldPassword)) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_WRONG_OLD_PASSWORD, null)); return; } File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); Preconditions.checkState(WalletManager.INSTANCE.getCurrentWalletFile(applicationDataDirectory).isPresent()); File currentWalletSummaryFile = WalletManager.INSTANCE.getCurrentWalletSummaryFile(applicationDataDirectory).get(); List<EncryptedFileListItem> filesToChangePassword = createListOfFilesToChangePassword(applicationDataDirectory, walletId); for (File file : filesToChangePassword) { log.debug("File to change password on {}", file.getAbsolutePath()); } CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); BackupManager.INSTANCE.shutdownNow(); InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); try { byte[] encryptedOldBackupAESKey = walletSummary.getEncryptedBackupKey(); KeyParameter oldWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(oldPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] decryptedOldBackupAESKey = AESUtils.decrypt( encryptedOldBackupAESKey, oldWalletPasswordDerivedAESKey, walletSummary.getInitializationVector()); KeyParameter newWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(newPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] ivBytes = WalletManager.generateRandomIv(); byte[] encryptedNewBackupAESKey = AESUtils.encrypt( decryptedOldBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); byte[] decryptedRebornBackupAESKey = AESUtils.decrypt( encryptedNewBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); if (!Arrays.equals(decryptedOldBackupAESKey, decryptedRebornBackupAESKey)) { throw new IllegalStateException("The encryption of the backup AES key was not reversible. Aborting change of wallet credentials"); } byte[] newPasswordBytes = newPassword.getBytes(Charsets.UTF_8); byte[] paddedNewPassword = WalletManager.padPasswordBytes(newPasswordBytes); byte[] encryptedPaddedNewPassword = AESUtils.encrypt( paddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); byte[] decryptedRebornPaddedNewPassword = AESUtils.decrypt( encryptedPaddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); if (!Arrays.equals(newPasswordBytes, WalletManager.unpadPasswordBytes(decryptedRebornPaddedNewPassword))) { throw new IllegalStateException("The encryption of the new credentials was not reversible. Aborting change of wallet credentials"); } List<EncryptedFileListItem> newFiles = EncryptedFileReaderWriter.changeEncryptionPrepare(filesToChangePassword, oldPassword, newPassword); wallet.decrypt(oldPassword); walletSummary.setWalletPassword(new WalletPassword(newPassword, walletId)); walletSummary.setEncryptedPassword(encryptedPaddedNewPassword); wallet.encrypt(newPassword); walletSummary.setEncryptedBackupKey(encryptedNewBackupAESKey); walletSummary.setInitializationVector(ivBytes); WalletManager.updateWalletSummary(currentWalletSummaryFile, walletSummary); WalletManager.INSTANCE.setCurrentWalletSummary(walletSummary); WalletManager.INSTANCE.saveWallet(); EncryptedFileReaderWriter.changeEncryptionCommit(filesToChangePassword, newFiles); CoreServices.bootstrap(); CoreServices.getOrCreateBackupService(); CoreServices.getOrCreateWalletService(walletId); BitcoinNetworkService bitcoinNetworkService = CoreServices.getOrCreateBitcoinNetworkService(); CoreServices.getOrCreateContactService(new WalletPassword(newPassword, walletId)); bitcoinNetworkService.replayWallet( applicationDataDirectory, Optional.<DateTime>absent(), false, false ); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(true, CoreMessageKey.CHANGE_PASSWORD_SUCCESS, null)); } catch (RuntimeException | NoSuchAlgorithmException | IOException e) { log.error("Failed to change password", e); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{e.getMessage()})); } } }
WalletService extends AbstractService { static void changeCurrentWalletPasswordInternal(final String oldPassword, final String newPassword) { Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.getCurrentWalletSummary(); if (walletSummaryOptional == null || !walletSummaryOptional.isPresent() || walletSummaryOptional.get().getWallet() == null) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{"There is no wallet"})); return; } WalletSummary walletSummary = walletSummaryOptional.get(); Wallet wallet = walletSummary.getWallet(); WalletId walletId = walletSummary.getWalletId(); if (!wallet.checkPassword(oldPassword)) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_WRONG_OLD_PASSWORD, null)); return; } File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); Preconditions.checkState(WalletManager.INSTANCE.getCurrentWalletFile(applicationDataDirectory).isPresent()); File currentWalletSummaryFile = WalletManager.INSTANCE.getCurrentWalletSummaryFile(applicationDataDirectory).get(); List<EncryptedFileListItem> filesToChangePassword = createListOfFilesToChangePassword(applicationDataDirectory, walletId); for (File file : filesToChangePassword) { log.debug("File to change password on {}", file.getAbsolutePath()); } CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); BackupManager.INSTANCE.shutdownNow(); InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); try { byte[] encryptedOldBackupAESKey = walletSummary.getEncryptedBackupKey(); KeyParameter oldWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(oldPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] decryptedOldBackupAESKey = AESUtils.decrypt( encryptedOldBackupAESKey, oldWalletPasswordDerivedAESKey, walletSummary.getInitializationVector()); KeyParameter newWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(newPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] ivBytes = WalletManager.generateRandomIv(); byte[] encryptedNewBackupAESKey = AESUtils.encrypt( decryptedOldBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); byte[] decryptedRebornBackupAESKey = AESUtils.decrypt( encryptedNewBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); if (!Arrays.equals(decryptedOldBackupAESKey, decryptedRebornBackupAESKey)) { throw new IllegalStateException("The encryption of the backup AES key was not reversible. Aborting change of wallet credentials"); } byte[] newPasswordBytes = newPassword.getBytes(Charsets.UTF_8); byte[] paddedNewPassword = WalletManager.padPasswordBytes(newPasswordBytes); byte[] encryptedPaddedNewPassword = AESUtils.encrypt( paddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); byte[] decryptedRebornPaddedNewPassword = AESUtils.decrypt( encryptedPaddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); if (!Arrays.equals(newPasswordBytes, WalletManager.unpadPasswordBytes(decryptedRebornPaddedNewPassword))) { throw new IllegalStateException("The encryption of the new credentials was not reversible. Aborting change of wallet credentials"); } List<EncryptedFileListItem> newFiles = EncryptedFileReaderWriter.changeEncryptionPrepare(filesToChangePassword, oldPassword, newPassword); wallet.decrypt(oldPassword); walletSummary.setWalletPassword(new WalletPassword(newPassword, walletId)); walletSummary.setEncryptedPassword(encryptedPaddedNewPassword); wallet.encrypt(newPassword); walletSummary.setEncryptedBackupKey(encryptedNewBackupAESKey); walletSummary.setInitializationVector(ivBytes); WalletManager.updateWalletSummary(currentWalletSummaryFile, walletSummary); WalletManager.INSTANCE.setCurrentWalletSummary(walletSummary); WalletManager.INSTANCE.saveWallet(); EncryptedFileReaderWriter.changeEncryptionCommit(filesToChangePassword, newFiles); CoreServices.bootstrap(); CoreServices.getOrCreateBackupService(); CoreServices.getOrCreateWalletService(walletId); BitcoinNetworkService bitcoinNetworkService = CoreServices.getOrCreateBitcoinNetworkService(); CoreServices.getOrCreateContactService(new WalletPassword(newPassword, walletId)); bitcoinNetworkService.replayWallet( applicationDataDirectory, Optional.<DateTime>absent(), false, false ); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(true, CoreMessageKey.CHANGE_PASSWORD_SUCCESS, null)); } catch (RuntimeException | NoSuchAlgorithmException | IOException e) { log.error("Failed to change password", e); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{e.getMessage()})); } } WalletService(NetworkParameters networkParameters); }
WalletService extends AbstractService { static void changeCurrentWalletPasswordInternal(final String oldPassword, final String newPassword) { Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.getCurrentWalletSummary(); if (walletSummaryOptional == null || !walletSummaryOptional.isPresent() || walletSummaryOptional.get().getWallet() == null) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{"There is no wallet"})); return; } WalletSummary walletSummary = walletSummaryOptional.get(); Wallet wallet = walletSummary.getWallet(); WalletId walletId = walletSummary.getWalletId(); if (!wallet.checkPassword(oldPassword)) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_WRONG_OLD_PASSWORD, null)); return; } File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); Preconditions.checkState(WalletManager.INSTANCE.getCurrentWalletFile(applicationDataDirectory).isPresent()); File currentWalletSummaryFile = WalletManager.INSTANCE.getCurrentWalletSummaryFile(applicationDataDirectory).get(); List<EncryptedFileListItem> filesToChangePassword = createListOfFilesToChangePassword(applicationDataDirectory, walletId); for (File file : filesToChangePassword) { log.debug("File to change password on {}", file.getAbsolutePath()); } CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); BackupManager.INSTANCE.shutdownNow(); InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); try { byte[] encryptedOldBackupAESKey = walletSummary.getEncryptedBackupKey(); KeyParameter oldWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(oldPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] decryptedOldBackupAESKey = AESUtils.decrypt( encryptedOldBackupAESKey, oldWalletPasswordDerivedAESKey, walletSummary.getInitializationVector()); KeyParameter newWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(newPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] ivBytes = WalletManager.generateRandomIv(); byte[] encryptedNewBackupAESKey = AESUtils.encrypt( decryptedOldBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); byte[] decryptedRebornBackupAESKey = AESUtils.decrypt( encryptedNewBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); if (!Arrays.equals(decryptedOldBackupAESKey, decryptedRebornBackupAESKey)) { throw new IllegalStateException("The encryption of the backup AES key was not reversible. Aborting change of wallet credentials"); } byte[] newPasswordBytes = newPassword.getBytes(Charsets.UTF_8); byte[] paddedNewPassword = WalletManager.padPasswordBytes(newPasswordBytes); byte[] encryptedPaddedNewPassword = AESUtils.encrypt( paddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); byte[] decryptedRebornPaddedNewPassword = AESUtils.decrypt( encryptedPaddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); if (!Arrays.equals(newPasswordBytes, WalletManager.unpadPasswordBytes(decryptedRebornPaddedNewPassword))) { throw new IllegalStateException("The encryption of the new credentials was not reversible. Aborting change of wallet credentials"); } List<EncryptedFileListItem> newFiles = EncryptedFileReaderWriter.changeEncryptionPrepare(filesToChangePassword, oldPassword, newPassword); wallet.decrypt(oldPassword); walletSummary.setWalletPassword(new WalletPassword(newPassword, walletId)); walletSummary.setEncryptedPassword(encryptedPaddedNewPassword); wallet.encrypt(newPassword); walletSummary.setEncryptedBackupKey(encryptedNewBackupAESKey); walletSummary.setInitializationVector(ivBytes); WalletManager.updateWalletSummary(currentWalletSummaryFile, walletSummary); WalletManager.INSTANCE.setCurrentWalletSummary(walletSummary); WalletManager.INSTANCE.saveWallet(); EncryptedFileReaderWriter.changeEncryptionCommit(filesToChangePassword, newFiles); CoreServices.bootstrap(); CoreServices.getOrCreateBackupService(); CoreServices.getOrCreateWalletService(walletId); BitcoinNetworkService bitcoinNetworkService = CoreServices.getOrCreateBitcoinNetworkService(); CoreServices.getOrCreateContactService(new WalletPassword(newPassword, walletId)); bitcoinNetworkService.replayWallet( applicationDataDirectory, Optional.<DateTime>absent(), false, false ); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(true, CoreMessageKey.CHANGE_PASSWORD_SUCCESS, null)); } catch (RuntimeException | NoSuchAlgorithmException | IOException e) { log.error("Failed to change password", e); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{e.getMessage()})); } } WalletService(NetworkParameters networkParameters); void initialise(File applicationDataDirectory, WalletId walletId, CharSequence password); Set<PaymentData> getPaymentDataSet(); int getPaymentDataSetSize(); List<PaymentData> subsetPaymentsAndSort(Set<PaymentData> paymentDataSet, PaymentType subsettingPaymentType); @SuppressFBWarnings({"ITC_INHERITANCE_TYPE_CHECKING"}) List<PaymentData> filterPaymentsByContent(String query); TransactionData adaptTransaction(Wallet wallet, Transaction transaction, Map<UUID, Protos.PaymentDetails> unmatchedPaymentDetailsMap); static PaymentStatus calculateStatus(TransactionConfidence.ConfidenceType confidenceType, int depth, int numberOfPeers); static FiatPayment calculateFiatPaymentEquivalent(Coin amountBTC); void readPayments(CharSequence password); void writePayments(CharSequence password); WalletId getWalletId(); void addMBHDPaymentRequestData(MBHDPaymentRequestData MBHDPaymentRequestData); void addPaymentRequestData(PaymentRequestData paymentRequestData); void addTransactionInfo(TransactionInfo transactionInfo); TransactionInfo getTransactionInfoByHash(String transactionHashAsString); Optional<PaymentRequestData> getPaymentRequestDataByHash(String transactionHashAsString); TransactionData getTransactionDataByHash(String transactionHashAsString); List<MBHDPaymentRequestData> getMBHDPaymentRequestDataList(); List<PaymentRequestData> getPaymentRequestDataList(); String generateNextReceivingAddress(Optional<CharSequence> walletPasswordOptional); String getLastGeneratedReceivingAddress(); Optional<Integer> getGap(); List<MBHDPaymentRequestData> findPaymentRequestsThisTransactionFunds(TransactionData transactionData); void deleteMBHDPaymentRequest(MBHDPaymentRequestData mbhdPaymentRequestData); void deletePaymentRequest(PaymentRequestData paymentRequestData); @SuppressFBWarnings({"ITC_INHERITANCE_TYPE_CHECKING"}) void undoDeletePaymentData(); boolean canUndo(); void exportPayments(
          File exportDirectory,
          String transactionFileStem,
          String mbhdPaymentRequestFileStem,
          String paymentRequestFileStem,
          CSVEntryConverter<TransactionData> transactionHeaderConverter,
          CSVEntryConverter<TransactionData> transactionConverter,
          CSVEntryConverter<MBHDPaymentRequestData> mbhdPaymentRequestHeaderConverter,
          CSVEntryConverter<MBHDPaymentRequestData> mbhdPaymentRequestConverter,
          CSVEntryConverter<PaymentRequestData> paymentRequestHeaderConverter,
          CSVEntryConverter<PaymentRequestData> paymentRequestConverter

  ); static void changeCurrentWalletPassword(final String oldPassword, final String newPassword); @Subscribe void onTransactionSeenEvent(TransactionSeenEvent transactionSeenEvent); File getPaymentDatabaseFile(); }
WalletService extends AbstractService { static void changeCurrentWalletPasswordInternal(final String oldPassword, final String newPassword) { Optional<WalletSummary> walletSummaryOptional = WalletManager.INSTANCE.getCurrentWalletSummary(); if (walletSummaryOptional == null || !walletSummaryOptional.isPresent() || walletSummaryOptional.get().getWallet() == null) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{"There is no wallet"})); return; } WalletSummary walletSummary = walletSummaryOptional.get(); Wallet wallet = walletSummary.getWallet(); WalletId walletId = walletSummary.getWalletId(); if (!wallet.checkPassword(oldPassword)) { CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_WRONG_OLD_PASSWORD, null)); return; } File applicationDataDirectory = InstallationManager.getOrCreateApplicationDataDirectory(); Preconditions.checkState(WalletManager.INSTANCE.getCurrentWalletFile(applicationDataDirectory).isPresent()); File currentWalletSummaryFile = WalletManager.INSTANCE.getCurrentWalletSummaryFile(applicationDataDirectory).get(); List<EncryptedFileListItem> filesToChangePassword = createListOfFilesToChangePassword(applicationDataDirectory, walletId); for (File file : filesToChangePassword) { log.debug("File to change password on {}", file.getAbsolutePath()); } CoreServices.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); WalletManager.INSTANCE.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); BackupManager.INSTANCE.shutdownNow(); InstallationManager.shutdownNow(ShutdownEvent.ShutdownType.SWITCH); try { byte[] encryptedOldBackupAESKey = walletSummary.getEncryptedBackupKey(); KeyParameter oldWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(oldPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] decryptedOldBackupAESKey = AESUtils.decrypt( encryptedOldBackupAESKey, oldWalletPasswordDerivedAESKey, walletSummary.getInitializationVector()); KeyParameter newWalletPasswordDerivedAESKey = org.multibit.commons.crypto.AESUtils.createAESKey(newPassword.getBytes(Charsets.UTF_8), WalletManager.scryptSalt()); byte[] ivBytes = WalletManager.generateRandomIv(); byte[] encryptedNewBackupAESKey = AESUtils.encrypt( decryptedOldBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); byte[] decryptedRebornBackupAESKey = AESUtils.decrypt( encryptedNewBackupAESKey, newWalletPasswordDerivedAESKey, ivBytes); if (!Arrays.equals(decryptedOldBackupAESKey, decryptedRebornBackupAESKey)) { throw new IllegalStateException("The encryption of the backup AES key was not reversible. Aborting change of wallet credentials"); } byte[] newPasswordBytes = newPassword.getBytes(Charsets.UTF_8); byte[] paddedNewPassword = WalletManager.padPasswordBytes(newPasswordBytes); byte[] encryptedPaddedNewPassword = AESUtils.encrypt( paddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); byte[] decryptedRebornPaddedNewPassword = AESUtils.decrypt( encryptedPaddedNewPassword, new KeyParameter(decryptedOldBackupAESKey), ivBytes); if (!Arrays.equals(newPasswordBytes, WalletManager.unpadPasswordBytes(decryptedRebornPaddedNewPassword))) { throw new IllegalStateException("The encryption of the new credentials was not reversible. Aborting change of wallet credentials"); } List<EncryptedFileListItem> newFiles = EncryptedFileReaderWriter.changeEncryptionPrepare(filesToChangePassword, oldPassword, newPassword); wallet.decrypt(oldPassword); walletSummary.setWalletPassword(new WalletPassword(newPassword, walletId)); walletSummary.setEncryptedPassword(encryptedPaddedNewPassword); wallet.encrypt(newPassword); walletSummary.setEncryptedBackupKey(encryptedNewBackupAESKey); walletSummary.setInitializationVector(ivBytes); WalletManager.updateWalletSummary(currentWalletSummaryFile, walletSummary); WalletManager.INSTANCE.setCurrentWalletSummary(walletSummary); WalletManager.INSTANCE.saveWallet(); EncryptedFileReaderWriter.changeEncryptionCommit(filesToChangePassword, newFiles); CoreServices.bootstrap(); CoreServices.getOrCreateBackupService(); CoreServices.getOrCreateWalletService(walletId); BitcoinNetworkService bitcoinNetworkService = CoreServices.getOrCreateBitcoinNetworkService(); CoreServices.getOrCreateContactService(new WalletPassword(newPassword, walletId)); bitcoinNetworkService.replayWallet( applicationDataDirectory, Optional.<DateTime>absent(), false, false ); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(true, CoreMessageKey.CHANGE_PASSWORD_SUCCESS, null)); } catch (RuntimeException | NoSuchAlgorithmException | IOException e) { log.error("Failed to change password", e); CoreEvents.fireChangePasswordResultEvent(new ChangePasswordResultEvent(false, CoreMessageKey.CHANGE_PASSWORD_ERROR, new Object[]{e.getMessage()})); } } WalletService(NetworkParameters networkParameters); void initialise(File applicationDataDirectory, WalletId walletId, CharSequence password); Set<PaymentData> getPaymentDataSet(); int getPaymentDataSetSize(); List<PaymentData> subsetPaymentsAndSort(Set<PaymentData> paymentDataSet, PaymentType subsettingPaymentType); @SuppressFBWarnings({"ITC_INHERITANCE_TYPE_CHECKING"}) List<PaymentData> filterPaymentsByContent(String query); TransactionData adaptTransaction(Wallet wallet, Transaction transaction, Map<UUID, Protos.PaymentDetails> unmatchedPaymentDetailsMap); static PaymentStatus calculateStatus(TransactionConfidence.ConfidenceType confidenceType, int depth, int numberOfPeers); static FiatPayment calculateFiatPaymentEquivalent(Coin amountBTC); void readPayments(CharSequence password); void writePayments(CharSequence password); WalletId getWalletId(); void addMBHDPaymentRequestData(MBHDPaymentRequestData MBHDPaymentRequestData); void addPaymentRequestData(PaymentRequestData paymentRequestData); void addTransactionInfo(TransactionInfo transactionInfo); TransactionInfo getTransactionInfoByHash(String transactionHashAsString); Optional<PaymentRequestData> getPaymentRequestDataByHash(String transactionHashAsString); TransactionData getTransactionDataByHash(String transactionHashAsString); List<MBHDPaymentRequestData> getMBHDPaymentRequestDataList(); List<PaymentRequestData> getPaymentRequestDataList(); String generateNextReceivingAddress(Optional<CharSequence> walletPasswordOptional); String getLastGeneratedReceivingAddress(); Optional<Integer> getGap(); List<MBHDPaymentRequestData> findPaymentRequestsThisTransactionFunds(TransactionData transactionData); void deleteMBHDPaymentRequest(MBHDPaymentRequestData mbhdPaymentRequestData); void deletePaymentRequest(PaymentRequestData paymentRequestData); @SuppressFBWarnings({"ITC_INHERITANCE_TYPE_CHECKING"}) void undoDeletePaymentData(); boolean canUndo(); void exportPayments(
          File exportDirectory,
          String transactionFileStem,
          String mbhdPaymentRequestFileStem,
          String paymentRequestFileStem,
          CSVEntryConverter<TransactionData> transactionHeaderConverter,
          CSVEntryConverter<TransactionData> transactionConverter,
          CSVEntryConverter<MBHDPaymentRequestData> mbhdPaymentRequestHeaderConverter,
          CSVEntryConverter<MBHDPaymentRequestData> mbhdPaymentRequestConverter,
          CSVEntryConverter<PaymentRequestData> paymentRequestHeaderConverter,
          CSVEntryConverter<PaymentRequestData> paymentRequestConverter

  ); static void changeCurrentWalletPassword(final String oldPassword, final String newPassword); @Subscribe void onTransactionSeenEvent(TransactionSeenEvent transactionSeenEvent); File getPaymentDatabaseFile(); final static String PAYMENTS_DIRECTORY_NAME; static final String PAYMENTS_DATABASE_NAME; static final String PREFIX_SEPARATOR; static final String BIP70_PAYMENT_REQUEST_DIRECTORY; static final String BIP70_PAYMENT_REQUEST_SUFFIX; static final String BIP70_PAYMENT_SUFFIX; static final String BIP70_PAYMENT_ACK_SUFFIX; static final int GAP_LIMIT; }