How to generate passwords for .htpasswd using PHP

In my earlier post about .htaccess I had described about authentication using .htaccess and command to generate .htpasswd file. However, when we want to add passwords for many users that method will take too long, since we will have to add passwords for each user one at a time. However, there is an easier way to generate the .htpasswd file using PHP. In this post I will show the different algorithms which can be used to generate the .htpasswd file.

Method 1: Using crypt() function.

This uses method uses crypt() encryption for passwords. This used to be the default algorithm used by Apache (2.2.17 and older). The password generated by this method will not work on Windows systems as they use MD5 based passwords. This method is same as using the command :

htpasswd -d /usr/local/etc/apache/.htpasswd user1

The output of the code below can be directly added to the .htpasswd file.

<?php
// Password to be used for the user
$username = 'user1';
$password = 'password1';

// Encrypt password
$encrypted_password = crypt($password, base64_encode($password));

// Print line to be added to .htpasswd file
echo $username . ':' . $encrypted_password;
Sample Output:
user1:MzKS62M/K9HSs

Method 2: Using APR1-MD5 algorithm

MD5 encryption method is more secure than the crypt method. This is the default method since Apache 2.2.18. The password generated by using this method can be used on both Windows and Linux based systems. This method is same as using the command :

htpasswd -m /usr/local/etc/apache/.htpasswd user1

Here is a script which I created based on the function I found on Stack Overflow.

<?php
// APR1-MD5 encryption method (windows compatible)
function crypt_apr1_md5($plainpasswd)
{
$salt = substr(str_shuffle("abcdefghijklmnopqrstuvwxyz0123456789"), 0, 8);
$len = strlen($plainpasswd);
$text = $plainpasswd.'$apr1$'.$salt;
$bin = pack("H32", md5($plainpasswd.$salt.$plainpasswd));
for($i = $len; $i > 0; $i -= 16) { $text .= substr($bin, 0, min(16, $i)); }
for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(0) : $plainpasswd{0}; }
$bin = pack("H32", md5($text));
for($i = 0; $i < 1000; $i++)
{
$new = ($i & 1) ? $plainpasswd : $bin;
if ($i % 3) $new .= $salt;
if ($i % 7) $new .= $plainpasswd;
$new .= ($i & 1) ? $bin : $plainpasswd;
$bin = pack("H32", md5($new));
}
for ($i = 0; $i < 5; $i++)
{
$k = $i + 6;
$j = $i + 12;
if ($j == 16) $j = 5;
$tmp = $bin[$i].$bin[$k].$bin[$j].$tmp;
}
$tmp = chr(0).chr(0).$bin[11].$tmp;
$tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");

return "$"."apr1"."$".$salt."$".$tmp;
}

// Password to be used for the user
$username = 'user1';
$password = 'password1';

// Encrypt password
$encrypted_password = crypt_apr1_md5($password);

// Print line to be added to .htpasswd file
echo $username . ':' . $encrypted_password;
Sample Output:
user1:$apr1$e5cytbnu$ps.bh8zF0tkJpEgkGtYcf0
We can use either of the above methods, however, the preferred method is to use the MD5 algorithm, since it is more secure and also works on both Windows and Linux systems.
Using any of the above methods and a loop we can easily generate the passwords for many users. We can use loop similar to the following to generate the passwords to be added to the .htpasswd file.

// Array for usernames and password.
$users = array();
// User 1
$users[0]['username'] = 'user1';
$users[0]['password'] = 'password1';
// User 2
$users[1]['username'] = 'user2';
$users[1]['password'] = 'password2';
// User 3
$users[2]['username'] = 'user3';
$users[2]['password'] = 'password3';

foreach($users as $user => $data)
{
$username = $data['username'];
$password = $data['password'];
// Encrypt password
$encryptedpwd = crypt_apr1_md5($password);

// Print line to be added to .htpasswd file
$content = $username . ':' . $encryptedpwd;
echo $content . '<br />';
}
Sample Output:
user1:$apr1$9qrj2x80$p2L32fS0tO7JgwzUISW8b.
user2:$apr1$hmay01vn$uIHCNVBgF5qH5jmNBIzw4/
user3:$apr1$v2tohm9c$3TtZAPuaD4dhPF62kPOwO/

By using PHP we can easily generate the code to be added to .htpasswd file for many users very easily. All the usernames and passwords in my examples are just sample users. Make use the username that you want and a different, more secure, password.

Update: Newer versions of Apache can use BCRPYT for password hash so here is another posts about Generating bcrypt .htpasswd passwords using PHP.

Related posts:

  1. more .htaccess tips
  2. Generating bcrypt .htpasswd passwords using PHP
  3. PHP 5.5 Password Hashing API
  4. .htaccess tips

7 thoughts on “How to generate passwords for .htpasswd using PHP”

  1. Thanks for your work, in method 1 there a 2 different $var for the username, in line 3 you use “$username”, but in line 10 you use just “$user”, perhaps you want to edit this ? greetings !

        1. I am not very sure why it is. It working. I have used it on Apache 2.4 on Centos as well as fedora machines and it works. May be for some reason your system doesn’t support bcrypt. Can you try to use the command line command and see if it works.
          E.g. htpasswd -nbB myName myPassword

Leave a Reply