Generating strong, random passwords is an important security practice for anyone living in the 21st century, but especially for devs. So, we are going to walk through the process of building a simple PHP CLI tool for generating random passwords. And we are going to call this tool,cli-passwd-gen
.
What Do We Need?
The basic concept of cli-passwd-gen
is to create a random string of characters and then print the resulting string to the screen. Before getting started, we should consider the program requirements for cli-passwd-gen
.
Program Requirements
Capability to specify the length of the password
Capability to specify character types (lowercase, uppercase, numbers, and/or special characters)
The characters in the password should be random
The generated password should output to the command line at the completion
When executing the command, the user will need to specify values for the following required arguments:
-t, --types
- Types of characters the user wants to include in the password.- There are only four valid values for this argument: '
l', 'u', 'n', 's'
. Which represent: lowercase, uppercase, numbers, and/or special (for special characters).
- There are only four valid values for this argument: '
-l, --length
- Integer value denoting the number of characters the user wants to include in their password.
We will also need to use the following built-in PHP functions:
getopt()
- Parses command-line options and arguments into an array.- This will allow us to take in user input to customize the password.
isset()
- Determines whether a variable has been set or not.- This will help us verify that the user has set the required options.
strpos()
- Finds the position of the first occurrence of a substring in a string.- This allows us to determine the optional arguments that the user has selected.
exit()
- Terminates the program and outputs a message to the screen.- We will use this when handling input validation errors.
pregmatch()
- Finds a match for a specified regular expression.- We will use this to validate user input.
random_int()
- Generates a cryptographically random integer.- This will help us select random characters for the password string.
strlen()
- Gets the length of a string.
In a few lines of code, we will create a simple, but effective password generator that can be used to create strong and secure passwords on the fly.
1. Set Up The Command Line Interface
First, create a PHP file for this program. I'm going to name mine, cli-passwd-gen.php
.
To set up the command line interface, we'll use PHP's built-in getopt()
function. This function parses command line options and arguments and returns an associative array of the options and their values.
Here's an example of how we use getopt()
to parse command line options at the beginning of the program:
<?php
// Parse the user's command and compare with these options
$options = getopt("l:t:", ["length:", "types:"]);
// Check if $options['l'] exists -- if so, assign it to $length
// Else, assign $options['length'] to $length
$length = isset($options['l']) ? (int)$options['l'] : (int)$options['length'];
$types = isset($options['t']) ? $options['t'] : $options['types'];
Defining Arguments And Assigning User Input
This code does two things:
It defines arguments. In this case,
length
andtypes
.It specifies how the program will identify what values the user has passed in for each of these arguments. Then, it assigns those values to corresponding variables.
-l
or--length
specifies thelength
of the password. The user passes in an integer value for$options['l']
or$options['length']
. This will be assigned to$length
.-t
or--types
specifies the charactertypes
to include in the password. The user will pass in character value(s) for$options['t']
or$options['types']
. Then, this will be assigned to$types
.- There are only four values that can be passed in for
-t, --types
: 'l', 'u', 'n', and/or 's'. Which represent lowercase letters, uppercase letters, numbers, and special characters, respectively.
- There are only four values that can be passed in for
Let's look at an example. The user opens the terminal and runs the cli-passwd-gen
program. If the user wants a password of length 12 with only lowercase and uppercase letters. So, their command would look like this:
php cli-passwd-gen.php --length 12 --types lu
The program is going to take the values that the user specified for each of the options and assign the values to the corresponding variables. See in the code below how $length
is assigned 12 and $types
is assigned 'lu':
$length = isset($options['l']) ? (int)$options['l'] : (int)$options['length'];
// $length = 12;
$types = isset($options['t']) ? $options['t'] : $options['types'];
// $types = 'lu';
2. Validate Arguments & Handle Errors
Next, we'll validate the command line arguments and handle any potential errors. For the --length, -l
argument, we'll check that it's a positive integer. For the --types, -t
argument, we'll check that it's a string containing only the characters l
, u
, n
, and/or s
.
If either one of these statements is false (input does not pass validation), which will cause the program to exit.
if (!$length || $length <= 0) {
exit("Error: Password length must be a positive integer\n");
}
if (!$types || !preg_match('/^[luns]*$/', $types)) {
exit("Error: Password types must be a string containing only 'l', 'u', 'n', and/or 's'\n");
}
We use preg_match()
to check that the types
string contains only the allowed characters.
3. Filter User Input
Now, the program is taking the options that the user typed in the command line and determining what characters should be used to generate the password:
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$numbers = '0123456789';
$special = '!@#$%^&*()_+-={}[];\',./<>?:"|\\';
$chars = '';
// Find the first occurrence of each substring (l, u, n, or s) within $types
if (strpos($types, 'l') !== false) {
$chars .= $lowercase;
}
if (strpos($types, 'u') !== false) {
$chars .= $uppercase;
}
if (strpos($types, 'n') !== false) {
$chars .= $numbers;
}
if (strpos($types, 's') !== false) {
$chars .= $special;
}
But, let's break this down a little bit.
Specify Character Types To Use In The Password
We begin by defining several variables ($lowercase
, $uppercase
, $numbers
, and $special
). These are the character types that are available for the user to choose for their password.
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$numbers = '0123456789';
$special = '!@#$%^&*()_+-={}[];\',./<>?:"|\\';
The final variable definition, $chars
, is an empty string. The value of each character type ($lowercase
, $uppercase
, $numbers
, and/or $special
) that is chosen by the user will be concatenated to this string.
$chars = '';
The $chars
variable will determine which characters the program should use when randomly generating a password string.
Check User Input
The collection of if
statements below the variable definitions will sift through the user's input to determine which options were selected ('l', 'u', 'n', or 's').
if (strpos($types, 'l') !== false) {
$chars .= $lowercase;
}
if (strpos($types, 'u') !== false) {
$chars .= $uppercase;
}
if (strpos($types, 'n') !== false) {
$chars .= $numbers;
}
if (strpos($types, 's') !== false) {
$chars .= $special;
}
If one of these arguments were specified by the user (e.g., --types ln
), then that set of characters (in this case,$lowercase
and $numbers
) will be concatenated to the $chars
string. Which will be used to generate a randomized password.
Continuing from the last example (--types ln
), the program will check if the user's input includedl
for the -t, --types
argument. Since l
was specified by the user, this statement is true. So, the entire $lowercase
string will be concatenated to $chars
.
if (strpos($types, 'l') !== false) {
$chars .= $lowercase;
}
# $chars = 'abcdefghijklmnopqrstuvwxyz'
When the program receives input from the user that specifies that the types
of characters used should be lowercase letters l
and numbers n
, the string values stored in the $lowercase
and $numbers
variables are concatenated to $chars
.
php cli-passwd-gen.php --length 12 --types ln
So, our $chars
string will be equivalent to this:
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
Now that the user has specified parameters for the password, it's time to put all of this information together and generate a random string.
4. Generate The Password
We'll use PHP's random_int()
function to generate random numbers, and use those numbers to select characters from the user-specified character types, $chars
.
$password = '';
for ($i = 0; $i < $length; $i++) {
$index = random_int(0, strlen($chars) - 1);
$password .= $chars[$index];
}
echo $password . "\n";
Here, we are using a for-loop to add random characters to the password string. Notice that strlen()
takes the size of $chars
to determine a random integer.
$index = random_int(0, strlen($chars) - 1);
This will serve as the index to select a value from the $chars
string and concatenate it to the password.
$password .= $chars[$index];
This loop continues until the user's desired password $length
is met. At this point, the echo
statement causes the password string to be printed to the terminal.
5. Test The Program
Navigate to the directory where you have saved the cli-passwd-gen
program file. Then run the following command with your chosen file name:
$ php cli-passwd-gen.php --length 12 --types lun
# output: Tc7s1b4Lw3fV
To test the program, you can run it with various combinations of options and verify that the generated passwords meet the requirements.
$ php cli-passwd-gen.php --length 8 --types l
# output: xhzzjmli
$ php cli-passwd-gen.php --length 10 --types u
# output: LPKNWVRSDI
$ php cli-passwd-gen.php --length 6 --types ns
# output: @*&#$^
$ php cli-passwd-gen.php --length 5 --types luns
# output: g%u6K
Conclusion
In this project, we learned how to create a command-line password generator using PHP. We put basic concepts of password generation into practice. And also gained experience working with PHP functions, such as getopt()
and strpos()
, among others. In addition, we learned how to generate random characters and validate user input, which are important skills in any programming project.
By combining these lessons, we were able to create a simple but effective tool for generating strong passwords on the command line.