4

PHP 是我定期使用的那些语言之一,但当我再次开始使用它时,通常不得不把蜘蛛网弄掉。本周我将一些 C 代码移植到 PHP 时也是如此。这使用了大量的 AES 加密和 SHA256 散列 - 到目前为止一切正常。然而,解密后的字符串以“C”形式出现——即以零字节结尾,后跟“垃圾”填充字节。

我目前使用以下内容将这些 C 风格的字符串“修剪”为 PHP 形式:

$iv = strpos( $hashsalt8, "\0");
if ($iv)
   $hashsalt8 = substr( $hashsalt8, 0, $iv );

似乎冗长,应该有一个单行函数调用,但我找不到它?

注意:虽然在这种情况下,“哈希盐”名称暗示我可能知道原始字符串的长度,但这在一般情况下是未知的。substr()显然,当先验已知长度时,可以使用单行解决方案。

4

3 回答 3

9

使用strstr

$hashsalt8 = strstr($hashsalt8, "\0", TRUE);

低于 5.3.0 的版本(第三个参数不可用)的更丑陋的解决方案使用strrev,substrstrrchr函数代替:

$hashsalt8 = strrev(substr(strrchr(strrev($hashsalt8), "\0"), 1));
于 2010-10-27T17:50:23.070 回答
2

永远不需要超过 32 个字节的填充,对吧?(来自您的评论)

您可能可以执行以下操作:

preg_replace('/\x00.{0,32}$/', "", $hashsalt8);

注意单引号而不是双引号,如果您使用双引号,\x00似乎会破坏 preg :)

于 2010-10-27T18:11:43.177 回答
2

strtok函数将一次性完成,而不是两次:

$hashsalt8 = strtok($hashsalt8, "\0");

但是,从 PHP 4.1.0strtok开始,如果输入字符串以零字节开头,则不会返回空字符串。您可以执行以下操作来处理这种情况:

如果 ($hashsalt8[0] == "\0") {
  $hashsalt8 = '';
}
别的 {
  $hashsalt8 = strtok($hashsalt8, "\0");
}

请注意,以零字节开头的输入字符串也会暴露当前代码中的错误。在这种情况下,strpos将返回0if ($iv)失败。

您应该使用!==运算符来区分0false

$iv = strpos($hashsalt8, "\0");
如果 ($iv !== 假) {
   $hashsalt8 = substr($hashsalt8, 0, $iv);
}
于 2010-10-28T08:05:04.157 回答