【问题标题】:How to programmatically build an APR1-MD5 using PHP如何使用 PHP 以编程方式构建 APR1-MD5
【发布时间】:2009-06-24 14:37:09
【问题描述】:

很像this question 我想从 PHP 生成一个 htpasswd 文件条目。但是,它必须是 APR1 (Apache) 样式,如原始答案中所述(答案没有显示如何实现 APR1 样式),才能与 mod_dav_svn 一起使用。

我似乎找不到可以创建密码的有效实现。

我找到了这个(我忘了现在在哪里):

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

但它不会生成有效密码。我认为这可能与 apache 的版本有关,但不确定。 (我在 CENTOS 5 上运行)

【问题讨论】:

  • 此代码来自 PHP 'crypt' 文档的 cmets 部分:php.net/manual/en/function.crypt.php
  • 我收到一个错误,它会抱怨 $tmp 未定义,我只是在函数的开头添加了 $tmp="" 并且它现在可以正常工作,但我不确定是否这是解决问题的正确方法。

标签: php apache md5 mod-dav-svn


【解决方案1】:

事实证明我犯了一个错误,这个函数实际上创建了有效的 APR1 htpasswd 条目。它们看起来确实与 Apache 创建的不同,但它们确实有效。

【讨论】:

    【解决方案2】:

    在 phpclasses.org 等网站上寻找现有的组件。一个例子:http://www.phpclasses.org/browse/package/5066.html

    【讨论】:

    • 这个来自 phpclasses 的特定示例甚至不支持 apr1/MD5 密码文件,因此对于这个特定问题毫无用处。
    【解决方案3】:

    谢谢!它就像一个魅力。

    只是一个小注释:salt除了“a..z0..9”之外还可以包含“./”和“A..Z”,所以它与'translate-to'字符串相同的字符串最后一行。 有时您还想设置盐,以创建可重现的结果,例如:

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

    【讨论】:

      【解决方案4】:

      这可能有点 hacky,但是您是否考虑过使用 exec() 函数来调用生成 htpasswd 的命令?

      【讨论】:

      • 是的,我确实在尝试避免使用任何系统调用。事实上,我这样做是为了完全取代它。如果我找不到其他方法,这将是我最后的手段。不过谢谢!
      【解决方案5】:

      看看这个:

      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>
      

      【讨论】:

        猜你喜欢
        • 2010-09-10
        • 2012-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-07
        • 1970-01-01
        • 2011-07-24
        • 2020-02-26
        相关资源
        最近更新 更多