【发布时间】:2013-04-04 14:50:24
【问题描述】:
好的,所以这个问题与我之前提出的问题有关: Storing the output of openssl_random_pseudo_bytes in Postgres using php? I get an error: invalid byte sequence for encoding “UTF8”。已经回答了,但现在我遇到了另一个问题。
我使用openssl_random_pseudo_bytes 生成盐,然后将其添加到用户密码并散列整个内容。
然后我在盐上使用pg_escape_bytea,以便我可以将值插入/存储到 PostgreSQL 数据库中。这很好用。现在要在需要时检索盐,我从数据库中获取它,并在盐上使用pg_unescape_bytea 来获取用于创建散列密码的原始原始值。
现在我发现在另一台机器上,pg_unescape_bytea salt 值不同,即使运行完全相同的代码,使用相同版本的 PHP,来自同一个数据库。
这怎么可能?当然,如果在完全相同的数据库中运行相同的代码,它应该是相同的吗?
我不应该在插入后将盐从数据库中转义,也许它会以未转义的形式返回?
或者在将盐与密码结合之前,我是否应该先转义盐(使用pg_unescape_bytea 或base64_encode?)?
更新示例:
$password = 'mypassword';
$salt = openssl_random_pseudo_bytes(30);
$pepper = 'pepper';
// Perhaps I should be performing a pg_escape_bytea on the salt before doing this?
$password_hash = hash('sha512', $password . $salt . $pepper);
// Adds the user to the database
$result = $data->add($email, $password_hash, pg_escape_bytea($salt), $company_id, $role_id);
那么当从数据库中取盐时:
// ...some code
// ...last step when fetching the salt from the database.
$row = pg_fetch_assoc($result, 0);
$row = pg_unescape_bytea( $row['salt'] ); // This value outputted produces different results
另外,我应该注意:
在一台机器上,未转义后的盐看起来像 gobbledygook,像非 UTF 字符或其他东西,这是我在表示二进制时所期望的。
但在另一台机器上,未转义的盐看起来实际上与转义的盐相同。减去\
示例:
转义盐:\x34e21
未转义的盐:x34e21
版本:
PHP 版本:5.3.13
PostgreSQL 版本:9.1
【问题讨论】:
-
我看到了一些与 PHP 的
pg_escape_bytea相关的其他报告,这让我想知道它是否在做正确的事情,或者某些系统是否存在错误。您需要在两个服务器及其 Pg 驱动程序版本上检查bytea_output的设置,服务器可能正在生成hex并且过时的驱动程序不知道会发生这种情况,因此它将其解释为八进制转义。请显示输入和两个输出,以便我们知道您在处理什么。 -
我个人强烈建议您使用正确的参数化语句,而不是依赖
pg_escape函数和字符串连接。这样一来,驱动程序就可以处理所有的混乱并减少小错误导致潜在 SQL 注入漏洞的机会。 -
无论如何,请显示确切的代码、输入和输出、PHP 版本和 PostgreSQL 版本。
-
嗨,谢谢。请参阅代码示例。我会将我的所有代码移动到适当的参数化语句中,但我没有意识到它也会自动处理这样的事情?认为它在一般意义上更健壮并防止 SQL 注入。
-
确实不能专门为PHP说话;在区分字节序列和文本字符串的语言中,SQL 驱动程序通常可以检查传递的值并为服务器进行适当的转换。我刚刚研究了一下,发现 PHP 不区分无编码字节序列和文本字符串,所以很可能你必须使用不同的函数来设置字节和字符串参数。
标签: php postgresql