0

好吧,我花了几天时间研究这个,我不敢相信 Apache 原生支持的散列函数已经过时了。

我发现了几种方法来做到这一点,它们是 mod_perl 和 mod_authnz_external,它们都太慢了,因为只要调用受保护目录中的任何对象,apache 就会运行它。这意味着用户可能必须在单个会话中进行数百次身份验证。

有没有人设法让 Apache 使用比 MD5 和 SHA-1 更安全的东西,而无需将身份验证从 Apache 移开?Salted SHA-2 将是一个真正的奖励。

谢谢!

4

1 回答 1

3

如果你在 GNU/Linux 系统上使用过去 5 年左右发布的 glibc2 版本,你可以修改 htpasswd 的 crypt() 实现,在 salt 前面加上“$6$”,然后就很简单了作为:

 # htpasswd -d -c .htpasswd someusername

当 salt 以“$6$”开头时,glibc2 将使用 salted SHA-512,之后最多 16 个字符是 salt,范围为 [a-zA-Z0-9./]。

见 man 3 地穴。

我不知道有任何补丁可以支持这一点,但它应该是一个简单的补丁。

编辑:我还想提一下,如果您的攻击者足够坚定,那么一轮甚至加盐的 SHA-512 是易碎的。我建议并且在我能够编辑的大多数事情中使用 128000 轮带有 HMAC-SHA512 的 PBKDF2,但这将是一个非常广泛的编辑,除非您想将 htpasswd 与具有 PKCS5_PBKDF2_HMAC 的 openssl 链接起来() 功能。

编辑 2:此外,如果您有兴趣,使用 openssl 进行强散列并不难:

abraxas ~ # cat pbkdf2.c 

#include <string.h>
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/sha.h>

#define PBKDF2_SALT_PREFIX          "$pbkdf2sha512$"
#define PBKDF2_SALT_PREFIX_LENGTH   strlen(PBKDF2_SALT_PREFIX)
#define PBKDF2_PRF_ALGORITHM        EVP_sha512()
#define PBKDF2_DIGEST_LENGTH        SHA512_DIGEST_LENGTH
#define PBKDF2_SALT_LENGTH          32
#define PBKDF2_RESULT_LENGTH        PBKDF2_SALT_PREFIX_LENGTH + (2 * PBKDF2_DIGEST_LENGTH) + PBKDF2_SALT_LENGTH + 2
#define PBKDF2_ROUNDS               128000

void hash_password(const char* pass, const unsigned char* salt, char* result)
{
    unsigned int i;
    static unsigned char digest[PBKDF2_DIGEST_LENGTH];
    memcpy(result, PBKDF2_SALT_PREFIX, PBKDF2_SALT_PREFIX_LENGTH);
    memcpy(result + PBKDF2_SALT_PREFIX_LENGTH, salt, PBKDF2_SALT_LENGTH);
    result[PBKDF2_SALT_PREFIX_LENGTH + PBKDF2_SALT_LENGTH] = '$';
    PKCS5_PBKDF2_HMAC(pass, strlen(pass), salt, PBKDF2_SALT_LENGTH, PBKDF2_ROUNDS, PBKDF2_PRF_ALGORITHM, PBKDF2_DIGEST_LENGTH, digest);
    for (i = 0; i < sizeof(digest); i++)
        sprintf(result + PBKDF2_SALT_PREFIX_LENGTH + PBKDF2_SALT_LENGTH + 1 + (i * 2), "%02x", 255 & digest[i]);
}

int main(void)
{
    char result[PBKDF2_RESULT_LENGTH];
    char pass[] = "password";
    unsigned char salt[] = "178556d2988b6f833f239cd69bc07ed3";
    printf("Computing PBKDF2(HMAC-SHA512, '%s', '%s', %d, %d) ...\n", pass, salt, PBKDF2_ROUNDS, PBKDF2_DIGEST_LENGTH);
    memset(result, 0, PBKDF2_RESULT_LENGTH);
    hash_password(pass, salt, result);
    printf("Result: %s\n", result);
    return 0;
}

abraxas ~ # gcc -Wall -Wextra -O3 -lssl pbkdf2.c -o pbkdf2
abraxas ~ # time ./pbkdf2 

Computing PBKDF2(HMAC-SHA512, 'password', '178556d2988b6f833f239cd69bc07ed3', 128000, 64) ...
Result: $pbkdf2sha512$178556d2988b6f833f239cd69bc07ed3$3acb79896ce3e623c3fac32f91d4421fe360fcdacfb96ee3460902beac26807d28aca4ed01394de2ea37b363ab86ba448286eaf21e1d5b316149c0b9886741a7

real    0m0.320s
user    0m0.319s
sys 0m0.001s

abraxas ~ # 
于 2012-06-15T01:36:32.807 回答