120

RegEx を使用して Base64 データを検証またはサニタイズすることは可能ですか? それは単純な質問ですが、この質問を難しくしている要因があります。

RFC 仕様に従うために入力データに完全に依存できない Base64 デコーダーがあります。したがって、私が直面している問題は、おそらく 78 に分割されない可能性のある Base64 データのような問題です (78 だと思います。RFC を再確認する必要があるため、正確な数が間違っていても気にしないでください)。行、または行が CRLF で終わっていない可能性があります。つまり、CR または LF のみを含むか、どちらも含まない可能性があります。

だから、私はそのようにフォーマットされたBase64データを解析するのにかなりの時間を費やしました. このため、次のような例は確実にデコードできなくなります。簡潔にするために、部分的な MIME ヘッダーのみを表示します。

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

わかりました。解析は問題なく、まさに期待どおりの結果です。そして、99% のケースで、任意のコードを使用して、少なくともバッファー内の各文字が有効な base64 文字であることを確認すると、完全に機能します。しかし、次の例では問題が発生しています。

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

この Base64 エンコーディングのバージョンは、一部のメール リーダーを利用しようとする一部のウイルスやその他のもので見られたバージョンであり、厳密に書籍または RFC に従っているものとは対照的に、すべての犠牲を払って MIME を解析したいと考えています。もしよろしければ。

私の Base64 デコーダーは、2 番目の例を次のデータ ストリームにデコードします。ここで、元のストリームはすべて ASCII データであることを覚えておいてください。

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

一度に両方の問題を解決する良い方法はありますか? 異なるルールを適用してデータに2つの変換を行い、結果を比較する以外に、それが可能かどうかさえわかりません。しかし、そのアプローチを採用した場合、どのアウトプットを信頼しますか? ASCII ヒューリスティックが最善の解決策であるように見えますが、このコードが実際に関与しているウイルス スキャナーのような複雑なものに、コード、実行時間、および複雑さがどれだけ追加されるのでしょうか? Base64 で許容できるものとそうでないものを学習するには、ヒューリスティック エンジンをどのようにトレーニングしますか?


アップデート:

この質問が引き続き取得するビューの数に合わせて、数十万のトランザクションで C# アプリケーションで 3 年間使用してきた単純な RegEx を投稿することにしました。正直なところ、Gumboからの回答が一番気に入っているので、選択した回答として選択しました。しかし、C# を使用していて、文字列または byte[] に有効な Base64 データが含まれているかどうかを少なくとも検出する非常に簡単な方法を探している人にとっては、次の方法が非常にうまく機能することがわかりました。

[^-A-Za-z0-9+/=]|=[^=]|={3,}$

はい、これはBase64 データのSTRINGのためのものであり、適切にフォーマットされたRFC1341メッセージではありません。したがって、このタイプのデータを扱う場合は、上記の正規表現を使用する前にそのことを考慮してください。他の目的 (URL、ファイル名、XML エンコーディングなど) で Base16、Base32、Radix、さらには Base64 を扱っている場合は、Gumboが回答で言及したRFC4648を読むことを強くお勧めします。この質問/回答セットの提案を使用する前に、実装で使用される文字セットとターミネータを認識してください。

4

8 に答える 8

170

RFC 4648から:

データのベース エンコーディングは、おそらく従来の理由で US-ASCII データに制限されている環境でデータを保存または転送するために、多くの状況で使用されます。

そのため、暗号化されたデータが危険とみなされるかどうかは、暗号化されたデータの使用目的によって異なります。

ただし、Base64 でエンコードされた単語に一致する正規表現を探しているだけの場合は、次を使用できます。

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
于 2009-01-24T00:40:53.653 に答える
41
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

これは良いですが、空の文字列に一致します

これは空の文字列と一致しません:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$
于 2011-05-04T14:33:26.517 に答える
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);

あなたが望むものかもしれません。それは生産します

これは、StackOverflow の例の単純な ASCII Base64 です。

于 2009-01-24T01:01:49.850 に答える
5

base64 イメージを検証するには、この正規表現を使用できます

/^data:image/(?: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);
  }
于 2020-05-06T07:46:51.357 に答える
4

私が今まで見つけた最高の正規表現はここにあり ます 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');
};
于 2015-03-26T09:33:03.747 に答える