确定字符串是否是base64编码两次

时间:2018-04-04 12:18:39

标签: php regex base64

有没有办法确定字符串是否经过两次base64编码?

例如,是否有可以与preg_match一起使用的正则表达式模式来执行此操作?

1 个答案:

答案 0 :(得分:9)

(实际答案。) 不要使用正则表达式。使用base64_decode()的可选$strict参数设置为true解码您的字符串,看看它是否与您期望的格式匹配。或者只是在它允许的情况下尝试解码它多次。 E.g:

function base64_decode_multiple(string $data, int $count = 2) {
    while ($count-- > 0 && ($decoded = base64_decode($data, true)) !== false) {
        $data = $decoded;
    }
    return $data;
}

(理论答案。) 双基64编码字符串 是常规的,因为正确的字节数量有限base64编码base64编码的消息。

您可以检查某些内容是否为base64编码一次,因为您可以验证每组四个字符。 base64编码消息中的最后四个字节可能是一种特殊情况,因为=用作填充。)使用正则表达式:

<char>           := [A-Za-z0-9+/]
<end-char>       := [A-Za-z0-9+/=]
<chunk>          := <char>{4}
<end-chunk>      := <char>{2} <end-char>{2} | <char>{3} <end-char>
<base64-encoded> := <chunk>* <end-chunk>?

您还可以使用正则表达式确定某些内容是否为base64编码的两次,但解决方案并非简单或漂亮,因为它不足以一次检查4个字节。

示例:&#34; QUFBQQ ==&#34; base64-decodes to&#34; AAAA&#34; base64解码为三个NUL字节:

$ echo -n "QUFBQQ==" | base64 -d | xxd
00000000: 4141 4141                                AAAA

$ echo -n "AAAA" | base64 -d | xxd
00000000: 0000 00                                  ...

此时我们可以枚举所有的base-base64编码,其中base64编码是4个字节(&#34; AAAA&#34;,&#34; AAAB&#34;,&#34; AAAC&#34; ,&#34; AAAD&#34;等)并尽量减少这一点:

<ugly 4> := QUFBQQ== | QUFBQg== | QUFBQw== | QUFBRA== | ...

我们可以枚举所有double-base64编码的前4个字节,其中base64编码为8个字节或更长(不涉及=的情况)并最小化:

<chunk 4> := QUFB | QkFB | Q0FB | REFB | ...

双base64编码字符串的一个分区(漂亮的一个)最后不包含=个;它们的长度是8的倍数:

<pretty double-base64-encoded> := <chunk 4>{2}*

double-base64编码字符串的另一个分区的长度是4的倍数,但不是8(4,12,20等);他们可以被认为是漂亮的,最后有点丑陋:

<ugly double-base64-encoded> := <chunk 4>{2}* <ugly 4>

然后我们可以构造一个组合的正则表达式:

<double-base64-encoded> := <pretty double-base64-encoded>
                         | <ugly double-base64-encoded>

正如我所说,你可能不想仅仅因为双基64编码的消息 是常规的而经历所有这些混乱。就像你不想检查整数是否在某个区间内一样。此外,这是一个很好的例子,当你应该问另一个问题时得到错误的答案。 : - )

关于提出上述模式的一些想法:

  • 由于每个base64编码的字符串都有4个字节的倍数,因此每个double-base64编码的字符串必须解码为4个字节的倍数。例如,&#34; AAAA&#34;不能进行双基64解码,因为它只能解码为3个字节。 如何确定某些内容解码为4个字节的倍数?

  • 当消息的长度不是3的倍数时,base64编码的字符串会向上舍入到下一个4个字符的倍数。例如,编码&#34; AAAA&#34;,&#34; AAAAA&#34;和#A; AAAAAA&#34;全部需要8个字节。

  • 另一个例子:&#34; QUFBIQ ==&#34; base64-decodes to&#34; AAA!&#34;,这不是有效的base64编码;有四个字节,但&#34;!&#34;不在base64 table

  • 由于每个base64编码的字符串都匹配[A-Za-z0-9+/]{4}(最后四个字节是特殊情况),因此双base64编码的字符串只能使用4字节的子集来描述它们。 什么子集?

  • 我们知道&#34; QUFBQQ ==&#34;是一个有效的双base64编码和&#34; QUFB&#34;部分始终是前三个&#34; A&#34; s。但它们只是有效的双base64编码的一部分,后面跟着编码为匹配[A-Za-z0-9+/]的单个字符的东西; &#34; QQ ==&#34;解码为&#34; A&#34;,这样做很好。