-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpassword.cpp
More file actions
236 lines (195 loc) · 7.82 KB
/
Copy pathpassword.cpp
File metadata and controls
236 lines (195 loc) · 7.82 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#include <string>
#include <optional>
#include <vector>
#include <random>
#include <algorithm>
#include <cctype>
#include "cypher.h"
#include "files.h"
#include "password.h"
#include "time_stamp.h"
std::optional<std::string> read_master_password(const std::string& fileName) {
if (!validate_whether_the_file_exists(fileName)) {
return std::nullopt;
}
std::ifstream file(fileName);
std::string line;
const std::string tag = encrypt_decrypt_input("__MASTER__: ");
while (std::getline(file, line)) {
if (line.rfind(tag, 0) == 0) {
std::string decrypted = encrypt_decrypt_input(line, false);
return decrypted.substr(std::string("__MASTER__: ").size());
}
}
return std::nullopt;
}
void write_master_password(const std::string& fileName, const std::string& masterPassword) {
std::ofstream file(fileName, std::ios::app);
file << encrypt_decrypt_input("__MASTER__: " + masterPassword) << '\n';
}
/**
* Generates a random password according to user defined rules (arguments).
*
* @param length lenght of the password decaler by the user
* @param use_uppercase tells whether the password should contain capital letters
* @param use_special tells whether the password should contain special characters
* @param name name of the password
* @return a random generated password is returned
*/
std::string generate_password(int length, bool use_uppercase, bool use_special, const std::string& name) {
if (length <= 0) return "";
// Base character sets
const std::string lowercase = "abcdefghijklmnopqrstuvwxyz";
const std::string uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const std::string digits = "0123456789";
const std::string special = "!@#$%^&*()_+-=`~{}[]:;'\".,/<>?|\\";
std::string pool = lowercase + digits;
if (use_uppercase) pool += uppercase;
if (use_special) pool += special;
// RNG setup
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, pool.size() - 1);
std::string password;
password.reserve(length);
// Ensure at least one of each required category
if (use_uppercase) password += uppercase[dist(gen) % uppercase.size()];
if (use_special) password += special[dist(gen) % special.size()];
password += digits[dist(gen) % digits.size()];
password += lowercase[dist(gen) % lowercase.size()];
// Fill remaining characters
while ((int)password.size() < length) {
password += pool[dist(gen)];
}
// Shuffle so guarantees arent at the front
std::shuffle(password.begin(), password.end(), gen);
return password;
}
/**
* Veryfing the password strenght based on some general criteria
*
* @param password password that is beign verified
* @return quality of the password in a string
*/
std::string password_strength_verifier(std::string password) {
const int STRONG_LEN = 12;
const int GOOD_LEN = 9;
const int MIN_LEN = 8;
const int BAD_LEN = 4;
int lowercaseCount = 0;
int uppercaseCount = 0;
int digitCount = 0;
int specialCount = 0;
for (unsigned char ch : password) {
if (std::islower(ch)) {
++lowercaseCount;
}
else if (std::isupper(ch)) {
++uppercaseCount;
}
else if (std::isdigit(ch)) {
++digitCount;
}
else if (std::isprint(ch) && !std::isalnum(ch)) {
++specialCount;
}
}
const int password_length = password.size();
if (password_length >= STRONG_LEN && lowercaseCount > 3 && uppercaseCount > 3 && digitCount > 2 && specialCount >= 2) {
return "Excelent";
}
if (password_length >= GOOD_LEN && lowercaseCount > 2 && uppercaseCount > 2 && digitCount >= 2) {
return "Good";
}
if (password_length >= MIN_LEN && lowercaseCount >= 1 && uppercaseCount >= 1 && digitCount >= 1) {
return "Bad";
}
if (password_length > BAD_LEN && password_length < MIN_LEN) {
return "Terrible";
}
return "Dangerous";
}
/**
* Password chosen by the user can be edited. After edition the password is saved back to the file
*
* @param fileName name of the file that will be searched
* @return message stating summary of the operation
*/
std::string password_edition(const std::string& fileName) {
if (!validate_whether_the_file_exists(fileName)) return "";
std::ifstream currentFile;
std::vector<std::string> lines;
std::string currentLine;
std::string editedPassword;
int lineNumber = 0;
currentFile.open(fileName);
int lineIndicatorForFile = 1;
while (getline(currentFile, currentLine)) {
lines.push_back(currentLine);
if (currentLine.find(encrypt_decrypt_input(DEFAULT_TAG)) != std::string::npos) {
std::string clearLineWithoutTag;
for (int i = DEFAULT_TAG.size(); i < currentLine.length(); i++) {
clearLineWithoutTag += currentLine[i];
}
std::cout << lineIndicatorForFile << ". " << encrypt_decrypt_input(clearLineWithoutTag, false) << std::endl;
}
lineIndicatorForFile++;
}
std::cout << "Wpisz numer hasla, ktore chcesz edytowac:" << std::endl;
std::cout << ">";
std::cin >> lineNumber;
std::cout << "Edytujesz haslo numer: " << lineNumber << ", wprowadz zmiany:" << std::endl;
std::cout << ">";
std::cin >> editedPassword;
currentFile.close();
if (lineNumber > lines.size()) {
std::cout << "Linia: " << lineNumber << ", nie znajduje sie w pliku." << std::endl;
}
write_to_file(fileName, lines, lineNumber, editedPassword);
return "Zapisano wprowadzone zmiany.";
}
/**
* Function opens a file and searches for passwords or tagged entries.
*
* @param fileName name of the file to search
* @param searchedPassword the password or phrase to search for
* @param startOfLineTag tag marking the start of relevant lines (default "Haslo: ")
* @param printResults whether to print matching lines (true) or return summary (false)
* @return summary message if printResults is false, otherwise empty string
*/
std::string search_password(const std::string& fileName, const std::string& searchedPassword, const std::string& startOfLineTag, bool printResults) {
if (!validate_whether_the_file_exists(fileName)) return "";
std::ifstream currentFile(fileName);
std::vector<std::string> lines;
std::string currentLine;
int lineNumber = 1;
int matchCount = 0;
const std::string encryptedTag = encrypt_decrypt_input(startOfLineTag);
const std::string encryptedSearch = encrypt_decrypt_input(searchedPassword);
while (std::getline(currentFile, currentLine)) {
lines.push_back(currentLine);
// Only process lines that begin with the expected tag
if (currentLine.find(encryptedTag) != std::string::npos) {
// Decrypt and remove tag
std::string decryptedLine = encrypt_decrypt_input(currentLine, false);
std::string clearPart = decryptedLine.substr(startOfLineTag.size());
// Count or print matches
if (clearPart == searchedPassword) {
matchCount++;
}
if (printResults) {
std::cout << lineNumber << ". " << decryptedLine << std::endl;
}
}
lineNumber++;
}
currentFile.close();
write_to_file(fileName, lines);
// Print the message only if the caller wants it
if (!printResults) {
return "Wprowadzono haslo, ktore pojawilo sie w pliku - "
+ std::to_string(matchCount)
+ " razy.";
}
return "";
}