将C(\ 0已终止)字符串转换为PHP字符串

时间:2010-10-27 17:41:37

标签: php c string substr strstr

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

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

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

似乎啰嗦,而且应该有一行函数调用,但我找不到它?

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

3 个答案:

答案 0 :(得分:9)

使用strstr

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

对于小于5.3.0的版本(第三个参数不可用)的丑陋解决方案使用strrevsubstrstrrchr函数代替:

$hashsalt8 = strrev(substr(strrchr(strrev($hashsalt8), "\0"), 1));

答案 1 :(得分:2)

永远不需要超过32个字节的填充权吗? (来自你的评论)

你可能会做这样的事情:

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

注意单引号而不是双引号,如果你使用双引号\x00似乎打破了preg:)

答案 2 :(得分:2)

strtok函数将在一次传递而不是两次传递中执行:

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

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

if ($hashsalt8[0] == "\0") {
  $hashsalt8 = '';
}
else {
  $hashsalt8 = strtok($hashsalt8, "\0");
}

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

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

$iv = strpos($hashsalt8, "\0");
if ($iv !== false) {
   $hashsalt8 = substr($hashsalt8, 0, $iv);
}