RegEx para analizar o validar los datos de Base64

¿Es posible usar un RegEx para validar o desinfectar los datos de Base64? Esa es la pregunta simple, pero los factores que impulsan esta pregunta son lo que lo hace difícil.

Tengo un decodificador Base64 que no puede confiar plenamente en los datos de entrada para seguir las especificaciones de RFC. Entonces, los problemas que enfrento son cuestiones como, tal vez, los datos de Base64 que pueden no estar divididos en 78 (creo que es 78, tendría que verificar dos veces el RFC, así que no me diga si el número exacto es incorrecto). líneas, o que las líneas no pueden terminar en CRLF; en que puede tener solo un CR, o LF, o quizás ninguno.

Por lo tanto, me ha costado muchísimo tiempo analizar datos de Base64 formateados como tales. Debido a esto, ejemplos como los siguientes se vuelven imposibles de descodificar de manera confiable. Solo mostraré encabezados MIME parciales por brevedad.

Content-Transfer-Encoding: base64 VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu 

Ok, entonces el análisis no es un problema, y ​​es exactamente el resultado que esperaríamos. Y en el 99% de los casos, usar cualquier código para, al menos, verificar que cada char en el búfer sea un carácter base64 válido, funciona perfectamente. Pero, el siguiente ejemplo arroja una llave en la mezcla.

 Content-Transfer-Encoding: base64 http://www.stackoverflow.com VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu 

Esta es una versión de la encoding Base64 que he visto en algunos virus y otras cosas que intentan aprovechar el deseo de algunos lectores de correo de analizar el mimo a toda costa, frente a los que se basan estrictamente en el libro, o más bien RFC; Si tu quieres.

Mi decodificador Base64 decodifica el segundo ejemplo para la siguiente secuencia de datos. Y tenga en cuenta aquí, ¡la transmisión original es toda la información ASCII!

 [0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D 2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8 

¿Alguien tiene una buena manera de resolver ambos problemas a la vez? No estoy seguro de que sea posible, aparte de hacer dos transformaciones en los datos con diferentes reglas aplicadas, y comparar los resultados. Sin embargo, si toma ese enfoque, ¿en qué producto confía? Parece que la heurística ASCII es la mejor solución, pero ¿cuánto más código, tiempo de ejecución y complejidad se agregarían a algo tan complicado como un escáner de virus, en el que está realmente involucrado este código? ¿Cómo entrenarías el motor heurístico para aprender qué es un Base64 aceptable y qué no?


ACTUALIZAR:

Con respecto al número de vistas que sigue recibiendo esta pregunta, he decidido publicar el sencillo RegEx que he estado usando en una aplicación C # durante 3 años, con cientos de miles de transacciones. Honestamente, me gusta la respuesta dada por Gumbo lo mejor, por lo que la escogí como la respuesta seleccionada. Pero para cualquiera que use C #, y busque una forma muy rápida de detectar al menos si una cadena, o un byte [] contiene datos válidos de Base64 o no, he encontrado que lo siguiente funciona muy bien para mí.

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

Y sí, esto es solo para un STRING de datos de Base64, NO un mensaje RFC1341 debidamente formateado. Por lo tanto, si está tratando con datos de este tipo, tenga en cuenta eso antes de intentar usar el RegEx anterior. Si está tratando con Base16, Base32, Radix o incluso Base64 para otros fines (URL, nombres de archivos, encoding XML, etc.), le recomendamos encarecidamente que lea RFC4648 que Gumbo mencionó en su respuesta, ya que necesita estar bien. consciente del conjunto de caracteres y terminadores utilizados por la implementación antes de intentar usar las sugerencias en este conjunto de preguntas / respuestas.

Del RFC 4648 :

La encoding básica de datos se usa en muchas situaciones para almacenar o transferir datos en entornos que, tal vez por razones heredadas, están restringidos a los datos US-ASCII.

Por lo tanto, depende de la finalidad del uso de los datos codificados si los datos se consideran peligrosos.

Pero si solo busca una expresión regular que coincida con las palabras codificadas en Base64, puede usar lo siguiente:

 ^(?:[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}=)?$ 

Este es bueno, pero coincidirá con un String vacío

Esta no coincide con la cadena vacía:

 ^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$ 

Ni un ” : ” ni un ” . ” Se mostrarán en Base64 válido, por lo que creo que puede tirar inequívocamente la línea http://www.stackoverflow.com . En Perl, digamos, algo así como

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

podría ser lo que quieras Produce

Esto es simple ASCII Base64 para StackOverflow exmaple.

La mejor expresión regular que pude encontrar hasta ahora está aquí https://www.npmjs.com/package/base64-regex

que se encuentra en la versión actual se ve así:

 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'); };