Có thể sử dụng RegEx để xác thực hoặc làm sạch dữ liệu Base64 không? Đó là câu hỏi đơn giản, nhưng các yếu tố thúc đẩy câu hỏi này là những gì làm cho nó khó khăn.
Tôi có bộ giải mã Base64 không thể hoàn toàn dựa vào dữ liệu đầu vào để tuân theo các thông số kỹ thuật RFC. Vì vậy, các vấn đề tôi gặp phải là các vấn đề như có lẽ dữ liệu Base64 có thể không được chia thành 78 (tôi nghĩ đó là 78, tôi phải kiểm tra lại RFC, vì vậy đừng ding tôi nếu số chính xác bị sai) dòng, hoặc các dòng có thể không kết thúc bằng CRLF; trong đó nó có thể chỉ có CR, hoặc LF, hoặc có thể không.
Vì vậy, tôi đã rất mất thời gian phân tích cú pháp dữ liệu Base64 được định dạng như vậy. Do đó, các ví dụ như sau không thể giải mã một cách đáng tin cậy. Tôi sẽ chỉ hiển thị một phần tiêu đề MIME cho ngắn gọn.
Content-Transfer-Encoding: base64
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Ok, vì vậy việc phân tích cú pháp đó không có vấn đề gì và chính xác là kết quả mà chúng tôi mong đợi. Và trong 99% trường hợp, sử dụng bất kỳ mã nào để ít nhất xác minh rằng mỗi char trong bộ đệm là một char base64 hợp lệ, hoạt động hoàn hảo. Tuy nhiên, ví dụ tiếp theo ném một cờ lê vào hỗn hợp.
Content-Transfer-Encoding: base64
http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Đây là phiên bản mã hóa Base64 mà tôi đã thấy trong một số loại vi-rút và những thứ khác cố gắng lợi dụng một số người đọc thư mong muốn phân tích cú pháp kịch câm bằng mọi giá, so với những phiên bản hoàn toàn theo cuốn sách, hay đúng hơn là RFC; nếu bạn muốn.
Bộ giải mã Base64 của tôi giải mã ví dụ thứ hai cho luồng dữ liệu sau. Và hãy nhớ ở đây, luồng gốc là tất cả dữ liệu ASCII!
[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
Bất cứ ai có một cách tốt để giải quyết cả hai vấn đề cùng một lúc? Tôi không chắc điều đó thậm chí có thể xảy ra, ngoài việc thực hiện hai phép chuyển đổi trên dữ liệu với các quy tắc khác nhau được áp dụng và so sánh kết quả. Tuy nhiên, nếu bạn thực hiện cách tiếp cận đó, bạn tin tưởng đầu ra nào? Có vẻ như ASCII heuristics là giải pháp tốt nhất , nhưng có bao nhiêu mã, thời gian thực thi và độ phức tạp sẽ thêm vào một thứ phức tạp như máy quét vi-rút, mà mã này thực sự có liên quan? Bạn sẽ đào tạo công cụ heuristics như thế nào để tìm hiểu Base64 có thể chấp nhận được và điều gì không?
CẬP NHẬT:
Do số lượt xem mà câu hỏi này vẫn tiếp tục nhận được, tôi đã quyết định đăng RegEx đơn giản mà tôi đã sử dụng trong một ứng dụng C # trong 3 năm nay, với hàng trăm nghìn giao dịch. Thành thật mà nói, tôi thích câu trả lời do Gumbo đưa ra nhất, đó là lý do tại sao tôi chọn nó làm câu trả lời đã chọn. Nhưng đối với bất kỳ ai sử dụng C # và đang tìm kiếm một cách rất nhanh để ít nhất là phát hiện một chuỗi hoặc byte [] có chứa dữ liệu Base64 hợp lệ hay không, tôi thấy những điều sau đây hoạt động rất tốt cho tôi.
[^-A-Za-z0-9+/=]|=[^=]|={3,}$
Và có, đây chỉ dành cho STRING dữ liệu Base64, KHÔNG PHẢI là thông báo RFC1341 được định dạng đúng . Vì vậy, nếu bạn đang xử lý dữ liệu kiểu này, hãy tính đến điều đó trước khi cố gắng sử dụng RegEx ở trên. Nếu bạn đang đối phó với Base16, Base32, Radix hoặc thậm chí Base64 cho các mục đích khác (URL, tên file, XML Encoding, vv), sau đó nó được đánh giá cao đề nghị bạn đọc RFC4648 rằng Gumbo đề cập trong câu trả lời của mình như là bạn cần phải hiểu rõ biết về bộ ký tự và ký tự kết thúc được sử dụng bởi triển khai trước khi cố gắng sử dụng các gợi ý trong bộ câu hỏi / câu trả lời này.
^
bên ngoài dấu ngoặc, như một ký tự bắt đầu. Tuy nhiên, một nhiều regex tốt hơn, mà không nhận được phức tạp như câu trả lời được chấp nhận, sẽ là^[-A-Za-z0-9+/]*={0,3}$