web-dev-qa-db-ja.com

Base64データを解析または検証するRegEx

Reg64を使用してBase64データを検証またはサニタイズすることは可能ですか?それは簡単な質問ですが、この質問を駆動する要因はそれを困難にするものです。

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

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

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

わかりましたので、解析は問題ありませんし、まさに私たちが期待する結果です。そして、99%のケースでは、少なくともバッファー内の各文字が有効なbase64文字であることを検証するコードを使用して、完全に機能します。しかし、次の例では、レンチを組み合わせて使用​​しています。

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

これは、私がいくつかのウイルスや他の事柄で見たBase64エンコーディングのバージョンで、一部のメールリーダーを利用しようとするものです。もしそうなら。

私のBase64デコーダーは、2番目の例を次のデータストリームにデコードします。ここで、元のストリームはすべてASCII data!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

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


UPDATE:

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

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

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

86
LarryF

RFC 4648 から:

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

そのため、データが危険であると見なされるかどうかは、エンコードされたデータの使用目的に依存します。

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

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
125
Gumbo
^(?:[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})$
27
njzk2

有効なBase64には ""も ""も表示されないため、http://www.stackoverflow.com行を明確に破棄できると思います。 Perlでは、たとえば

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

say decode_base64($sanitized_str);

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

これは簡単ですASCII StackOverflow exmapleのBase64。

4
oylenshpeegul

これまでに見つけた最高の正規表現はここにあります 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');
};
2