Existe uma maneira no C # para ver se uma string está codificada na Base 64, além de apenas tentar convertê-la e ver se há algum erro? Eu tenho código de código como este:
// Convert base64-encoded hash value into a byte array.
byte[] HashBytes = Convert.FromBase64String(Value);
Desejo evitar a exceção "Caractere inválido em uma seqüência de caracteres Base-64" que ocorre se o valor não for uma string base 64 válida. Quero apenas verificar e retornar false em vez de manipular uma exceção, porque espero que, às vezes, esse valor não seja uma cadeia de base 64. Existe alguma maneira de verificar antes de usar a função Convert.FromBase64String?
Obrigado!
Atualização:
Obrigado por todas as suas respostas. Aqui está um método de extensão que você pode usar até agora, para garantir que sua string seja aprovada em Convert.FromBase64String sem uma exceção. O .NET parece ignorar todos os espaços finais e finais ao converter para a base 64, para que "1234" seja válido e "1234"
public static bool IsBase64String(this string s)
{
s = s.Trim();
return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);
}
Para aqueles que se perguntam sobre o desempenho dos testes versus captura e exceção, na maioria dos casos, para essa coisa de base 64, é mais rápido verificar do que capturar a exceção até atingir um determinado comprimento. Quanto menor o comprimento, mais rápido é
Em meus testes muito pouco científicos: para 10000 iterações para caracteres de 100.000 a 110000, era 2,7 vezes mais rápido testar primeiro.
Para 1000 iterações para caracteres de 1 a 16 caracteres para um total de 16.000 testes, foi 10,9 vezes mais rápido.
Estou certo de que há um ponto em que se torna melhor testar com o método baseado em exceção. Só não sei em que ponto.
fonte
=
sinal. Se o preenchimento estiver errado, ocorrerá um erro, mesmo que a entrada corresponda a uma expressão.\n\fLE16
- seu método produziria um falso positivo para isso. Para quem lê e procura um método infalível; Eu recomendaria capturar o FormatException ou usar um RegEx adequado às especificações, consulte stackoverflow.com/questions/475074/… .@"^[a-zA-Z0-9\+/]*={0,2}$"
Respostas:
É muito fácil reconhecer uma string Base64, pois ela será composta apenas de caracteres
'A'..'Z', 'a'..'z', '0'..'9', '+', '/'
e geralmente é preenchida no final com até três '=', para tornar o comprimento múltiplo de 4. Mas, em vez de compará-las, você ' d seria melhor ignorar a exceção, se ela ocorrer.fonte
Use Convert.TryFromBase64String do C # 7.2
fonte
Convert.TryFromBase64String(base64.PadRight(base64.Length / 4 * 4 + (base64.Length % 4 == 0 ? 0 : 4), '='), new Span<byte>(new byte[base64.Length]), out _)
. Obrigado.Eu sei que você disse que não queria pegar uma exceção. Mas, como capturar uma exceção é mais confiável, irei adiante e publicarei esta resposta.
Atualização: atualizei a condição graças ao oybek para melhorar ainda mais a confiabilidade.
fonte
base64String.Contains
várias vezes pode resultar em baixo desempenho, porbase64String
ser uma string grande.base64String== null || base64String.Length == 0
comstring.IsNullOrEmpty(base64String)
Eu acredito que o regex deve ser:
Combinando apenas um ou dois sinais '=' à direita, não três.
s
deve ser a sequência que será verificada.Regex
faz parte doSystem.Text.RegularExpressions
espaço para nome.fonte
Por que não capturar a exceção e retornar False?
Isso evita sobrecarga adicional no caso comum.
fonte
Por uma questão de integridade, quero fornecer alguma implementação. De um modo geral, o Regex é uma abordagem cara, especialmente se a string for grande (o que acontece ao transferir arquivos grandes). A abordagem a seguir tenta primeiro as formas mais rápidas de detecção.
EDITAR
Conforme sugerido por Sam , você também pode alterar um pouco o código fonte. Ele fornece uma abordagem com melhor desempenho para a última etapa dos testes. A rotina
pode ser usado para substituir a
if (!Base64Chars.Contains(value[i]))
linha porif (IsInvalid(value[i]))
O código fonte completo com aprimoramentos de Sam será parecido com este (comentários removidos para maior clareza)
fonte
A resposta deve depender do uso da string. Há muitas seqüências de caracteres que podem ser "base64 válidas" de acordo com a sintaxe sugerida por vários pôsteres, mas que podem decodificar "corretamente", sem exceção, para lixo. Exemplo: a sequência 8char
Portland
é Base64 válida. Qual é o sentido de afirmar que isso é Base64 válido? Eu acho que em algum momento você gostaria de saber que essa string deve ou não ser decodificada em Base64.No meu caso, eu tenho cadeias de conexão Oracle que podem estar em texto sem formatação como:
ou em base64 como
Eu só tenho que verificar a presença de um ponto e vírgula, porque isso prova que NÃO é base64, que é obviamente mais rápido do que qualquer método acima.
fonte
Regras do futebol de Knibb High!
Isso deve ser relativamente rápido e preciso, mas admito que não fiz um teste completo, apenas alguns.
Isso evita exceções caras, regex e também evita o loop através de um conjunto de caracteres, em vez disso, usa intervalos ascii para validação.
fonte
fonte
Vou usar assim para não precisar chamar o método convert novamente
fonte
Decodifique, recodifique e compare o resultado com a sequência original
fonte
Imho isso não é realmente possível. Todas as soluções postadas falham em strings como "test" e assim por diante. Se eles puderem ser divididos por 4, não forem nulos ou vazios, e se tiverem um caractere base64 válido, serão aprovados em todos os testes. Isso pode ser muitas cordas ...
Portanto, não há outra solução real a não ser saber que essa é uma sequência codificada de base 64 . O que eu vim com isso é o seguinte:
Eu espero que a string decodificada comece com uma certa estrutura, então eu verifico isso.
fonte
Certo. Apenas certifique-se cada personagem está dentro
a-z
,A-Z
,0-9
,/
, ou+
, e as extremidades da corda com==
. (Pelo menos, essa é a implementação mais comum Base64. Você pode encontrar algumas implementações que usam caracteres diferentes de/
ou+
para os dois últimos caracteres.)fonte
Sim, como o Base64 codifica dados binários em seqüências ASCII usando um conjunto limitado de caracteres, você pode simplesmente verificá-lo com esta expressão regular:
/ ^ [A-Za-z0-9 \ = \ + \ / \ s \ n] + $ / s
que garantirá que a string contenha apenas AZ, az, 0-9, '+', '/', '=' e espaço em branco.
fonte
=
caractere no final. Se esse preenchimento for inválido, não será uma codificação base64 correta, mesmo que corresponda ao seu regex. Você pode demonstrar isso localizando uma string de base 64 com 1 ou 2=
no final, removendo-as e tentando decodificá-la.Eu sugeriria a criação de uma regex para fazer o trabalho. Você terá que procurar algo assim: [a-zA-Z0-9 + / =] Você também terá que verificar o comprimento da string. Não tenho certeza, mas tenho certeza de que, se alguma coisa for cortada (além do preenchimento "="), ela explodirá.
Ou melhor ainda, confira esta pergunta sobre o stackoverflow
fonte
Acabei de ter um requisito muito semelhante no qual deixo o usuário fazer alguma manipulação de imagem em um
<canvas>
elemento e, em seguida, envio a imagem resultante recuperada.toDataURL()
para o back-end. Eu queria fazer alguma validação do servidor antes de salvar a imagem e implementar umValidationAttribute
uso de parte do código de outras respostas:Como você pode ver, estou esperando uma string de tipo imagem / png, que é o padrão retornado
<canvas>
ao usar.toDataURL()
.fonte
Verifique Base64 ou sequência normal
bool público IsBase64Encoded (String str)
{
}
fonte
Todas as respostas foram digeridas em uma função que garante 100% de que seus resultados serão precisos.
1) Use a função como abaixo:
2) Abaixo está a função:
fonte
Gosto da ideia de uma verificação de expressão regular. Expressões regulares podem ser rápidas e, às vezes, salvar a sobrecarga de codificação. o inquérito original, teve uma atualização que fez exatamente isso. Acho, porém, que nunca posso assumir que as seqüências não seriam nulas. Eu expandiria a função Extension para verificar a cadeia de origem quanto a caracteres nulos ou apenas em espaço em branco.
fonte