- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPasswordManager.java
More file actions
Latest commit
117 lines (99 loc) · 4.18 KB
/
Copy pathPasswordManager.java
File metadata and controls
117 lines (99 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.FileReader;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.security.SecureRandom;
importjava.util.ArrayList;
importjava.util.Collections;
importjava.util.Comparator;
importjava.util.List;
publicclassPasswordManager {
privateList<Account> accounts;
privateStringmasterPassword;
privateCryptoUtilscryptoUtils;
publicPasswordManager(StringmasterPassword) {
this.masterPassword = masterPassword;
this.accounts = newArrayList<>();
this.cryptoUtils = newCryptoUtils(masterPassword);
}
publicvoidaddAccount(Accountaccount) {
accounts.add(account);
}
publicList<Account> getAccounts() {
returnaccounts;
}
publicStringgeneratePassword(intlength) {
if (length < 8) {
length = 8;
}
StringuppercaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
StringlowercaseChars = "abcdefghijklmnopqrstuvwxyz";
StringnumberChars = "0123456789";
StringspecialChars = "!@#$%^&*()_-+=<>?";
StringallChars = uppercaseChars + lowercaseChars + numberChars + specialChars;
SecureRandomrandom = newSecureRandom();
StringBuilderpassword = newStringBuilder();
// Ensure at least one character from each group
password.append(uppercaseChars.charAt(random.nextInt(uppercaseChars.length())));
password.append(lowercaseChars.charAt(random.nextInt(lowercaseChars.length())));
password.append(numberChars.charAt(random.nextInt(numberChars.length())));
password.append(specialChars.charAt(random.nextInt(specialChars.length())));
// Fill the rest with random characters
for (inti = 4; i < length; i++) {
password.append(allChars.charAt(random.nextInt(allChars.length())));
}
// Shuffle the password characters
char[] passwordArray = password.toString().toCharArray();
for (inti = passwordArray.length - 1; i > 0; i--) {
intindex = random.nextInt(i + 1);
chartemp = passwordArray[index];
passwordArray[index] = passwordArray[i];
passwordArray[i] = temp;
}
returnnewString(passwordArray);
}
publicvoidsaveToFile(Stringfilename) throwsException {
try (BufferedWriterwriter = newBufferedWriter(newFileWriter(filename))) {
for (Accountaccount : accounts) {
StringplainText = account.toDataString();
Stringencrypted = cryptoUtils.encrypt(plainText);
writer.write(encrypted);
writer.newLine();
}
}
}
publicvoidloadFromFile(Stringfilename) throwsException {
accounts.clear();
try (BufferedReaderreader = newBufferedReader(newFileReader(filename))) {
Stringline;
while ((line = reader.readLine()) != null) {
try {
Stringdecrypted = cryptoUtils.decrypt(line);
Accountaccount = Account.fromString(decrypted);
accounts.add(account);
} catch (Exceptione) {
thrownewException("Failed to decrypt data. Incorrect master password or corrupted file.");
}
}
// Sort accounts by website name for better organization
sortAccountsByWebsite();
} catch (IOExceptione) {
thrownewException("Error reading file: " + e.getMessage());
}
}
publicvoidsortAccountsByWebsite() {
Collections.sort(accounts, Comparator.comparing(Account::getWebsite, String.CASE_INSENSITIVE_ORDER));
}
publicList<Account> searchAccounts(StringsearchTerm) {
List<Account> results = newArrayList<>();
StringlowerSearchTerm = searchTerm.toLowerCase();
for (Accountaccount : accounts) {
if (account.getWebsite().toLowerCase().contains(lowerSearchTerm) ||
account.getUsername().toLowerCase().contains(lowerSearchTerm)) {
results.add(account);
}
}
returnresults;
}
}