#native_company# #native_desc#
#native_cta#

Encrypting passwords for use in Apache AuthUserFile files

By Greg Miller
on October 11, 2005

I was having a problem with managing with PHP my AuthUserFiles in Apache, namely that in the Windows environment crypt is not supported, and php’s md5() and sha1() did not generate encrypted text that was readily compatible with Apache’s password encryption routines. After digging around on the Internet, I found some code on Patrick R. Michaud’s webpage at the University of Oulu in Finland (http://www.student.oulu.fi/~samiantt/scripts/authuser.php
) , which illustrated techniques for generating compatible encrypted text. I adapted his code so that you can encrypt passwords in a format that can be stored readily into an AuthUserFile.

The main function is encrypt_password_for_apache() which takes two arguments. The first argument is the plain text of the password to be encrypted, and the second argument is the encryption type desired. Currently the code supports MD5 Message-Digest (“MD5”) and US Secure Hash (“SHA”), and standard DES encryption (by default). The second function is generate_salt() which generates a random salt value to the length specified, and this is called from within encrypt_password_for_apache().

If you take the encrypted password, and store it into the AuthUserFile with the corresponding login name, you can manage access to an Apache website using Basic Authentication.

Hope this proves to be as helpful to you as it was to me!

example:

$password = "pickles";
print "SHA: " .  htmlentities(encrypt_password_for_apache($password,"SHA"),ENT_QUOTES) . "
"; print "MD5: " . htmlentities(encrypt_password_for_apache($password,"MD5"),ENT_QUOTES) . "
"; print "DES: " . htmlentities(encrypt_password_for_apache($password,"DES"),ENT_QUOTES) . "
";


Produces this:

SHA: {SHA}CMQGCU4zI7ukGHodiVAM5mH6hwY=
MD5: $apr1$bXqnYWFV$83N309IUpMq7AGA.R.hwh1
DES: dKvH7o6wmoRzg

Function referenced above are specified below:

function generate_salt($len) {
  $randset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  $randset .= './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
  $salt = "";
  for ($i=0;$i<$len;$i++) {
    $choice = rand(0,strlen($randset)-1);
    $salt .= (substr($randset,$choice,1));
  }
  return $salt;
}
function encrypt_password_for_apache($plain,$ptype) {
/*
  adapted from:
  http://www.student.oulu.fi/~samiantt/scripts/authuser.php
*/
  switch ($ptype) {
    case "SHA": //
      return '{SHA}' . base64_encode(pack('H*', sha1($plain)));
      break;
    case "MD5":
      $salt = generate_salt(8);
      $length = strlen($plain);
      $context = $plain . '$apr1$' . $salt;
      $binary = pack('H32', md5($plain . $salt . $plain));
      for($i = $length; $i > 0; $i -= 16) {
        $context .= substr($binary, 0, min(16, $i));
      }
      for($i = $length; $i > 0; $i >>= 1) {
        $context .= ($i & 1) ? chr(0) : $plain{0};
      }
      $binary = pack('H32', md5($context));
      for($i = 0; $i < 1000; $i++) {
        $new = ($i & 1) ? $plain : $binary;
        if ($i % 3) $new .= $salt;
        if ($i % 7) $new .= $plain;
        $new .= ($i & 1) ? $binary : $plain;
        $binary = pack('H32', md5($new));
      }
      $q = '';
      for ($i = 0; $i < 5; $i++) {
        $k = $i + 6;
        $j = $i + 12;
        if ($j == 16) $j = 5;
        $q = $binary{$i} . $binary{$k} . $binary{$j} . $q;
      }
     $q = chr(0) . chr(0) . $binary{11} . $q;
     $q = strtr(strrev(substr(base64_encode($q), 2)),
                'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
                './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
     return "$apr1$$salt$$q";
     break;
   default:
     return crypt($plain, generate_salt(2));
     break;
  }
}