How to programmatically build an APR1-MD5 using PHP

 ̄綄美尐妖づ 提交于 2019-11-29 15:30:14

问题


Much like this question I want to generate an htpasswd file entry from PHP. However it needs to be the APR1 (Apache) style, as mentioned in the original answer (The answer did not show how to implement the APR1 style), to work with mod_dav_svn.

I can't seem to find a working implementation that will create the password.

I found this (I forget 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 doesn't generate a working password. I think this might be something to do with the version of apache but am not sure. (I am running on CENTOS 5)


回答1:


It turns out I made a mistake and this function does in fact create working APR1 htpasswd entries. They do look different to the ones Apache creates but they do work.




回答2:


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




回答3:


This might be a bit hacky, but have you considered using the exec() function to call the command that generates the htpasswd ?




回答4:


Thanks you! It works like a charm.

Just a small comment: The salt can also contain "./" and "A..Z" besides "a..z0..9", so it is the same string as the 'translate-to' string in the last line. And sometimes you want to set the salt in addition, to create reproducable results, like:

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




回答5:


See on 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>


来源:https://stackoverflow.com/questions/1038791/how-to-programmatically-build-an-apr1-md5-using-php

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!