This project generate a random password to the user, based on what groups of characters the user want on his password. The user input the parameters and the password is generated. The groups and their parameters are:
-l, --lower Add letter in [a-z].
-u, --upper Add letter in [A-Z].
-d, --digits Add letter in [0-9].
-o, --logograms Add letter in [#$%&@^`~].
-p, --punctuation Add letter in [.,;:].
-q, --quotes Add letter in [\"'].
-s, --slashes Add letter in [\/|_-].
-m, --math Add letter in [*+!?=].
-b, --braces Add letter in [{}[]()].
-a, --all-groups Add letter from all the above groups.
As a matter of fact, the user can use the parameter -h or --help to show this mensage about the parameters as a "how to use the program" tutorial.
The user can also set the length of the password with --len parameter. 7 is the default length.
Finally, the user can use the --strength (or -t) parameter if he wants to check the strength and the entropy of the generated password.
Haniel Lucas Machado Rocha: hani.lucas70@gmail.com
Theo Henrique da Silva Borges: theo123b@gmail.com
- Created
validate_argumentsand performed all the error handling in it. - All the items in the
RunningOptionsstruct in addition to those that Professor Selan had added. - The mappings that identified the groups of characters corresponding to their flags (
flags_with_their_items), and the characters corresponding to their groups (items_with_their_characters). These maps were used constantly throughout the code. - Doxygen documentation.
- Created
generate_password. - Implemented the external library
zxcvbn. - Created
password_qualityusing the resources available inzxcvbn.
It is necessary to say that, even though each one did these parts separately, we talked to each other at all times, cleared up doubts and helped with the logic behind what the other was doing.
Here we are registering some difficulties doing this project.
In the validate_arguments function, inside the for loop that iterates through the command line to apply the conditions for passwords, when we go to set up the if statement that checks the password length, Theo placed the command:
run_options.pass_length = std::stoul(argv[ct + 1]);run_options is a variable of the RunningOptions struct, and pass_length is a field in this structure that represents the password length.
This command will define the password length as the string inside argv[ct + 1] converted to an unsigned int. However, it is missing a check to verify if the input after --len is a number. To do this, Haniel tried:
if (++ct > argc || !isdigit(argv[++ct]))But this causes an error in the second condition because it says that argument of type 'char *' is incompatible with parameter of type 'int'.
One attempted solution was to use if (++ct > argc || !isdigit(argv[++ct][0])) so that it only looks at the first digit. This made the error disappear, but it allowed the user to type something like 1ab, which would be interpreted as a number, even though clearly it isn't.
The solution used is in the code.
If the user types something completely random, e.g. gevfaqtheb, instead of usage() being called, the code generates a password with only LOWER (if nothing else is typed).
I used the items_with_their_characters unordered map to organize and make the password generation easier, associating a variable that stores a std::uint8_t number. Then, i created a array of booleans to check if the options inputed by the user were true or false.
So i were atributting a password character this way:
password += items_with_their_characters[inc1][inc2]Where inc1 was correctly incremented to scan the array of booleans, but inc2 were also incremented.
The problem was that inc2 determines the position of the character that will be catched in items_with_their_characters[inc1], so it can't be greater than items_with_their_characters[inc1].size().
I tried to do this verification:
if (items_with_their_characters[inc1][inc2] > items_with_their_characters[inc1].size()){
inc2 = 0;
}That bring me another problem: I was repeating the same characters of one group before all the other characters were used. Then i finally realized that i must use an vector with 9 zero's initially. Each of the zero's will represent an index, and they will be reseted if index[inc1] >= items_with_their_characters[inc1].size(). This way, the groups will not share the same iterator.
It took me a long time to understand how to correctly configure the includes and find the correct files in the library to import to the project.
Also, the zxcvbn-c library is a c-library as default, not c++. I took a long time to realize that i must change the extensions .c to .cpp.
Preencha os itens que você implementou, indicando qual a nota esperada para cada item.
| Item | Valor máximo | Valor esperado |
|---|---|---|
| Interface de acordo com o especificado | 20 | 20 |
| Seleciona caracteres dos grupos adequadamente | 15 | 15 |
| Apresenta a tela de ajuda quando solicitado | 5 | 5 |
| Trata os erros de entrada corretamente | 12 | 10 |
| Avalia a qualidade da senha com 5 categorias | 10 | 10 |
| Implementa os 9 grupos de caracteres solicitados | 18 | 18 |
| Utiliza corretamente a aleatoriedade | 10 | 10 |
In your terminal, stay on the ".../trabalho-03-projeto-passgen-el-th-hani" directory, and use the following commands:
g++ src/main.cpp lib/zxcvbn.cpp -o passgen -IlibWe have to compile the code this way because we are using the zxcvbn-c library locally to check the password strength.
Command details:
g++: Call g++ compilersrc/main.cpp: Compile the source-code of the program (main.cpp)lib/zxcvbn.cpp: Compile the auxiliary code zxcvbn.cpp from the library-o passgen: Name the executable as passgen-Ilib: Specify thelibdirectory as a include directory
Example:
./passgen --len 15 -a -t./passgen: The name of the executable you are running--len: --len + Number specify the length of the password that will be generated-a: Is the parameter that says that the user want all the groups-t: Is the parameter that says that the user want to know the password strength and the entropy