From 2669fb00f16eb96f73c87bcc10c318a54ede782d Mon Sep 17 00:00:00 2001 From: Radek Davidek Date: Wed, 29 Apr 2026 19:11:57 +0200 Subject: [PATCH] added feature for changing master password Co-authored-by: Copilot --- .../java/cz/kamma/jkeepass/KeepassApp.java | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/main/java/cz/kamma/jkeepass/KeepassApp.java b/src/main/java/cz/kamma/jkeepass/KeepassApp.java index e18d335..76592a8 100644 --- a/src/main/java/cz/kamma/jkeepass/KeepassApp.java +++ b/src/main/java/cz/kamma/jkeepass/KeepassApp.java @@ -87,6 +87,7 @@ public class KeepassApp extends JFrame { // Menu items that need state management private JMenuItem menuSave; + private JMenuItem menuChangeMasterPassword; private JMenuItem menuLock; private JMenuItem menuEntryAdd; private JMenuItem menuEntryEdit; @@ -171,12 +172,14 @@ public class KeepassApp extends JFrame { JMenuItem openItem = new JMenuItem("Open Database..."); recentMenu = new JMenu("Open Recent"); menuSave = new JMenuItem("Save"); + menuChangeMasterPassword = new JMenuItem("Change Master Password..."); JMenuItem minimizeItem = new JMenuItem("Minimize & Lock"); menuLock = new JMenuItem("Lock Database"); JMenuItem exitItem = new JMenuItem("Exit"); openItem.addActionListener(e -> openDatabase(null)); menuSave.addActionListener(e -> saveDatabase()); + menuChangeMasterPassword.addActionListener(e -> changeMasterPassword()); minimizeItem.addActionListener(e -> minimizeToCustomTray()); menuLock.addActionListener(e -> lockDatabase()); exitItem.addActionListener(e -> System.exit(0)); @@ -184,6 +187,7 @@ public class KeepassApp extends JFrame { fileMenu.add(openItem); fileMenu.add(recentMenu); fileMenu.add(menuSave); + fileMenu.add(menuChangeMasterPassword); fileMenu.addSeparator(); fileMenu.add(menuLock); fileMenu.add(minimizeItem); @@ -449,7 +453,7 @@ public class KeepassApp extends JFrame { */ private void updateMenuState() { // Safely check if menu items are initialized (they might not be during early init) - if (menuSave == null || menuLock == null || menuEntryAdd == null || + if (menuSave == null || menuChangeMasterPassword == null || menuLock == null || menuEntryAdd == null || menuEntryEdit == null || menuEntryDelete == null || menuEditCopyUser == null || menuEditCopyPass == null) { return; @@ -461,6 +465,7 @@ public class KeepassApp extends JFrame { // File menu items menuSave.setEnabled(dbIsLoaded); + menuChangeMasterPassword.setEnabled(dbIsLoaded); menuLock.setEnabled(dbIsLoaded); // Entry menu items @@ -594,6 +599,70 @@ public class KeepassApp extends JFrame { } } + private void changeMasterPassword() { + if (database == null || currentFile == null || currentPassword == null) { + JOptionPane.showMessageDialog(this, "Database must be unlocked to change master password.", "Warning", JOptionPane.WARNING_MESSAGE); + return; + } + + JPasswordField newPasswordField = new JPasswordField(24); + JPasswordField confirmPasswordField = new JPasswordField(24); + Dimension passwordFieldSize = new Dimension(260, newPasswordField.getPreferredSize().height); + newPasswordField.setPreferredSize(passwordFieldSize); + confirmPasswordField.setPreferredSize(passwordFieldSize); + + JPanel panel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(5, 5, 5, 5); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridx = 0; + gbc.gridy = 0; + panel.add(new JLabel("New master password:"), gbc); + gbc.gridx = 1; + panel.add(newPasswordField, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + panel.add(new JLabel("Confirm password:"), gbc); + gbc.gridx = 1; + panel.add(confirmPasswordField, gbc); + + int result = JOptionPane.showConfirmDialog( + this, + panel, + "Change Master Password", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE + ); + + if (result != JOptionPane.OK_OPTION) { + return; + } + + String newPassword = new String(newPasswordField.getPassword()); + String confirmPassword = new String(confirmPasswordField.getPassword()); + + if (newPassword.isEmpty()) { + JOptionPane.showMessageDialog(this, "Master password cannot be empty.", "Warning", JOptionPane.WARNING_MESSAGE); + return; + } + + if (!newPassword.equals(confirmPassword)) { + JOptionPane.showMessageDialog(this, "Passwords do not match.", "Warning", JOptionPane.WARNING_MESSAGE); + return; + } + + try { + CustomDatabaseFormat.saveDatabase(currentFile, database, newPassword); + currentPassword = newPassword; + statusLabel.setText(" Master password changed successfully."); + } catch (Exception ex) { + JOptionPane.showMessageDialog(this, "Error changing master password: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); + ex.printStackTrace(); + } + } + private void lockDatabase() { if (database == null) return;