How to programmatically build APR1-MD5 using PHP

Like this question I want to generate a htpasswd file entry with PHP. However, it must be APR1 (Apache) style, as indicated in the original answer (the answer did not show how to implement APR1 style), to work with mod_dav_svn.

I can not find a working implementation that will create a password.

I found this (I forgot where now):

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; } 

But it does not create a working password. I think this may be due to the apache version, but I'm not sure. (I work on CENTOS 5)

+6
php apache md5 mod-dav-svn
source share
5 answers

It turns out that I made a mistake, and this function really creates the working records APR1 htpasswd. They look different than those created by Apache, but they really work.

+2
source share

Look for existing components that do this on sites like phpclasses.org. One example: http://www.phpclasses.org/browse/package/5066.html .

+1
source share

This might be a bit hacky, but do you think you use the exec () function to call the command that htpasswd generates?

0
source share

Thanks! It works like a charm.

A short comment: salt can also contain "./" and "A..Z", except for "a..z0..9", so this is the same line as the line "translate-to" in the last line. And sometimes you want to also add salt to create reproducible results, for example:

function crypt_apr1_md5( $plainpasswd, $salt = '' ) {
$translateTo = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
if ( $salt == '' ) { $salt = substr(str_shuffle($translateTo), 0, 8); }

...

$tmp = strtr(strrev(substr(base64_encode($tmp), 2)), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", $translateTo);
return '$apr1$'.$salt.'$'.$tmp;
}

0
source share

Take a look at this:

 1: private function crypt_apr1_md5($plainpasswd) { </br> 7: for($i = $len; $i > 0; $i >>= 1) { $text .= ($i & 1) ? chr(o) : $plainpasswd{0}; } </br> 16: $tmp = ''; </br> 
0
source share

All Articles