2
\$\begingroup\$

My goal in creating this project was to create a password generator that was simple enough to be useful as well as sophisticated enough in its random-number generator so as to not be contrived.

I used Boost Program Options for argument parsing. The interface seems extremely easy to use, and the fact that it's both more readable and allows for writing idiomatic C++ seem pretty good reasons to not use getopt.h in this case.

Using the --passwords or -n flags the user may set the number of passwords to generate. Likewise, the --length or -l flags set the length of the password. I looked around for a standard list of character symbols to use, but I couldn't find anything like a standard, so my default symbol list is "!@#$``~|\\%^&*()[]-_=+{}';:,<.>/?". (Note: the backtick is repeated so StackOverflow's markdown highlights everything properly.) The user may use the --simple-symbols flag to use only "!@#$&?".

The actual random number generation was what I wanted to explore with this project. While researching this question I came across some very similar projects like this one, which used Sodium, but I'm wondering if the method I'm using here is as good, or at least viable.

I used std::random_device to generate my random numbers, along with std::uniform_int_distribution, to ensure as random and uniform an output as possible. I'm looking for a way to check whether std::random_device will work as expected; since it may not be non-deterministic if there is no hardware implementation, I would like to at least warn the user during execution.

Lastly, I wanted to make the alphabets used for password generation as extensible as possible, but after implementing them, it seems a little too much for the benefit gained in return. It theoretically allows a user to not have to use numbers or letters, or whatever, but with the benefit of hindsight this doesn't look like a good feature.

PGEN.hpp

#ifndef PGEN_INCLUDES_PGEN_H_
#define PGEN_INCLUDES_PGEN_H_
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <random>
#include <string>
#include <boost/program_options.hpp>
#endif // PGEN_INCLUDES_PGEN_H_

main.cpp

#include "PGEN.hpp"
namespace Options = boost::program_options;
int main(int argc, char *argv[])
{
 /** Program Defaults
 *
 */
 const auto DefaultPasswordsToCreate = 1;
 const auto DefaultPasswordLength = 16;
 const std::string DefaultSymbolList = "!@#$`~|\\%^&*()[]-_=+{}';:,<.>/?";
 const std::string SimplerSymbolList = "!@#$&?";
 /** Program Options
 *
 */
 bool verbose = false;
 /** Password parameters:
 *
 */
 int N = DefaultPasswordsToCreate;
 int PasswordLength = DefaultPasswordLength;
 std::string AlphabetUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 std::string AlphabetLower = "abcdefghijklmnopqrstuvwxyz";
 std::string AlphabetNumeric = "0123456789";
 std::string AlphabetSymbols = DefaultSymbolList;
 Options::options_description OptionsDescription("Program Options");
 OptionsDescription.add_options()
 ("help,h", "Display this help message and exit.")
 ("version", "Print program version information.")
 ("passwords,n", Options::value<int>(&N)->default_value(DefaultPasswordsToCreate), "Number of passwords to generate.")
 ("length,l", Options::value<int>(&PasswordLength)->default_value(DefaultPasswordLength), "Length of passwords to generate.")
 ("symbols", Options::value<std::string>(&AlphabetSymbols)->default_value(DefaultSymbolList), "Pass in custom legal symbols list.")
 ("simple-symbols", "Use simpler symbol list.")
 ("verbose,v", "Log additional info to stdout during execution.")
 ;
 Options::variables_map ArgsInput;
 Options::store(Options::parse_command_line(argc, argv, OptionsDescription), ArgsInput);
 Options::notify(ArgsInput);
 if (ArgsInput.count("help"))
 {
 std::cout << OptionsDescription << std::endl;
 return EXIT_SUCCESS;
 }
 if (ArgsInput.count("version"))
 {
 std::cout << "[Program Version Information...]" << std::endl;
 return EXIT_SUCCESS;
 }
 if (ArgsInput.count("verbose"))
 {
 verbose = true;
 }
 if (ArgsInput.count("symbols"))
 {
 // TODO: Validate symbol list input.
 if (verbose) {
 std::cout << "Legal Symbols: " << AlphabetSymbols << std::endl;
 }
 }
 if (ArgsInput.count("simple-symbols"))
 {
 AlphabetSymbols = SimplerSymbolList;
 if (verbose) {
 std::cout << "Legal Symbols: " << AlphabetSymbols << std::endl;
 }
 }
 // TODO: Refactor to idiomatic C++.
 const auto AlphabetSize = 62 + strlen(AlphabetSymbols.c_str());
 char* Alphabet = static_cast<char *>(malloc(sizeof(char) * AlphabetSize));
 sprintf(Alphabet, "%s%s%s%s", AlphabetUpper.c_str(), AlphabetLower.c_str(), AlphabetNumeric.c_str(), AlphabetSymbols.c_str());
 std::random_device rd;
 std::uniform_int_distribution<int> dist(0, AlphabetSize);
 for (auto i = 0; i < N; ++i) {
 for (auto n = 0; n < PasswordLength; ++n) {
 const auto r = dist(rd);
 std::cout << Alphabet[r];
 }
 std::cout << std::endl;
 }
 return EXIT_SUCCESS;
}

Directory Structure

PGEN
|-- Makefile
|
|-- src
| |_ main.cpp
|
|__ include
 |_ PGEN.hpp

Makefile

SHELL = /bin/sh
.SUFFIXES:
.SUFFIXES: .cpp .hpp
vpath %.cpp src
vpath %.hpp include
PROGRAM = pgen
all: $(PROGRAM)
$(PROGRAM): main.o
 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $^ -lboost_program_options
main.o: main.cpp
 $(CXX) $(CXXFLAGS) $(CPPFLAGS) -I include $(TARGET_ARCH) -c -o $@ $^
.PHONY: clean
clean:
 rm -rf *.o $(PROGRAM)

To build I usually used the following:

make CXX=g++ CXXFLAGS="-std=c++17 -Wall -Wextra -pedantic"

Example:

$ ./pgen
i=2TBdeDK8E8L%xk
$ ./pgen -n 10 -l 24
zE'S9l(6C3r_F8!V6)[Q!ZiW
-2iJVbW3(4@556vL-@v&naM
96T`-Bl3;MkVmAVHogx]|}X
F~~UJ$tpmrZ2Phf2/WEzlY>$
QLfD5m}29%o#E;\-}MM.QiGb
V'Rwv^\)Rw~5zL5X6a'9{;MJ
RO,m`-K&^G=f/^7IK+@>4@7b
F?fdM6)+.Qcmd<&II;R}1ao
xI6-VCv'ct\g2Da;OfhN^-td
Ayai>)'PQ=T,=zyoEg[Fod`G
$ ./pgen -n -10 -l 24 --simple-symbols
z@?IquGoOw8IhqBJCoat4YM0
qjOXC!1o0ZjfHQezxfHyYe2
4#uyBN5oGoWqbmw!eYTNwW@e
I65bEWLHHg8&3WXhtUXIxX6W
i95SuYP0Ab#d0FUUmpIbGGzk
gOF!EHe1!LeaiP#I?UoD84ドルv
jPLzBFv2IIqp7iQ$z4@ORW$&
d4eM#NeCaxNf?hGroLBgp&E
QPNZ849rKJnDO$rVhFGkfWWZ
0Ch&IzAQN8PjfUFCMBtVwaVC
asked Mar 15, 2019 at 9:59
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This might be of help to you. \$\endgroup\$ Commented Mar 15, 2019 at 18:43

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.