ExportPrivateKeysSubmitAction extends MultiBitSubmitAction implements WalletBusyListener { @Override public void actionPerformed(ActionEvent e) { if (abort()) { return; } exportPrivateKeysPanel.clearMessages(); if (super.bitcoinController.getModel().getActiveWallet() != null && super.bitcoinController.getModel().getActiveWallet().getEncryptionType() == EncryptionType.ENCRYPTED_SCRYPT_AES) { if (walletPassword.getPassword() == null || walletPassword.getPassword().length == 0) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "showExportPrivateKeysAction.youMustEnterTheWalletPassword")); return; } try { if (!super.bitcoinController.getModel().getActiveWallet().checkPassword(CharBuffer.wrap(walletPassword.getPassword()))) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "createNewReceivingAddressSubmitAction.passwordIsIncorrect")); exportPrivateKeysPanel.setMessage2(" "); return; } } catch (KeyCrypterException kce) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "createNewReceivingAddressSubmitAction.passwordIsIncorrect")); exportPrivateKeysPanel.setMessage2(" "); } } String exportPrivateKeysFilename = exportPrivateKeysPanel.getOutputFilename(); if (exportPrivateKeysFilename == null || "".equals(exportPrivateKeysFilename)) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "showExportPrivateKeysAction.youMustSelectAnOutputFile")); return; } File exportPrivateKeysFile = new File(exportPrivateKeysFilename); privateKeysHandler = new PrivateKeysHandler(super.bitcoinController.getModel().getNetworkParameters()); boolean performEncryptionOfExportFile = false; CharSequence exportPasswordToUse = null; if (exportPrivateKeysPanel.requiresEncryption()) { if (exportFilePassword.getPassword() == null || exportFilePassword.getPassword().length == 0) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser() .getString("showExportPrivateKeysAction.enterPasswords")); return; } else { if (!Arrays.areEqual(exportFilePassword.getPassword(), exportFileRepeatPassword.getPassword())) { exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "showExportPrivateKeysAction.passwordsAreDifferent")); return; } else { performEncryptionOfExportFile = true; exportPasswordToUse = CharBuffer.wrap(exportFilePassword.getPassword()); } } } if (exportPrivateKeysFile.exists()) { String yesText = controller.getLocaliser().getString("showOpenUriView.yesText"); String noText = controller.getLocaliser().getString("showOpenUriView.noText"); String questionText = controller.getLocaliser().getString("showExportPrivateKeysAction.thisFileExistsOverwrite", new Object[] { exportPrivateKeysFile.getName() }); String questionTitle = controller.getLocaliser().getString("showExportPrivateKeysAction.thisFileExistsOverwriteTitle"); int selection = JOptionPane.showOptionDialog(mainFrame, questionText, questionTitle, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, ImageLoader.createImageIcon(ImageLoader.QUESTION_MARK_ICON_FILE), new String[] { yesText, noText }, noText); if (selection != JOptionPane.YES_OPTION) { return; } } WalletData perWalletModelData = super.bitcoinController.getModel().getActivePerWalletModelData(); if (!perWalletModelData.isBusy()) { perWalletModelData.setBusy(true); perWalletModelData.setBusyTaskKey("showExportPrivateKeysAction.text.camel"); exportPrivateKeysPanel.setMessage1(controller.getLocaliser().getString( "exportPrivateKeysSubmitAction.exportingPrivateKeys")); exportPrivateKeysPanel.setMessage2(""); super.bitcoinController.fireWalletBusyChange(true); CharSequence walletPasswordToUse = null; if (walletPassword.getPassword() != null) { walletPasswordToUse = CharBuffer.wrap(walletPassword.getPassword()); } exportPrivateKeysInBackground(exportPrivateKeysFile, performEncryptionOfExportFile, exportPasswordToUse, walletPasswordToUse); } } ExportPrivateKeysSubmitAction(BitcoinController bitcoinController, ExportPrivateKeysPanel exportPrivateKeysPanel,
            ImageIcon icon, JPasswordField walletPassword, JPasswordField exportFilePassword, JPasswordField exportFileRepeatPassword, MultiBitFrame mainFrame); @Override void actionPerformed(ActionEvent e); @Override void walletBusyChange(boolean newWalletIsBusy);  }
@Test public void testExportPrivateKeysWithNonEncryptedWallet() throws Exception { final CreateControllers.Controllers controllers = CreateControllers.createControllers(); BitcoinController controller = controllers.bitcoinController; ActionTestUtils.createNewActiveWallet(controller, "testExportPrivateKeysWithNonEncryptedWallet", false, null); SimpleWalletBusyListener walletBusyListener = new SimpleWalletBusyListener(); controller.registerWalletBusyListener(walletBusyListener); FontSizer.INSTANCE.initialise(controller); ExportPrivateKeysPanel exportPanel = new ExportPrivateKeysPanel(controller, null); ExportPrivateKeysSubmitAction exportAction = exportPanel.getExportPrivateKeySubmitAction(); assertNotNull("exportAction was not created successfully", exportAction); assertEquals("Wrong number of keys at wallet creation", 1, controller.getModel().getActiveWallet().getKeychain().size()); assertTrue("Wallet password is enabled when it should not be", !exportPanel.isWalletPasswordFieldEnabled()); exportAction.actionPerformed(null); assertEquals("Wrong message1 after default export execute", EXPECTED_YOU_MUST_SELECT_AN_OUTPUT_FILE, exportPanel.getMessageText1()); assertEquals("Wrong message2 after default export execute", "", exportPanel.getMessageText2().trim()); String outputFilename1 = controller.getModel().getActiveWalletFilename() + "-" + UUID.randomUUID().toString() + ".key"; exportPanel.setOutputFilename(outputFilename1); exportAction.actionPerformed(null); assertEquals("Wrong message1 after no password set execute", EXPECTED_ENTER_THE_EXPORT_FILE_PASSWORD, exportPanel.getMessageText1()); assertEquals("Wrong message2 after no password set execute", "", exportPanel.getMessageText2().trim()); exportPanel.setExportPassword(EXPORT_FILE_PASSWORD); exportAction.actionPerformed(null); assertEquals("Wrong message1 after no password set execute", EXPECTED_PASSWORDS_DO_NOT_MATCH, exportPanel.getMessageText1()); assertEquals("Wrong message2 after no password set execute", "", exportPanel.getMessageText2().trim()); exportPanel.setRepeatExportPassword(EXPORT_FILE_PASSWORD); assertTrue("Encrypted export file exists when it should not", !(new File(outputFilename1)).exists()); exportAction.actionPerformed(null); BitcoinControllerTest.waitForWalletNotBusy(walletBusyListener); assertTrue("Encrypted export file does not exist when it should", (new File(outputFilename1)).exists()); assertEquals("Wrong message1 after encrypted export is good to go", EXPECTED_THE_PRIVATE_KEYS_WERE_EXPORTED, exportPanel.getMessageText1()); assertEquals("Wrong message2 after encrypted export is good to go", EXPECTED_THE_EXPORT_FILE_COULD_BE_READ_IN_CORRECTLY, exportPanel.getMessageText2().trim()); PrivateKeysHandler privateKeysHandler = new PrivateKeysHandler(controller.getModel().getNetworkParameters()); Collection<PrivateKeyAndDate> privateKeyAndDates = null; try { privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), null); fail("An encrypted export file was read in with no password. Fail."); } catch (KeyCrypterException kce) { assertTrue("Unexpected exception thrown when decoding export file with no password", kce.getMessage().indexOf(EXPECTED_COULD_NOT_DECRYPT_INPUT_STRING) > -1); } try { privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), WRONG_PASSWORD); fail("An encrypted export file was read in with the wrong password. Fail."); } catch (KeyCrypterException kce) { assertTrue("Unexpected exception thrown when decoding export file with wrong password", kce.getMessage().indexOf(EXPECTED_COULD_NOT_DECRYPT_INPUT_STRING) > -1); } privateKeysHandler = new PrivateKeysHandler(controller.getModel().getNetworkParameters()); privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), EXPORT_FILE_PASSWORD); assertEquals("Wrong number of keys read in from encrypted export file", 1, privateKeyAndDates.size()); assertEquals("Wrong private key read in from encrypted export file", Utils.bytesToHexString(controller.getModel().getActiveWallet().getKeychain().iterator().next().getPrivKeyBytes()), Utils.bytesToHexString(privateKeyAndDates.iterator().next().getKey().getPrivKeyBytes())); exportPanel.getDoNotPasswordProtect().setSelected(true); String outputFilename2 = controller.getModel().getActiveWalletFilename() + "-" + UUID.randomUUID().toString() + ".key"; exportPanel.setOutputFilename(outputFilename2); assertTrue("Unencrypted export file exists when it should not", !(new File(outputFilename2)).exists()); exportAction.actionPerformed(null); BitcoinControllerTest.waitForWalletNotBusy(walletBusyListener); assertTrue("Unencrypted export file does not exist when it should", (new File(outputFilename2)).exists()); assertEquals("Wrong message1 after unencrypted export is good to go", EXPECTED_THE_PRIVATE_KEYS_WERE_EXPORTED, exportPanel.getMessageText1()); assertEquals("Wrong message2 after unencrypted export is good to go", EXPECTED_THE_EXPORT_FILE_COULD_BE_READ_IN_CORRECTLY, exportPanel.getMessageText2().trim()); privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename2), null); assertEquals("Wrong number of keys read in from unencrypted export file", 1, privateKeyAndDates.size()); assertEquals("Wrong private key read in from unencrypted export file", Utils.bytesToHexString(controller.getModel().getActiveWallet().getKeychain().iterator().next().getPrivKeyBytes()), Utils.bytesToHexString(privateKeyAndDates.iterator().next().getKey().getPrivKeyBytes())); }
@Test public void testExportPrivateKeysWithEncryptedWallet() throws Exception { final CreateControllers.Controllers controllers = CreateControllers.createControllers(); BitcoinController controller = controllers.bitcoinController; ActionTestUtils.createNewActiveWallet(controller, "testExportPrivateKeysWithEncryptedWallet", true, WALLET_PASSWORD); SimpleWalletBusyListener walletBusyListener = new SimpleWalletBusyListener(); controller.registerWalletBusyListener(walletBusyListener); EncryptedPrivateKey encryptedPrivateKey = controller.getModel().getActiveWallet().getKeychain().get(0).getEncryptedPrivateKey(); KeyCrypter keyCrypter = controller.getModel().getActiveWallet().getKeyCrypter(); byte[] originalPrivateKeyBytes = keyCrypter.decrypt(encryptedPrivateKey, keyCrypter.deriveKey(WALLET_PASSWORD)); FontSizer.INSTANCE.initialise(controller); ExportPrivateKeysPanel exportPanel = new ExportPrivateKeysPanel(controller, null); ExportPrivateKeysSubmitAction exportAction = exportPanel.getExportPrivateKeySubmitAction(); assertNotNull("exportAction was not created successfully", exportAction); assertEquals("Wrong number of keys at wallet creation", 1, controller.getModel().getActiveWallet().getKeychain().size()); assertTrue("Wallet password is not enabled when it should be", exportPanel.isWalletPasswordFieldEnabled()); exportAction.actionPerformed(null); assertEquals("Wrong message1 after default export execute", EXPECTED_ENTER_THE_WALLET_PASSWORD, exportPanel.getMessageText1()); assertEquals("Wrong message2 after default export execute", "", exportPanel.getMessageText2().trim()); exportPanel.setWalletPassword(WALLET_PASSWORD); exportAction.actionPerformed(null); assertEquals("Wrong message1 after password set execute", EXPECTED_YOU_MUST_SELECT_AN_OUTPUT_FILE, exportPanel.getMessageText1()); assertEquals("Wrong message2 after password set execute", "", exportPanel.getMessageText2().trim()); String outputFilename1 = controller.getModel().getActiveWalletFilename() + "-" + UUID.randomUUID().toString() + ".key"; exportPanel.setOutputFilename(outputFilename1); exportAction.actionPerformed(null); assertEquals("Wrong message1 after no password set execute", EXPECTED_ENTER_THE_EXPORT_FILE_PASSWORD, exportPanel.getMessageText1()); assertEquals("Wrong message2 after no password set execute", "", exportPanel.getMessageText2().trim()); exportPanel.setExportPassword(EXPORT_FILE_PASSWORD); exportAction.actionPerformed(null); assertEquals("Wrong message1 after no password set execute", EXPECTED_PASSWORDS_DO_NOT_MATCH, exportPanel.getMessageText1()); assertEquals("Wrong message2 after no password set execute", "", exportPanel.getMessageText2().trim()); exportPanel.setRepeatExportPassword(EXPORT_FILE_PASSWORD); assertTrue("Encrypted export file exists when it should not", !(new File(outputFilename1)).exists()); exportAction.actionPerformed(null); BitcoinControllerTest.waitForWalletNotBusy(walletBusyListener); assertTrue("Encrypted export file does not exist when it should", (new File(outputFilename1)).exists()); assertEquals("Wrong message1 after encrypted export is good to go", EXPECTED_THE_PRIVATE_KEYS_WERE_EXPORTED, exportPanel.getMessageText1()); assertEquals("Wrong message2 after encrypted export is good to go", EXPECTED_THE_EXPORT_FILE_COULD_BE_READ_IN_CORRECTLY, exportPanel.getMessageText2().trim()); PrivateKeysHandler privateKeysHandler = new PrivateKeysHandler(controller.getModel().getNetworkParameters()); Collection<PrivateKeyAndDate> privateKeyAndDates = null; try { privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), null); fail("An encrypted export file was read in with no export file password. Fail."); } catch (KeyCrypterException kce) { assertTrue("Unexpected exception thrown when decoding export file with no export file password", kce.getMessage().indexOf(EXPECTED_COULD_NOT_DECRYPT_INPUT_STRING) > -1); } try { privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), WRONG_PASSWORD); fail("An encrypted export file was read in with the wrong export file password. Fail."); } catch (KeyCrypterException kce) { assertTrue("Unexpected exception thrown when decoding export file with wrong export file password", kce.getMessage().indexOf(EXPECTED_COULD_NOT_DECRYPT_INPUT_STRING) > -1); } privateKeysHandler = new PrivateKeysHandler(controller.getModel().getNetworkParameters()); privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename1), EXPORT_FILE_PASSWORD); assertEquals("Wrong number of keys read in from encrypted export file", 1, privateKeyAndDates.size()); assertEquals("Wrong private key read in from encrypted export file", Utils.bytesToHexString(originalPrivateKeyBytes), Utils.bytesToHexString(privateKeyAndDates.iterator().next().getKey().getPrivKeyBytes())); exportPanel.getDoNotPasswordProtect().setSelected(true); exportPanel.setWalletPassword(WALLET_PASSWORD); String outputFilename2 = controller.getModel().getActiveWalletFilename() + "-" + UUID.randomUUID().toString() + ".key"; exportPanel.setOutputFilename(outputFilename2); assertTrue("Unencrypted export file exists when it should not", !(new File(outputFilename2)).exists()); exportAction.actionPerformed(null); BitcoinControllerTest.waitForWalletNotBusy(walletBusyListener); assertTrue("Unencrypted export file does not exist when it should", (new File(outputFilename2)).exists()); assertEquals("Wrong message1 after unencrypted export is good to go", EXPECTED_THE_PRIVATE_KEYS_WERE_EXPORTED, exportPanel.getMessageText1()); assertEquals("Wrong message2 after unencrypted export is good to go", EXPECTED_THE_EXPORT_FILE_COULD_BE_READ_IN_CORRECTLY, exportPanel.getMessageText2().trim()); privateKeyAndDates = privateKeysHandler.readInPrivateKeys(new File(outputFilename2), null); assertEquals("Wrong number of keys read in from unencrypted export file", 1, privateKeyAndDates.size()); assertEquals("Wrong private key read in from unencrypted export file", Utils.bytesToHexString(originalPrivateKeyBytes), Utils.bytesToHexString(privateKeyAndDates.iterator().next().getKey().getPrivKeyBytes())); }
@Test public void testNoWalletSelected() throws Exception { final CreateControllers.Controllers controllers = CreateControllers.createControllers(); BitcoinController controller = controllers.bitcoinController; assertTrue("There was an active wallet when there should not be", controller.getModel().thereIsNoActiveWallet()); FontSizer.INSTANCE.initialise(controller); ExportPrivateKeysPanel exportPrivateKeysPanel = new ExportPrivateKeysPanel(controller, null); ExportPrivateKeysSubmitAction exportPrivateKeysSubmitAction = exportPrivateKeysPanel.getExportPrivateKeySubmitAction(); assertNotNull("exportPrivateKeysSubmitAction was not created successfully", exportPrivateKeysSubmitAction); exportPrivateKeysSubmitAction.actionPerformed(null); Object[] messages = MessageManager.INSTANCE.getMessages().toArray(); assertTrue("There were no messages but there should have been", messages != null && messages.length > 0); assertEquals("Wrong message after receive bitcoin confirm with no active wallet", ResetTransactionsSubmitActionTest.EXPECTED_NO_WALLET_IS_SELECTED, ((Message)messages[messages.length - 1]).getText()); }