¿Hay alguna manera en C # para ver si una cadena está codificada en Base 64, aparte de tratar de convertirla y ver si hay un error? Tengo un código de código como este:
// Convert base64-encoded hash value into a byte array.
byte[] HashBytes = Convert.FromBase64String(Value);
Quiero evitar la excepción "Carácter inválido en una cadena Base-64" que ocurre si el valor no es una cadena base 64 válida. Solo quiero verificar y devolver falso en lugar de manejar una excepción porque espero que a veces este valor no sea una cadena base 64. ¿Hay alguna forma de verificar antes de usar la función Convert.FromBase64String?
¡Gracias!
Actualización:
Gracias por todas sus respuestas. Aquí hay un método de extensión que todos pueden usar hasta ahora, parece asegurarse de que su cadena pasará Convert.FromBase64String sin una excepción. .NET parece ignorar todos los espacios finales y finales al convertir a base 64, por lo que "1234" es válido y también "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 aquellos que se preguntan sobre el rendimiento de las pruebas frente a la captura y la excepción, en la mayoría de los casos para esta cosa de base 64 es más rápido verificar que detectar la excepción hasta que alcance una cierta longitud. Cuanto menor es la longitud, más rápido es
En mis pruebas muy poco científicas: para 10000 iteraciones para la longitud de caracteres 100,000 - 110000, fue 2,7 veces más rápido probar primero.
Para 1000 iteraciones para caracteres de longitud 1 - 16 caracteres para un total de 16,000 pruebas, fue 10.9 veces más rápido.
Estoy seguro de que hay un punto en el que es mejor probar con el método basado en excepciones. Simplemente no sé en qué punto es eso.
fuente
=
signo. Si el relleno es incorrecto, dará un error aunque la entrada coincida con una expresión.\n\fLE16
: su método arrojaría un falso positivo para esto. Para cualquiera que lea y busque un método infalible; Recomendaría capturar la FormatException o usar un RegEx adecuado a las especificaciones, consulte stackoverflow.com/questions/475074/… .@"^[a-zA-Z0-9\+/]*={0,2}$"
Respuestas:
Es bastante fácil reconocer una cadena Base64, ya que solo estará compuesta de caracteres
'A'..'Z', 'a'..'z', '0'..'9', '+', '/'
y a menudo se rellena al final con hasta tres '=', para hacer que la longitud sea múltiplo de 4. Pero en lugar de compararlos, usted ' Sería mejor ignorar la excepción, si ocurre.fuente
Use Convert. tryFromBase64String desde C # 7.2
fuente
Convert.TryFromBase64String(base64.PadRight(base64.Length / 4 * 4 + (base64.Length % 4 == 0 ? 0 : 4), '='), new Span<byte>(new byte[base64.Length]), out _)
. Gracias.Sé que dijiste que no querías atrapar una excepción. Pero, dado que detectar una excepción es más confiable, seguiré adelante y publicaré esta respuesta.
Actualización: He actualizado la condición gracias a oybek para mejorar aún más la confiabilidad.
fuente
base64String.Contains
varias veces puede resultar en un bajo rendimiento en caso debase64String
ser una cadena grande.base64String== null || base64String.Length == 0
constring.IsNullOrEmpty(base64String)
Creo que la expresión regular debería ser:
Solo coincide con uno o dos signos '=' finales, no con tres.
s
debe ser la cadena que se verificará.Regex
es parte delSystem.Text.RegularExpressions
espacio de nombres.fuente
¿Por qué no capturar la excepción y devolver False?
Esto evita gastos generales adicionales en el caso común.
fuente
Solo en aras de la integridad, quiero proporcionar alguna implementación. En términos generales, Regex es un enfoque costoso, especialmente si la cadena es grande (lo que sucede al transferir archivos grandes). El siguiente enfoque intenta primero las formas más rápidas de detección.
EDITAR
Según lo sugerido por Sam , también puede cambiar ligeramente el código fuente. Proporciona un enfoque de mejor desempeño para el último paso de las pruebas. La rutina
se puede usar para reemplazar la
if (!Base64Chars.Contains(value[i]))
línea conif (IsInvalid(value[i]))
El código fuente completo con mejoras de Sam se verá así (comentarios eliminados para mayor claridad)
fuente
La respuesta debe depender del uso de la cadena. Hay muchas cadenas que pueden ser "base64 válida" de acuerdo con la sintaxis sugerida por varios carteles, pero que pueden decodificar "correctamente", sin excepción, la basura. Ejemplo: la cadena 8char
Portland
es válida Base64. ¿Cuál es el punto de afirmar que esto es válido Base64? Supongo que en algún momento querrás saber que esta cadena debería o no ser decodificada en Base64.En mi caso, tengo cadenas de conexión Oracle que pueden estar en texto plano como:
o en base64 como
Solo tengo que verificar la presencia de un punto y coma, porque eso prueba que NO es base64, que por supuesto es más rápido que cualquier método anterior.
fuente
Knibb High reglas de fútbol!
Esto debería ser relativamente rápido y preciso, pero admito que no lo sometí a una prueba exhaustiva, solo algunas.
Evita excepciones costosas, expresiones regulares, y también evita recorrer un conjunto de caracteres, en su lugar utiliza rangos ascii para la validación.
fuente
fuente
Usaré así para no tener que volver a llamar al método de conversión.
fuente
Decodifique, vuelva a codificar y compare el resultado con la cadena original
fuente
En mi humilde opinión esto no es realmente posible. Todas las soluciones publicadas fallan para cadenas como "prueba", etc. Si pueden dividirse entre 4, no son nulos o están vacíos, y si son un carácter base64 válido, pasarán todas las pruebas. Eso puede ser muchas cadenas ...
Por lo tanto, no hay una solución real que no sea saber que esta es una cadena codificada en base 64 . Lo que se me ocurrió es esto:
Espero que la cadena decodificada comience con una determinada estructura, así que verifico eso.
fuente
Por supuesto. Sólo asegúrese de que cada personaje está dentro
a-z
,A-Z
,0-9
,/
, o+
, y los extremos de cadena con==
. (Al menos, esa es la implementación de Base64 más común. Es posible que encuentre algunas implementaciones que usan caracteres diferentes/
o+
para los dos últimos caracteres).fuente
Sí, dado que Base64 codifica datos binarios en cadenas ASCII utilizando un conjunto limitado de caracteres, simplemente puede verificarlo con esta expresión regular:
/ ^ [A-Za-z0-9 \ = \ + \ / \ s \ n] + $ / s
lo que asegurará que la cadena solo contenga AZ, az, 0-9, '+', '/', '=' y espacios en blanco.
fuente
=
personaje al final. Si ese relleno no es válido, no es una codificación base64 correcta, aunque coincida con su expresión regular. Puede hacer una demostración de esto encontrando una cadena base 64 con 1 o 2=
al final, eliminándolas e intentando decodificarla.Sugeriría crear una expresión regular para hacer el trabajo. Tendrá que verificar algo como esto: [a-zA-Z0-9 + / =] También deberá verificar la longitud de la cadena. No estoy seguro de esto, pero estoy bastante seguro de que si algo se recorta (aparte del relleno "=") explotaría.
O mejor aún, mira esta pregunta de stackoverflow
fuente
Acabo de tener un requisito muy similar en el que dejo que el usuario realice alguna manipulación de imagen en un
<canvas>
elemento y luego envíe la imagen resultante recuperada.toDataURL()
al backend. Quería hacer una validación del servidor antes de guardar la imagen y he implementado unValidationAttribute
uso del código de otras respuestas:Como puede ver, estoy esperando una cadena de tipo imagen / png, que es el valor predeterminado que se devuelve
<canvas>
al usar.toDataURL()
.fuente
Verifique Base64 o cadena normal
public bool IsBase64Encoded (String str)
{
}
fuente
Todas las respuestas fueron digeridas en 1 función que garantiza al 100% que sus resultados serán precisos.
1) Use la función de la siguiente manera:
2) A continuación se muestra la función:
fuente
Me gusta la idea de un cheque de expresión regular. Las expresiones regulares pueden ser rápidas y a veces ahorran la sobrecarga de codificación. La consulta original, tenía una actualización que hizo justamente esto. Sin embargo, encuentro que nunca puedo asumir que las cadenas no serían nulas. Expandiría la función de Extensión para verificar que la cadena de origen no contenga caracteres nulos o en blanco.
fuente