【问题标题】:PHP pg_unescape_bytea producing different results on different machinesPHP pg_unescape_bytea 在不同的机器上产生不同的结果
【发布时间】: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_byteabase64_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


【解决方案1】:

我的直接猜测是,您在其中一台服务器上有一个旧的 libpq,无法正确处理 bytea 的十六进制编码。如果您要对 bytea 进行十六进制编码,您可以考虑直接在 PHP 中取消编码以节省您的工作量。

显然没有更多信息我们不能肯定地说,但是无论问题如何,PHP 中的简单解决方案是在返回的字符串的开头检查 \x,如果是,将其去掉,然后然后将十六进制转换为二进制。

【讨论】:

    猜你喜欢
    • 2018-03-27
    • 2020-09-17
    • 2016-10-05
    • 1970-01-01
    • 2016-10-15
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多