Czy można użyć wyrażenia regularnego do walidacji lub oczyszczenia danych Base64? To proste pytanie, ale czynniki, które napędzają to pytanie, sprawiają, że jest ono trudne.
Mam dekoder Base64, który nie może w pełni polegać na danych wejściowych, aby postępować zgodnie ze specyfikacjami RFC. Tak więc problemy, z którymi się spotykam, to problemy takie jak być może dane Base64, które mogą nie zostać podzielone na 78 (myślę, że to 78, musiałbym dwukrotnie sprawdzić RFC, więc nie daj mi znać, jeśli dokładna liczba jest błędna) znak linie lub że linie nie mogą kończyć się CRLF; w tym, że może mieć tylko CR lub LF, a może żadnego.
Miałem więc cholernie dużo czasu analizując sformatowane w ten sposób dane Base64. Z tego powodu niezawodne dekodowanie przykładów, takich jak poniższe, staje się niemożliwe. Dla zwięzłości wyświetlę tylko częściowe nagłówki MIME.
Content-Transfer-Encoding: base64
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Ok, więc parsowanie nie stanowi problemu i jest dokładnie takim wynikiem, jakiego byśmy oczekiwali. W 99% przypadków użycie dowolnego kodu przynajmniej do sprawdzenia, czy każdy znak w buforze jest prawidłowym znakiem base64, działa idealnie. Ale następny przykład rzuca klucz do miksu.
Content-Transfer-Encoding: base64
http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Jest to wersja kodowania Base64, którą widziałem w niektórych wirusach i innych rzeczach, które próbują wykorzystać to, że niektórzy czytelnicy poczty chcą analizować mime za wszelką cenę, w przeciwieństwie do tych, które ściśle przestrzegają tej książki, a raczej RFC; Jeśli będziesz.
Mój dekoder Base64 dekoduje drugi przykład do następującego strumienia danych. Pamiętaj, że oryginalny strumień to wszystkie dane ASCII!
[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
Czy ktoś ma dobry sposób na rozwiązanie obu problemów jednocześnie? Nie jestem pewien, czy jest to w ogóle możliwe, poza wykonaniem dwóch przekształceń danych z zastosowanymi różnymi regułami i porównaniem wyników. Jeśli jednak przyjmiesz takie podejście, którym wynikom ufasz? Wygląda na to, że heurystyka ASCII jest najlepszym rozwiązaniem, ale o ile więcej kodu, czasu wykonania i złożoności dodałoby to do czegoś tak skomplikowanego, jak skaner wirusów, w który ten kod jest faktycznie zaangażowany? Jak wyszkoliłbyś silnik heurystyczny, aby dowiedzieć się, co jest akceptowalnym Base64, a co nie?
AKTUALIZACJA:
Jeśli chodzi o liczbę wyświetleń, które nadal uzyskuje to pytanie, zdecydowałem się opublikować proste wyrażenie regularne, którego używam w aplikacji C # od 3 lat, z setkami tysięcy transakcji. Szczerze mówiąc, najbardziej podoba mi się odpowiedź udzielona przez Gumbo , dlatego wybrałem ją jako wybraną odpowiedź. Ale dla każdego, kto używa C # i szuka bardzo szybkiego sposobu, aby przynajmniej wykryć, czy ciąg znaków lub bajt [] zawiera prawidłowe dane Base64, czy nie, stwierdziłem, że poniższe elementy działają bardzo dobrze dla mnie.
[^-A-Za-z0-9+/=]|=[^=]|={3,}$
I tak, to jest po prostu na STRING danych Base64, a nie prawidłowo sformatowany RFC1341 wiadomości. Jeśli więc masz do czynienia z danymi tego typu, weź to pod uwagę przed próbą użycia powyższego wyrażenia regularnego. Jeśli masz do czynienia z Base16, Base32, Radix lub nawet Base64 do innych celów (adresy URL, nazwy plików, kodowanie XML itp.), To zdecydowanie zalecamy przeczytanie RFC4648, o którym Gumbo wspomniał w swojej odpowiedzi, ponieważ musisz być zdrowy świadomy zestawu znaków i terminatorów używanych przez implementację przed próbą użycia sugestii w tym zestawie pytań / odpowiedzi.
źródło
^
poza nawiasami klamrowymi, jako kotwicę początkową. Jednak znacznie lepszym wyrażeniem regularnym, bez komplikowania się, jak zaakceptowana odpowiedź, byłoby^[-A-Za-z0-9+/]*={0,3}$
Odpowiedzi:
Z RFC 4648 :
Zależy to więc od celu wykorzystania zakodowanych danych, czy dane te należy uznać za niebezpieczne.
Ale jeśli szukasz tylko wyrażenia regularnego pasującego do słów zakodowanych w standardzie Base64, możesz użyć następującego:
źródło
name
jest to prawidłowe kodowanie Base64 sekwencji bajtów (szesnastkowej)9d a9 9e
.^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$
musi uciec od reakcjiTen jest dobry, ale dopasuje pusty ciąg
Ten nie pasuje do pustego ciągu:
źródło
MQ==
brak dopasowania do wyrażeniaAQENVg688MSGlEgdOJpjIUC=
jest prawidłową formą.=
. Ostatni?
pozwala na 0=
. Zastąpienie go{1}
wymaga zakończenia 1 lub 2=
Ani „ : ”, ani „ . ” Nie pojawią się w prawidłowym Base64, więc myślę, że możesz jednoznacznie odrzucić tę
http://www.stackoverflow.com
linię. W Perlu powiedzmy coś takiegomoże być tym, czego chcesz. Produkuje
To jest prosty przykład ASCII Base64 dla StackOverflow.
źródło
Najlepsze wyrażenie regularne, jakie udało mi się do tej pory znaleźć, jest tutaj https://www.npmjs.com/package/base64-regex
który w aktualnej wersji wygląda następująco:
źródło
\\n?
.Aby sprawdzić poprawność obrazu base64 , możemy użyć tego wyrażenia regularnego
źródło
Oto alternatywne wyrażenie regularne:
Spełnia następujące warunki:
(?=^(.{4})*$)
[A-Za-z0-9+/]*
={0,2}
źródło