好的我写了我自己的SALT版本我称之为咸lol不要取笑我..无论如何我的脚本的注册部分如下工作100%正确。
//generate SALTY my own version of SALT and I likes me salt.. lol
function rand_string( $length ) {
$chars = "ABCDEFGHIJKLMNOPQRSTUWXYZabcdefghijklmnopqrstuwxyz1234567890";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
$salty = rand_string( 256 );
//generate my extra salty pw
$password = crypt('password');
$hash = $password . $salty;
$newpass = $hash;
//insert the data in the database
include ('../../scripts/dbconnect.php');
//Update db record with my salty pw ;)
// TESTED WITH AND WITHOUT SALTY
//HENCE $password and $newpass
mysql_query("UPDATE `Register` SET `Password` = '$password' WHERE `emailinput` = '$email'");
mysql_close($connect);
但是我的LOGIN脚本失败了。如果它的登录与否,我将它设置为TEST并回显。它总是返回FAILED。我进入DB并将加密的咸pw改为“TEST”,我获得了成功。所以我的问题是在我假设的LOGIN脚本中的某个地方。现在我不知道如何实现我的$ Salty。但也请注意,即使没有SALTY(只使用crypt存储我的通行证) - 我仍然无法成功登录。如果你要建议我使用河豚 - 注意我的webhost没有支持它,我不知道如何安装它。
这是我的登录脚本:
if (isset($_POST['formsubmitted']))
{
include ('../../scripts/dbconnect.php');
$username = mysql_real_escape_string($_POST['username']);
$password = crypt(mysql_real_escape_string($_POST['password']));
$qry = "SELECT ID FROM Register WHERE emailinput='$username' AND Password='$password'";
$result = mysql_query($qry);
if(mysql_num_rows($result) > 0)
{
echo 'SUCCESS';
//START SESSION
}
else
{
echo 'FAILED';
//YOU ARE NOT LOGGED IN
}
}
这次登录有什么问题?为什么不使用crypt /只存储crypt?
如何使其存储隐藏和随机生成的SALTY :)?
Ty advance
答案 0 :(得分:2)
每次运行此代码时,您将生成一个不同的salt值。因此,当首次存储密码时,您的盐将会(构成一些示例内容)abc
。你隐藏了你的密码(比如说它是123
,附上盐,最后是123abc
,你存储在数据库中。
当您下次尝试登录时,会生成一个新的随机盐(例如456
)。您加密密码,附加盐,现在您已经123456
。这是你的问题。现在你有两个完全不同的字符串,所以你的登录失败了。
您需要将盐与加密文本分开存储,以便稍后再次重新使用盐。这意味着您的登录脚本首先必须检索与尝试登录的用户相关联的盐,重新/加密他们输入的密码,并查看字符串是否匹配。
从更大的图片来看,你也错误地使用了盐渍。必须将salt添加到密码 BEFORE 您通过crypt运行密码。盐可以增加暴力破解密码的难度。 123
是一个简单的密码,但123big_long_ugly_salt_value
不是。
您所做的只是一些无用的随机数生成,只会增加您的CPU和存储开销,但不会增加安全性。
答案 1 :(得分:1)
所以在存储中你要加密'密码'然后追加$ salty(这是一个rand_string)
但是在密码比较之后,您正在加密$ _POST ['password'],而不是附加相同的随机字符串。所以他们不会是一样的。
不是随着每个密码存储过程随机生成盐,而是最终在某处存储盐,或者从以后再次确定会再次找到的某些东西创建盐,以便在再次登录时进行比较。
现在如何让这个工作的一些想法是你可以使用用户ID,或者如果你想让每个用户拥有不同的盐,你可以使用其他一些不会改变的信息。或者,如果这无关紧要,您可以使用自己的其他随机字符串来使用。
正如马克B在他的回答中所说,你应该在加密之前加盐。在真正没有保护密码之后追加它。
使用crypt函数时,您可以在函数调用中添加salt:
crypt($ password,$ salt);
我不会真的搞乱mysql_real_escape_string的密码,因为你正在加密它。由于你正在加密可能的顽皮字符串,因此没有任何关于注射的担忧。
答案 2 :(得分:0)
我会对您的代码进行以下调整:
function rand_string( $length ) {
// added period and slash to the alphabet
$chars = "ABCDEFGHIJKLMNOPQRSTUWXYZabcdefghijklmnopqrstuwxyz1234567890./";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
}
return $str;
}
// we need 22 random characters
$salty = rand_string(22);
// apply blowfish with cost := 13
$newpass = crypt($password, sprintf('$2y$%02d$%s', 13, $salty));
这使用Blowfish来哈希密码;力量13需要大约0.5秒完成,所以根据你的情况,你可能想减少它;可以为更新的密码更改费用。
盐与密码btw一起存储,因此不需要另外一列。
要从数据库验证密码,您必须先从相应的Register
行加载密码字段。
if (crypt($_POST['password'], $password_from_db) === $password_from_db) {
// success
} else {
// password didn't match
}
顺便说一下,比较函数经常变成一个恒定时间算法来防止定时攻击。
您的salty()
函数可以替换为以下等效函数以生成22个char长盐:
substr(strtr(base64_encode(openssl_pseudo_random_bytes(18)), '+', '.'), 0, 22);