Чи можна використовувати RegEx для перевірки чи дезінфекції даних 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, яку я бачив у деяких вірусах та інших речах, які намагаються скористатися перевагами деяких читачів пошти, які бажають розібрати мім будь-якою ціною, порівняно з тими, які суворо відповідають книзі, а точніше RFC; якщо хочете.
Мій декодер Base64 декодує другий приклад до наступного потоку даних. І майте на увазі тут, оригінальний потік - це всі дані ASCII!
[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
У когось є хороший спосіб вирішити обидві проблеми одночасно? Я не впевнений, що це навіть можливо, окрім двох перетворень даних із різними застосованими правилами та порівняння результатів. Однак якщо ви взяли такий підхід, якому результату ви довіряєте? Здається, що евристика ASCII - це найкраще рішення, але наскільки більше коду, часу виконання та складності додало б чогось такого складного, як сканер вірусів, до якого насправді бере участь цей код? Як би ви навчили евристичний механізм, щоб дізнатися, що є прийнятним Base64, а що ні?
ОНОВЛЕННЯ:
Зважаючи на кількість переглядів, яке це питання продовжує отримувати, я вирішив опублікувати простий RegEx, який я використовую в додатку C # вже 3 роки, із сотнями тисяч транзакцій. Чесно кажучи, мені найбільше подобається відповідь, яку дав Гамбо , саме тому я вибрав її як вибрану відповідь. Але для тих, хто використовує C # і шукає дуже швидкий спосіб принаймні виявити, чи містить рядок чи байт [] дійсні дані Base64 чи ні, я виявив, що наступне дуже добре для мене працює.
[^-A-Za-z0-9+/=]|=[^=]|={3,}$
І так, це як раз для STRING даних Base64, а неправильно відформатований RFC1341 повідомлення. Отже, якщо ви маєте справу з даними такого типу, будь ласка, врахуйте це, перш ніж намагатися використовувати вищевказаний RegEx. Якщо ви маєте справу з Base16, Base32, Radix або навіть Base64 для інших цілей (URL-адреси, імена файлів, кодування XML тощо), то настійно рекомендуємо прочитати RFC4648, про який Гамбо згадав у своїй відповіді, оскільки вам потрібно добре знати про набір символів та термінатори, що використовуються реалізацією, перед спробою використати пропозиції цього набору запитань / відповідей.
^
зовнішні дужки, як стартовий якор. Тим НЕ менше, набагато краще регулярний вираз, не отримуючи так складно , як загальноприйнятому відповідь буде^[-A-Za-z0-9+/]*={0,3}$