如何将'原始二进制数据'哈希存储在MySQL中?

时间:2009-06-02 00:56:56

标签: php mysql hash

我想在MySQL中存储散列密码,我正在使用PHP:

<?php
    $salt = '!£$%^&*()#';
    $username = 'abc';
    $password = '123';
    $hash = hash('sha1', $username . $salt . $password, true);
?>

hash()中的true参数将返回值作为原始二进制数据。但我不明白这究竟意味着什么。应该如何正确存储在MySQL中?

4 个答案:

答案 0 :(得分:5)

我找到了解决方案。

sha1()的正常(hexed)哈希长度始终为CHAR(40)。当你在php中返回一个哈希作为原始二进制数据时,它将返回一个字符串作为CHAR(20),保存50%的数据库空间,但仍然代表完全相同的值。这是因为可以将2个十六进制的字符压缩成1个字符,从而将其减半所需的空间。

因此将密码存储为CHAR(20)并使用* _bin校对。

答案 1 :(得分:3)

hash()函数的最后一个参数指示如何返回哈希值:

  • 作为原始二进制数据。这条路 你得到的直接输出 您正在使用的特定哈希函数,在本例中为sha1。
  • 或者作为包含相同原始二进制数据的十六进制表示的字符串。

它们都是相同的,仅在它们的表示方面有所不同。除非你有充分的理由,否则我建议您使用十六进制表示并将其作为字符串存储在数据库中。这样,调试问题就容易得多,因为您可以轻松打印出十六进制哈希值。

答案 2 :(得分:1)

如果您确实想在MySQL中存储原始二进制字符串,请声明列BINARY(16),如果它是已知的16字节固定长度,VARBINARY(32),如果它的长度可变为32字节,或二进制字段的BLOB类型之一,可能会很长(例如,BLOB高达64K,LONGBLOB高达4G。

答案 3 :(得分:-1)

执行此操作的“正常”方式AFAIK,是使用addslashes()函数。

e.g:

$hash = hash('sha1', $username . $salt . $password, true);
$query_safe_hash = addslashes($hash);
$query_safe_username = addslashes($username);
$query = "INSERT INTO DBTable(username, password) VALUES ('$query_safe_username', '$query_safe_hash')";
mysql_query($query) or die("Failed to store credentials!");

旁注:从加密最佳实践的角度来看,salt应该是已知的长度,应该是随机生成的,并且在存储到数据库之前预先添加到哈希中。像

这样的东西
$salt = generate_random_salt();
$query_safe_hash = addslashes($salt) . addslashes(hash('sha1', $salt . $username . $password, true);

然后,要验证用户的凭据,请检索存储的哈希值,删除斜杠,并从存储的哈希值的开头删除已知的salt长度,并使用相同的salt生成提供的凭据的哈希值,然后进行比较。这有助于加强您的哈希算法以抵御各种密码分析攻击(特别是差分密码分析)。