Pergunta

É possível usar um RegEx para validar, ou higienizar dados Base64? Essa é a pergunta simples, mas os fatores que impulsionam esta questão são o que tornam difícil.

Eu tenho um decodificador Base64 que não pode confiar plenamente com os dados introduzidos a seguir as especificações RFC. Assim, as questões que enfrentamos são questões como talvez dados Base64 que não pode ser dividido em 78 (eu acho que é 78, eu teria que verifique o RFC, por isso não ding me se o número exato é errado) personagem linhas, ou que as linhas podem não terminam em CRLF; na medida em que podem ter apenas um CR ou LF, ou talvez nenhum deles.

Então, eu tive um inferno de um tempo de análise de dados Base64 formatados como tal. Devido a isso, exemplos como o seguinte tornar-se impossível de descodificar de forma confiável. Eu só irá exibir cabeçalhos MIME parciais para a brevidade.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Ok, então a análise que não é problema, e é exatamente o resultado que seria de esperar. E em 99% dos casos, usando qualquer código para, pelo menos, verificar se cada caractere no buffer é um char base64 válido, funciona perfeitamente. Mas, o próximo exemplo lança uma chave inglesa na mistura.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Esta é uma versão do Base64 codificação que eu já vi em alguns vírus e outras coisas que tentam tirar proveito de alguns leitores de correio deseja analisar mime a todo o custo, contra os que vão estritamente pelo livro, ou melhor, RFC; Se você for.

descodificador Meu base 64 descodifica o segundo exemplo para o fluxo de dados seguinte. E ter em mente aqui, o fluxo original é todos os dados ASCII!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

Alguém tem uma boa maneira de resolver dois problemas de uma vez? Eu não tenho certeza que é mesmo possível, fora de fazer duas transformações sobre os dados com regras diferentes aplicadas, e comparar os resultados. No entanto, se você tomou essa abordagem, que saída você confia? Parece que heurísticas ASCII é sobre o melhor solução, mas quanto mais código, o tempo de execução, e da complexidade que isso add para algo tão complicado como um scanner de vírus, que este código é realmente envolvido? Como você preparar o motor de heurísticas para aprender o que é Base64 aceitável eo que não é?


UPDATE:

Do que o número de pontos de vista esta questão continua a receber, eu decidi postar o simples RegEx que eu tenho usado em uma aplicação C # para 3 anos, com centenas de milhares de transações. Honestamente, eu como a resposta dada por Gumbo o melhor, e é por isso que eu escolhi-o como o resposta selecionada. Mas para qualquer pessoa usando C #, e à procura de uma forma muito rápida para pelo menos detectar se uma string, ou byte [] contém dados Base64 válidos ou não, eu encontrei o seguinte para o trabalho muito bem para mim.

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

E sim, isso é apenas para um string dos dados Base64, não uma formatado corretamente RFC1341 mensagem. Então, se você está lidando com os dados deste tipo, por favor, levar isso em conta antes de tentar usar o acima RegEx. Se você está lidando com base16, Base32, Radix ou mesmo Base64 para outros fins (URLs, nomes de arquivos XML de codificação, etc.), então é altamente recomendamos que você leia RFC4648 que Gumbo mencionado na sua resposta como você precisa estar bem ciente do charset e terminadores usado pela implementação antes de tentar usar as sugestões nesta pergunta / set resposta.

Foi útil?

Solução

A partir da RFC 4648 :

codificação de base de dados é usado em muitas situações para armazenar ou transferir dados em ambientes que, talvez por razões de legado, são restritos aos dados US-ASCII.

Por isso, depende da finalidade do uso dos dados codificados se os dados devem ser considerados como perigosos.

Mas se você está apenas procurando uma expressão regular para coincidir com Base64 codificado palavras, você pode usar o seguinte:

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

Outras dicas

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

Este é bom, mas irá corresponder a uma String vazia

Este não corresponde string vazia:

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

Nem um ": " nem um " ." Aparecerá na Base64 válido, então eu acho que você pode jogar fora de forma inequívoca a linha http://www.stackoverflow.com. Em Perl, digamos, algo como

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

say decode_base64($sanitized_str);

pode ser o que quiser. Produz

Isto é simples ASCII Base64 para StackOverflow exmaple.

A melhor regexp que eu poderia encontrar até agora é aqui https://www.npmjs.com/package/base64-regex

que é na versão olhares atuais como:

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');
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top