0

我有登录系统

例如,Joe可以使用用户名登录joe而没有任何问题。

目前,我正在使用使用用户名作为盐的密码加密。这会造成登录问题。例如,

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`)
$stmt->bindValue(':username', $_POST['user']);

这工作正常。问题涉及密码:

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`)
   AND `password` = :password
$stmt->bindValue(':username', $_POST['user']);
$stmt->bindValue(':password', encrypt($_POST['password'], $_POST['user'])); //encrypt(password, salt)

如您所见,密码加密不会检查数据库,因为用户已登录joe而不是Joe

有没有解决方法,或者我应该使用其他东西作为盐?如果是这样,我应该用什么作为盐?这是我的加密功能:

function encrypt($password, $salt) {
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($salt), $password, MCRYPT_MODE_CBC, md5(md5($salt))));
}
4

4 回答 4

2

首先,strtolower($_POST['user'])用作盐有什么问题?看起来它会起作用。

现在一般来说,盐应该是不可预测的。用户名并不是真的那么不可预测,所以虽然这不会是世界末日,但如果您用随机生成的适度长度的字符串替换用户名(它不必是加密强度随机的,只是不可预测)。

这里最大的问题是使用 MD5,一段时间以来一直被认为是不安全的。如果您切换到其他哈希函数,安全性将会提高;SHA-1 并不是一个特别糟糕的选择(它确实有一个不受欢迎的特性:计算速度很快),但最适合此类应用的是具有可变负载因子的哈希函数,例如bcrypt.

于 2012-10-03T19:32:35.457 回答
2

这里有几个问题:

  1. 盐的大小写敏感性
  2. 您的密码“加密”方法

第一个问题是你所问的,所以让我们来看看。

因此,您的密码使用用户名加盐,并且您希望能够使用用户在登录期间输入的用户名作为加盐。如果您确定盐的标准化方案,这将起作用。不要在输入时使用它,而是在函数中使用它之前将其转换为小写或大写。

另一种选择是对数据库执行两个查询:一个是在存储用户名时提取用户名,第二个是实际检查密码。这不是最佳的,但它确实是你的麻烦中最少的。

有没有解决方法,或者我应该使用其他东西作为盐?如果是这样,我应该用什么作为盐?

既然你问了,让我们看看第二个问题:你的密码“加密”方法。

出于多种原因,尝试发明自己的密码散列/加密方案绝不是一个好主意。您最好的选择是使用已经被广泛接受的密码散列方案,例如 bcrypt 或 PBKDF2 的一些衍生产品。这些都很棒,因为它们都包括盐渍和键拉伸。它们被设计为很慢(相对而言,无论如何),因此暴力破解这些类型的哈希在计算上非常昂贵。

使用上述密码散列方案之一也将解决您的第一个问题,因为这些方案使用内置的每用户盐。根据您选择实施这些方案的方式,您将不需要(不应该)提供自己的盐。顶级库将为您生成盐。

尝试查看这些库以进行密码散列:

于 2012-10-03T19:52:53.017 回答
1

跳过 SQLlower并使用 PHP 的strtolower(). 这样,您的用户名将全面一致。

于 2012-10-03T19:32:39.257 回答
1

您遇到的问题是用户名不应用作盐的原因之一。哈希密码的更好方法是使用crypt(). 你只需要生成一个随机盐来使用它。它返回的字符串包含哈希和哈希算法,因此您可以根据需要更改算法或难度,而无需重写代码。只要您的哈希是 7 位安全的,整个字符串就会是安全的,所以您不需要base64_encode()任何东西。

于 2012-10-03T19:37:48.487 回答