I have read a post here that utf8_bin gives us more accuracy on comparing characters while utf8_general_ci does not.
I wonder - if I have a table that stores usernames and passwords, and I need them to be exact or correct when the user logs in my website.
Then should I use utf8_bin for this purpose?
Thanks.
EDIT:
By the way, this is the hash function I use to has the password,
function hash_sha512($phrase,&$salt = null)
{
//$pepper = '!@#$%^&*()_+=-{}][;";/?<>.,';
if ($salt == '')
{
$salt = subst开发者_开发知识库r(hash('sha512',uniqid(rand(), true).PEPPER_KEY.microtime()), 0, SALT_LENGTH);
}
else
{
$salt = substr($salt, 0, SALT_LENGTH);
}
return hash('sha512',$salt.PEPPER_KEY.$phrase);
}
You're talking about the collation -- it's the characters the MySQL table will support. The "_ci" on a collation indicates that the collation is Case Insensitive. Meaning, "a" == "A" while in a case sensitive collation the example would evaluate to being false.
So yes, choosing a collation that is case sensitive will provide better accuracy. You can store the values using a case insensitive collation, but set a particular one for the query evaluation using the COLLATE function.
First on the issue of password storage... Since you seem to be using PHP (from your question history)... Salted sha1()
hashes just won't cut it in a world where renting a few AWS instances to compute fast rainbow tables... sha1()
is too fast.
Instead of trying your hand at do-it-yourself cryptology, why not trust libraries made by actual experts in the field? Use the Portable PHP password hashing framework.
PHPass actually uses bcrypt, which is an algorithm designed to prevent rainbow table, dictionary and brute force attacks. You can initialize it with a number of rounds: the higher the rounds, the longer it takes to compute the hash. That way, you can create stronger hashes if processing power increases.
Using it is simple:
require('PasswordHash.php');
$phpass = new PasswordHash(12, false); // Initiate for 12 rounds, using bcrypt
// Hash a password
$hash = $phpass->HashPassword('my secret password');
// Compare an hash to a given password
$formSupplied = 'hello world';
$isRight = $phpass->CheckPassword($formSupplied, $hash);
if($isRight) echo "Good";
else echo "Wrong";
Now on the subject of usernames... Store them using a _bin
collation (ie.: utf8_bin
). This will force MySQL to binary compare when during a WHERE
and effectively makes your usernames case-sensitive.
HOWEVER, since this is UTF-8, it is going to be important to normalize the username before inserting and querying your data. Different operating systems represent accented characters in different ways. PHP has the intl
extension which has a facility for UTF-8 normalization. The following should do:
$_POST['username'] = Normalizer::normalize($_POST['username']);
精彩评论