Регулярное выражение для анализа или проверки данных Base64



можно ли использовать регулярное выражение для проверки или очистки данных Base64? Это простой вопрос, но факторы, которые управляют этим вопросом, - это то, что затрудняет его.




у меня есть декодер Base64, который не может полностью полагаться на входные данные, чтобы следовать спецификациям RFC. Итак, проблемы, с которыми я сталкиваюсь, - это проблемы, такие как, возможно, данные Base64, которые не могут быть разбиты на 78 (я думаю, что это 78, мне нужно будет дважды проверить RFC, поэтому не динь мне, если точное число неверно) строки символов, или что строки не могут заканчиваться в CRLF; в том, что он может иметь только CR, или LF, или, возможно, ни то, ни другое.



Итак, у меня было чертовски много времени для анализа данных Base64, отформатированных как таковые. Из-за этого такие примеры, как следующие, становятся невозможными для надежного декодирования. Я буду отображать только частичные заголовки MIME для краткости.



Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu


хорошо, так что разбор это не проблема, и это именно тот результат, который мы ожидаем. И в 99% случаев, используя любой код, по крайней мере убедитесь, что каждый символ в буфере является допустимым символом base64, работает отлично. Но, следующий пример бросает ключ в смесь.



Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu


Это версия кодировки Base64, которую я видел в некоторых вирусах и других вещах, которые пытаются воспользоваться некоторыми почтовыми читателями, желающими любой ценой разобрать mime, по сравнению с теми, которые идут строго по книге или, скорее, RFC; если хотите.



Мой декодер Base64 декодирует второй пример в следующий поток данных. И имейте в виду, что исходный поток-это все данные ASCII!



[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8


у кого-нибудь есть хороший способ решить обе проблемы сразу? Я не уверен, что это даже возможно, кроме выполнения двух преобразований данных с различными применяемыми правилами и сравнения результатов. Однако если вы приняли такой подход, какой выход Вы доверяете? Кажется, что эвристика ASCII-это лучшие решение, но сколько еще кода, времени выполнения и сложности это добавит к чему-то как сложно, как антивирусный сканер, в котором этот код на самом деле участвует? Как бы вы обучили эвристический движок, чтобы узнать, что приемлемо Base64, а что нет?





обновление:



Do чтобы количество просмотров этого вопроса продолжало расти, я решил опубликовать простое регулярное выражение, которое я использую в приложении C# уже 3 года, с сотнями тысяч транзакций. Честно говоря, мне нравится ответ, данный Гамбо самое лучшее, именно поэтому я выбрал его в качестве выбранного ответа. Но для всех, кто использует C#, и ищет очень быстрый способ, по крайней мере, определить, содержит ли строка или байт[] допустимые данные Base64 или нет, я обнаружил, что следующее работает очень хорошо для меня.



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


и да, это только для строка данных Base64, не правильно отформатированных RFC1341 сообщение. Так что, если вы имеете дело с данными такого типа, Пожалуйста, примите это учтите, прежде чем пытаться использовать вышеуказанное регулярное выражение. Если вы имеете дело с Base16, Base32, Radix или даже Base64 для других целей (URL-адреса, имена файлов, кодировка XML и т. д.), то это очень рекомендуем Вам прочитать RFC4648 это Гамбо упомянутый в его ответе, поскольку вам нужно хорошо знать кодировку и Терминаторы, используемые реализацией, прежде чем пытаться использовать предложения в этом наборе вопросов/ответов.

841   4  

4 ответов:

С RFC 4648:

базовое кодирование данных используется во многих ситуациях для хранения или передачи данных в средах, которые, возможно, по устаревшим причинам, ограничены данными US-ASCII.

Так это зависит от цели использования закодированных данных, если эти данные должны рассматриваться как опасные.

но если вы просто ищете регулярное выражение, чтобы соответствовать Base64 закодированных слов, вы можете использовать следующее:

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

не ":" или ". " появится в действительном 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 в кодировке base64 objfunc для сайте StackOverflow.

самое лучшее выражение, которое я мог найти до сих пор здесь 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');
};

Comments

    Ничего не найдено.