É possível usar um RegEx para validar ou higienizar dados Base64? Essa é uma questão simples, mas os fatores que a motivam são os que a tornam difícil.
Eu tenho um decodificador Base64 que não pode confiar totalmente nos dados de entrada para seguir as especificações RFC. Então, os problemas que eu enfrento são problemas como talvez dados de Base64 que não podem ser divididos em 78 (eu acho que é 78, eu teria que verificar o RFC, então não me diga se o número exato estiver errado) caractere linhas, ou que as linhas não podem terminar em CRLF; no sentido de que pode ter apenas um CR, ou LF, ou talvez nenhum.
Então, eu tive um inferno de tempo ao analisar dados Base64 formatados como tal. Devido a isso, exemplos como o seguinte tornam-se impossíveis de decodificar de forma confiável. Exibirei apenas cabeçalhos MIME parciais por questões de brevidade.
Content-Transfer-Encoding: base64
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Ok, então analisar isso não é problema e é exatamente o resultado que esperaríamos. E em 99% dos casos, usar qualquer código para pelo menos verificar se cada caractere no buffer é um caractere base64 válido funciona perfeitamente. Mas, o próximo exemplo joga uma chave na mistura.
Content-Transfer-Encoding: base64
http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Esta é uma versão da codificação Base64 que vi em alguns vírus e outras coisas que tentam tirar vantagem do desejo de alguns leitores de e-mail de analisar a mímica a todo custo, em comparação com aquelas que seguem estritamente o livro, ou melhor, RFC; Se você for.
Meu decodificador Base64 decodifica o segundo exemplo para o seguinte fluxo de dados. E tenha em mente aqui, o stream original é todo de dados ASCII!
[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
Alguém tem uma boa maneira de resolver os dois problemas ao mesmo tempo? Não tenho certeza se isso é possível, além de fazer duas transformações nos dados com regras diferentes aplicadas e comparar os resultados. No entanto, se você adotou essa abordagem, em qual resultado você confia? Parece que a heurística ASCII é a melhor solução, mas quanto mais código, tempo de execução e complexidade isso acrescentaria a algo tão complicado quanto um scanner de vírus, no qual esse código está realmente envolvido? Como você treinaria o mecanismo de heurística para aprender o que é Base64 aceitável e o que não é?
ATUALIZAR:
Quanto ao número de visualizações que esta pergunta continua obtendo, decidi postar o RegEx simples que venho usando em um aplicativo C # há 3 anos, com centenas de milhares de transações. Honestamente, eu gosto mais da resposta dada por Gumbo , e é por isso que a escolhi como a resposta selecionada. Mas para qualquer pessoa que use C # e esteja procurando uma maneira muito rápida de pelo menos detectar se uma string ou byte [] contém dados Base64 válidos ou não, descobri que o seguinte funciona muito bem para mim.
[^-A-Za-z0-9+/=]|=[^=]|={3,}$
E sim, isso é apenas para uma STRING de dados Base64, NÃO uma mensagem RFC1341 formatada corretamente . Portanto, se você estiver lidando com dados desse tipo, leve isso em consideração antes de tentar usar o RegEx acima. Se você está lidando com Base16, Base32, Radix ou mesmo Base64 para outros fins (URLs, nomes de arquivos, codificação XML, etc.), então é altamente recomendável que você leia a RFC4648 que Gumbo mencionou em sua resposta, pois você precisa estar bem ciente do conjunto de caracteres e terminadores usados pela implementação antes de tentar usar as sugestões neste conjunto de perguntas / respostas.
^
fora dos colchetes, como uma âncora de início. No entanto, uma regex muito melhor, sem ficar tão complicada quanto a resposta aceita, seria^[-A-Za-z0-9+/]*={0,3}$