我想在MySQL中存储散列密码,我正在使用PHP:
<?php
$salt = '!£$%^&*()#';
$username = 'abc';
$password = '123';
$hash = hash('sha1', $username . $salt . $password, true);
?>
hash()中的true参数将返回值作为原始二进制数据。但我不明白这究竟意味着什么。应该如何正确存储在MySQL中?
答案 0 :(得分:5)
我找到了解决方案。
sha1()的正常(hexed)哈希长度始终为CHAR(40)。当你在php中返回一个哈希作为原始二进制数据时,它将返回一个字符串作为CHAR(20),保存50%的数据库空间,但仍然代表完全相同的值。这是因为可以将2个十六进制的字符压缩成1个字符,从而将其减半所需的空间。
因此将密码存储为CHAR(20)并使用* _bin校对。
答案 1 :(得分:3)
hash()函数的最后一个参数指示如何返回哈希值:
它们都是相同的,仅在它们的表示方面有所不同。除非你有充分的理由,否则我建议您使用十六进制表示并将其作为字符串存储在数据库中。这样,调试问题就容易得多,因为您可以轻松打印出十六进制哈希值。
答案 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生成提供的凭据的哈希值,然后进行比较。这有助于加强您的哈希算法以抵御各种密码分析攻击(特别是差分密码分析)。