简体   繁体   English

用于检查哈希等式的strcmp vs. == vs. ===在PHP中

[英]strcmp vs. == vs. === in PHP for checking hash equality

I'm using crypt() to hash passwords in PHP, and am trying to work out the safest way of testing equality of the resulting hash when performing password checks. 我正在使用crypt()在PHP中散列密码,并且我正在尝试在执行密码检查时找出最安全的方法来测试生成的散列的相等性。

There are three options that I can see: 我可以看到三个选项:

Option 1 - Double Equals 选项1 - 双等于

function checkPassword($hash, $password)
{
    return crypt($password, $hash) == $hash;
}

Option 2 - Triple Equals 选项2 - 三等于

function checkPassword($hash, $password)
{
    return crypt($password, $hash) === $hash;
}

Option 3 - strcmp() 选项3 - strcmp()

function checkPassword($hash, $password)
{
    return strcmp(crypt($password, $hash), $hash) === 0;
}

My intuition tells me that option 1 is a bad idea, due to the lack of type checking, and that options 2 or 3 are likely to be better. 我的直觉告诉我,由于缺乏类型检查,选项1是一个坏主意,选项2或3可能更好。 However, I can't work out if there's a specific case that === or strcmp would fail under. 但是,如果存在===strcmp失败的特定情况,我strcmp Which is safest for this purpose? 哪个是最安全的?

When it comes to security I prefer to use the === operator. 说到安全性,我更喜欢使用===运算符。 === ensures the two operands are exactly the same, without trying to accomodate some casting in order to "help" the comparison to reach a successful match - as it may help while developing thanks to a loose-typed language, like PHP. ===确保两个操作数完全相同,而不是试图容纳一些转换以“帮助”比较以达到成功匹配 - 因为它可能有助于在开发时感谢松散类型的语言,如PHP。

Of course, one of the operand is to be trusted. 当然,其中一个操作数是可信的。 A hash from the database is trustable, while the user input is not. 数据库中的哈希是可信的,而用户输入则不可信。

One can always dither for a while, coming to the conclusion there is no risk using == in a specific case. 总有一段时间可以抖动,得出结论在特定情况下使用==没有风险。 Maybe. 也许。 But for instance 但举个例子

  "0afd9f7b678fdefca" == 0 is true
  "aafd9f7b678fdefca" == 0 is also true

as PHP tries to convert the "hash" into a number (probably using atoi ) which gives 0. While it is unlikely crypt returns 0, I'd prefer to maximize the cases where the passwords don't match (and answer a support call) by using === , than allowing a rare case that I didn't think about by using == . 因为PHP试图将“哈希”转换为一个数字(可能使用atoi ),它给出0.尽管crypt不可能返回0,但我更愿意最大化密码不匹配的情况(并回答支持调用) )通过使用=== ,而不是通过使用==允许我没有考虑的罕见情况。

As for strcmp , the function returns <0 or >0 if different, and 0 if equal. 至于strcmp ,如果不同,函数返回<0>0 ,如果相等,则返回<0 But

  strcmp("3", 0003) returns 0
  strcmp("0003", 0003) returns -3

which are not surprising after all. 毕竟这并不奇怪。 A literal 0003 is actually an integer, 3 and since strcmp expects a string, the 3 will be converted to "3" . 文字0003实际上是一个整数, 3并且因为strcmp需要一个字符串,所以3将被转换为"3" But that shows there is some conversion that may happen in this case, since strcmp is a function, while === is part of the language. 但是这表明在这种情况下可能会发生一些转换,因为strcmp是一个函数,而===是语言的一部分。

So my preference in that case goes to === (which is faster than == anyway). 所以我在这种情况下的偏好是=== (反正比==更快)。

You should be using the hash_equals() function that is built into PHP. 您应该使用PHP内置的hash_equals()函数。 There would be no need to make your own function. 没有必要自己动手。 The hash_equals() will return a boolean value. hash_equals()将返回一个布尔值。

In my opinion it is usually NOT a good idea to use == or === for comparing strings let alone hashed strings. 在我看来,使用==或===来比较字符串,更不用说散列字符串通常不是一个好主意。

That is incorrect, please look at the definition of the function. 这是不正确的,请查看函数的定义。 According to PHP: 根据PHP:

Returns < 0 if str1 is less than str2;

> 0 if str1 is greater than str2,

and 0 if they are equal

It returns less than 0 if str1 is less than str2. 如果str1小于str2,则返回小于0。 Note the phrase "less than", it does not return just -1, but any negative value. 注意短语“小于”,它不仅返回-1,而是返回任何负值。 The same happens when str1 is greater than str2, but it returns a positive, non-zero value. 当str1大于str2时会发生同样的情况,但它返回一个正的非零值。 It returns a positive value that can be 1, or any number thereafter. 它返回一个正值,可以是1,或之后的任何数字。

strcmp() returns a number that is the difference between the two strings starting with the last character that was found to be similar. strcmp()返回一个数字,它是两个字符串之间的差异,从发现相似的最后一个字符开始。

Here is an example: 这是一个例子:

$output = strcmp("red", "blue");

The variable $output with contain a value of 16 变量$ output with包含值16

I think that using == would be sufficient in your case. 我认为在你的情况下使用==就足够了。

== checks for equality regardless of type, whereas === checks for equality as well as type. ==无论类型如何都检查相等性,而===检查相等性和类型。

1 == "1" = True 1 == "1" =真

1 === "1" = False 1 === "1" =假

Since we're not too concerned with type, I'd keep it simple and go with == . 既然我们不太关心类型,我会保持简单并使用==

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM