RegEx解析或验证Base64数据

Lar*_*ryF 92 regex base64 standards-compliance rfc

是否可以使用RegEx来验证或清理Base64数据?这是一个简单的问题,但推动这个问题的因素是让它变得困难的因素.

我有一个Base64解码器,不能完全依赖输入数据来遵循RFC规范.所以,我面临的问题可能是Base64数据可能没有被分解成78个问题(我认为它是78,我必须仔细检查RFC,所以如果确切的数字是错误的话,请不要告诉我)线条,或线条可能不以CRLF结尾; 因为它可能只有CR,或LF,或者两者都没有.

所以,我有一段时间解析Base64数据格式化.因此,以下示例变得不可能可靠地解码.为简洁起见,我只会显示部分MIME标头.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Run Code Online (Sandbox Code Playgroud)

好的,所以解析没问题,这正是我们所期望的结果.在99%的情况下,使用任何代码来至少验证缓冲区中的每个字符都是有效的base64字符,完美地运行.但是,下一个例子会给混合物带来麻烦.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Run Code Online (Sandbox Code Playgroud)

我在一些病毒和其他试图利用某些邮件阅读器的东西中看到的Base64编码版本希望不惜一切代价解析mime,而不是严格按照本书,或者说RFC; 如果你愿意的话.

我的Base64解码器将第二个示例解码为以下数据流.请记住,原始流是所有ASCII数据!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
Run Code Online (Sandbox Code Playgroud)

任何人都有一个很好的方法来解决这两个问题?我不确定它是否可能,除了对应用了不同规则的数据进行两次转换,并比较结果之外.但是,如果您采用这种方法,您信任哪个输出?似乎ASCII启发式算法是最好的解决方案,但是代码,执行时间和复杂性会增加多少像病毒扫描程序一样复杂的东西,这个代码实际上涉及到什么?您如何训练启发式引擎以了解什么是可接受的Base64,什么不是?


更新:

对于这个问题继续得到的观点数量,我已经决定发布我已经在C#应用程序中使用的简单RegEx 3年了,有数十万个事务.老实说,我喜欢Gumbo给出的最好的答案,这就是我选择它作为选定答案的原因.但是对于任何使用C#的人来说,并且寻找一种非常快速的方法来至少检测字符串或byte []是否包含有效的Base64数据,我发现以下内容对我来说非常有用.

[^-A-Za-z0-9+/=]|=[^=]|={3,}$
Run Code Online (Sandbox Code Playgroud)

是的,这仅适用于Base64数据的STRING,而不是格式正确的RFC1341消息.因此,如果您正在处理此类数据,请在尝试使用上述RegEx之前将其考虑在内.如果您正在处理Base16,Base32,Radix甚至Base64用于其他目的(URL,文件名,XML编码等),那么强烈建议您阅读Gumbo在其答案中提到的RFC4648,因为您需要做得好在尝试使用此问题/答案集中的建议之前,请了解实现所使用的字符集和终止符.

Gum*_*mbo 132

来自RFC 4648:

在许多情况下,数据的基本编码用于在环境中存储或传输数据,这些环境可能由于传统原因而限于US-ASCII数据.

因此,如果数据应被视为危险,则取决于编码数据的使用目的.

但是,如果您只是寻找匹配Base64编码单词的正则表达式,则可以使用以下内容:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
Run Code Online (Sandbox Code Playgroud)

  • 最简单的解决方案是在验证之前去除所有空格(根据RFC忽略). (9认同)
  • 起初我对复杂性持怀疑态度,但它确实很有效.如果你只想匹配base64-ish我会想出^ [a-zA-Z0-9 + /] = {0,3} $,这样更好! (4认同)
  • @BogdanNechyporenko那是因为`name`是(十六进制)字节序列`9d a9 9e`的有效Base64编码. (3认同)
  • `^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0- 9+\/]{3}=|[A-Za-z0-9+\/]{4})$` 必须避免反冲 (3认同)
  • 填充的最后一个非捕获组是可选的. (2认同)
  • 我可以问一个让我发疯的问题吗?“ Paul”如何有效的base64? (2认同)

njz*_*zk2 33

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
Run Code Online (Sandbox Code Playgroud)

这个很好,但会匹配一个空字符串

这个与空字符串不匹配:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$
Run Code Online (Sandbox Code Playgroud)

  • 它不是.但是如果你使用正则表达式来确定给定的字符串是否是base64,那么你很可能对空字符串不感兴趣.至少我知道我不是. (8认同)
  • @ruslan也不应该.这不是有效的基本64字符串.(大小为23,不是// 4).`AQENVg688MSGlEgdOJpjIUC =`是有效的表格. (5认同)
  • @LayZee:如果你这样做,你强制base64字符串至少包含一个4大小的块,渲染有效的值,例如`MQ ==`与你的表达式不匹配 (3认同)
  • 为什么空字符串无效? (2认同)

Ped*_*eno 11

到目前为止给出的答案未能检查 Base64 字符串是否将所有填充位设置为 0,因为它是 Base64 的规范表示(这在某些环境中很重要,请参阅https://www.rfc-editor)。 org/rfc/rfc4648#section-3.5),因此,它们允许对同一二进制字符串使用不同编码的别名。在某些应用程序中这可能是一个安全问题。

下面的正则表达式验证给定的字符串不仅是有效的 Base64,而且还是二进制数据的规范 Base64 字符串:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/][AQgw]==|[A-Za-z0-9+/]{2}[AEIMQUYcgkosw048]=)?$
Run Code Online (Sandbox Code Playgroud)

引用的 RFC 认为空字符串有效(请参阅https://www.rfc-editor.org/rfc/rfc4648#section-10),因此上述正则表达式也是如此。

base64url 的等效正则表达式(再次参考上面的 RFC)是:

^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-][AQgw]==|[A-Za-z0-9_-]{2}[AEIMQUYcgkosw048]=)?$
Run Code Online (Sandbox Code Playgroud)


Jay*_*ini 6

为了验证Base64 图像,我们可以使用这个正则表达式

/^数据:图像/(?:gif|png|jpeg|bmp|webp)(?:;charset=utf-8)?;base64,(?:[A-Za-z0-9]|[+/] )+={0,2}

  private validBase64Image(base64Image: string): boolean {
    const regex = /^data:image\/(?:gif|png|jpeg|bmp|webp|svg\+xml)(?:;charset=utf-8)?;base64,(?:[A-Za-z0-9]|[+/])+={0,2}/;
    return base64Image && regex.test(base64Image);
  }
Run Code Online (Sandbox Code Playgroud)

  • `(?:[A-Za-z0-9]|[+/])` 可以简化为 `[A-Za-z0-9+/]` (2认同)

Pau*_*aul 6

这是一个替代的正则表达式:

^(?=(.{4})*$)[A-Za-z0-9+/]*={0,2}$
Run Code Online (Sandbox Code Playgroud)

它满足以下条件:

  • 字符串长度必须是四的倍数 -(?=^(.{4})*$)
  • 内容必须是字母数字字符或 + 或 / -[A-Za-z0-9+/]*
  • 它的末尾最多可以有两个填充 (=) 字符 -={0,2}
  • 它接受空字符串


oyl*_*gul 5

" : " 和 " . " 都不会出现在有效的 Base64 中,所以我认为你可以毫不含糊地丢弃该http://www.stackoverflow.com行。在 Perl 中,比如说,类似

my $sanitized_str = join q{}, grep {!/[^A-Za-z0-9+\/=]/} split /\n/, $str;

say decode_base64($sanitized_str);
Run Code Online (Sandbox Code Playgroud)

可能是你想要的。它产生

这是用于 StackOverflow 示例的简单 ASCII Base64。


Bog*_*nko 5

到目前为止我能找到的最好的正则表达式在这里 https://www.npmjs.com/package/base64-regex

当前版本中的内容如下所示:

module.exports = function (opts) {
  opts = opts || {};
  var regex = '(?:[A-Za-z0-9+\/]{4}\\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)';

  return opts.exact ? new RegExp('(?:^' + regex + '$)') :
                    new RegExp('(?:^|\\s)' + regex, 'g');
};
Run Code Online (Sandbox Code Playgroud)


Pau*_*l M 5

用于检查强制规范编码的 RFC-4648 合规性的最短正则表达式(即所有填充位设置为 0):

^(?=(.{4})*$)[A-Za-z0-9+/]*([AQgw]==|[AEIMQUYcgkosw048]=)?$
Run Code Online (Sandbox Code Playgroud)

实际上,这是这个那个答案的混合。