htpasswd "encoding"

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

htpasswd "encoding"

Post by andym01480 »

What's the best form of encoding for htpasswd generated by a php script? MD5 doesn't seem to work everytime...
derchris
Forum Commoner
Posts: 44
Joined: Sat Jun 10, 2006 6:14 pm

Post by derchris »

The passwords for a .htaccess Userfile are always MD5,
there is no other choice.
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

Post by andym01480 »

Not sure that is accurate...
htpasswd encrypts passwords using either a version of MD5 modified for Apache, or the system's crypt() routine. Files managed by htpasswd may contain both types of passwords; some user records may have MD5-encrypted passwords while others in the same file may have passwords encrypted with crypt()......

The MD5 algorithm used by htpasswd is specific to the Apache software; passwords encrypted using it will not be usable with other Web servers.
from
http://httpd.apache.org/docs/2.0/programs/htpasswd.html
derchris
Forum Commoner
Posts: 44
Joined: Sat Jun 10, 2006 6:14 pm

Post by derchris »

but you were talking about PHP scripts, not the shell.
User avatar
andym01480
Forum Contributor
Posts: 390
Joined: Wed Apr 19, 2006 5:01 pm

Post by andym01480 »

Let me rephrase. I need to populate an htpasswd file and wanted my own tool for generating the passwords. I tried md5 in a php script and it doesn't always work, which seems strange. (I could login with a username and password, but someone else couldn't from their machine even cut and pasting.)

Those quotes imply that it is not straight md5, so what from a php script would generate the passwords that would always work?
Last edited by andym01480 on Mon Jun 12, 2006 2:49 pm, edited 1 time in total.
rich86
Forum Newbie
Posts: 15
Joined: Sun Jun 11, 2006 7:30 pm

Post by rich86 »

this is a script i have used before, it uses a database to store the uses passwords then compiles a new htpasswd file when called, this can be when someone changes a password or a new user is added.

Code: Select all

function makehtpasswd()
{

	$file_location = "passwd";  //needs to change depending on server
	$query_users = "SELECT name, password FROM users";
	$users = mysql_query($query_users) or die(mysql_error());
	$rows_users = mysql_num_rows($users);
	$t=0;
	if ($rows_users!=0) {
		$f = fopen($file_location,"w+");
		while ($rows_users>$t) {
			unset($seed);
			# generate random seed
			$all=explode(" ",
			  "a b c d e f g h i j k l m n o p q r s t u v w x y z "
			. "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z "
			. "0 1 2 3 4 5 6 7 8 9");
			for($i=0;$i<9;$i++) {
				srand((double)microtime()*1000000);
				$randy=rand(0, 61);
				$seed.=$all[$randy];
			}
			$username = mysql_result($users,$t,"name");
			$password = base64_decode(mysql_result($users,$t,"password"));
			$crypt = crypt($password, "\$1$$seed");
			fputs($f,"$username:$crypt\n");
			$t++;
		}
		fclose($f);
	}
hope that helps
User avatar
shoebappa
Forum Contributor
Posts: 158
Joined: Mon Jul 11, 2005 9:14 pm
Location: Norfolk, VA

Post by shoebappa »

Hrm wonder if the above code works? Certainly simpler if it does. I "borrowed" this from some pear library (I assume this is ok, prolly have to follow whatever the pear license is):

Code: Select all

<?php

$GLOBALS['_FILE_PASSWD_64'] =
    './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

$password = $HTTP_GET_VARS["password"];

function crypt_apr_md5($plain, $salt = null)
    {
        if (is_null($salt)) {
            $salt = salt(8);
        } elseif (preg_match('/^\$apr1\$/', $salt)) {
            $salt = preg_replace('/^\$apr1\$([^$]+)\$.*/', '\\1', $salt);
        } else {
            $salt = substr($salt, 0,8);
        }
        
        $length     = strlen($plain);
        $context    = $plain . '$apr1$' . $salt;
        $binary     = hexbin(md5($plain . $salt . $plain));
        
        for ($i = $length; $i > 0; $i -= 16) {
            $context .= substr($binary, 0, ($i > 16 ? 16 : $i));
        }
        for ( $i = $length; $i > 0; $i >>= 1) {
            $context .= ($i & 1) ? chr(0) : $plain[0];
        }
        
        $binary = hexbin(md5($context));
        
        for($i = 0; $i < 1000; $i++) {
            $new = ($i & 1) ? $plain : substr($binary, 0,16);
            if ($i % 3) {
                $new .= $salt;
            }
            if ($i % 7) {
                $new .= $plain;
            }
            $new .= ($i & 1) ? substr($binary, 0,16) : $plain;
            $binary = hexbin(md5($new));
        }
        
        $p = array();
        for ($i = 0; $i < 5; $i++) {
            $k = $i + 6;
            $j = $i + 12;
            if ($j == 16) {
                $j = 5;
            }
            $p[] = to64(
                (ord($binary[$i]) << 16) |
                (ord($binary[$k]) <<  |
                (ord($binary[$j])),
                5
            );
        }
        
        return 
            '$apr1$' . $salt . '$' . implode($p) . 
            to64(ord($binary[11]), 3);
    }


function salt($length = 2)
    {
        $salt = '';
        $length = (int) $length;
        $length < 2 && $length = 2;
        for($i = 0; $i < $length; $i++) {
            $salt .= $GLOBALS['_FILE_PASSWD_64'][rand(0, 63)];
        }
        return $salt;
    }

  
function hexbin($hex)
    {
        $rs = '';
        $ln = strlen($hex);
        for($i = 0; $i < $ln; $i += 2) {
            $rs .= chr(hexdec($hex{$i} . $hex{$i+1}));
        }
        return $rs;
    }


function to64($value, $count)
    {
        $result = '';
        while(--$count) {
            $result .= $GLOBALS['_FILE_PASSWD_64'][$value & 0x3f];
            $value >>= 6;
        }
        return $result;
    }

echo crypt_apr_md5($password);

?>
Post Reply