PHP是我定期使用的那种语言之一,但是当我再次开始使用它时,通常不得不将蜘蛛网弄脏。本周同样适用于我将一些C代码移植到PHP。这使用了大量的AES加密和SHA256散列 - 到目前为止一切正常。但是,解密的字符串以“C”形式出现 - 即以零字节后跟“垃圾”填充字节终止。
我目前正在使用以下内容将这些C风格的字符串“修剪”为PHP表单:
$iv = strpos( $hashsalt8, "\0");
if ($iv)
$hashsalt8 = substr( $hashsalt8, 0, $iv );
似乎啰嗦,而且应该有一行函数调用,但我找不到它?
注意:虽然在这种情况下“哈希盐”名称暗示我可能知道原始字符串的长度,但在一般情况下这是未知的。显然,当先验已知长度时,使用substr()
可以获得单行解决方案。
答案 0 :(得分:9)
使用strstr
:
$hashsalt8 = strstr($hashsalt8, "\0", TRUE);
对于小于5.3.0的版本(第三个参数不可用)的丑陋解决方案使用strrev
,substr
和strrchr
函数代替:
$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
将返回0
,if ($iv)
将失败。
您应该使用!==
运算符来区分0
和false
:
$iv = strpos($hashsalt8, "\0"); if ($iv !== false) { $hashsalt8 = substr($hashsalt8, 0, $iv); }