当值匹配时,random_bytes的比较失败

时间:2017-02-26 21:58:09

标签: php php-7 nonce

这里简短而有趣。我可能在这里有些奇怪,但我现在已经失去了几个小时而无法找出问题所在。

我有一个产生nonce的函数,就像这样。它目前并不复杂,但更多的是对我来说是一个新概念的实验。我使用random_bytes作为PHP7 +的mcrypt_create_iv的自然继承者:

$token = random_bytes(16);

然后将其存储起来:

$session->add('nonce',$token);

(which is essentially....)
$_SESSION[$var] = $val;

同时以我的形式使用,如下所示:

<input name="token" type="hidden" value="<?=$token?>">

表单提交并通过一些验证,依此类推。作为其中的一部分,我检索两个值:

$token = $_POST['token'];
$nonce = $session->get('nonce');

然后我有一个进一步执行的验证点 - 只有在两个值匹配时才进行。问题是,我实际上无法让他们进行验证。这些当前输出都不是真的:

if(hash_equals($nonce, $token))
if($nonce === $token)

var_dump显示两者都是相同长度的字符串,但由于某种原因,它们不具有可比性。两个值看起来都匹配。

if(hash_equals($nonce, $nonce))

等于true(正如你所期望的那样),所以我只能假设其中一个值在此过程中被改变,可以通过$_POST或通过我的检索函数(实际上只读取)来自会议)。

我很感激任何有关这方面的帮助/建议 - 我要么忽略了一些显而易见的事情,要么对此缺乏经验。

1 个答案:

答案 0 :(得分:3)

并非所有随机字节值都直接在HTML中有效。如果字符串包含ascii字母和数字([0-9a-zA-z])的常规序列之外的值,则任何事情都可能发生,如果您不为HTML上下文转义它。如有必要,您可以使用htmlspecialchars来转义值,或者使用随机字节的散列或base64编码版本。

一个很好的例子是,如果"的ascii值包含在16个随机字节中,那么HTML属性将提前结束。 HTML并不非常喜欢控制序列(低ascii字符)或当前编码之外的字母(如果是UTF-8,则在跨多个字节查看时,任何高于127的值都需要是有效的UTF-8代码点)。