¿Cómo codifico y decodifico una cadena base64?

885
  1. ¿Cómo devuelvo una cadena codificada en base64 dada una cadena?

  2. ¿Cómo decodifico una cadena codificada en base64 en una cadena?

Kevin Driedger
fuente
44
Si se trata de una pregunta y respuesta para "compartir el conocimiento", creo que estamos buscando algo un poco más profundo. También aparece una búsqueda rápida de SO: stackoverflow.com/a/7368168/419
Kev
1
@Gnark Cualquier cadena está codificada por un cierto esquema de codificación de bits subyacente. Ya sea ASCII, UTF7, UTF8, .... La pregunta planteada es, en el mejor de los casos, incompleta.
Lorenz Lo Sauer
2
Pregúntate a ti mismo ¿realmente necesitas hacer esto? Recuerde que base64 está destinado principalmente a representar datos binarios en ASCII, para almacenar en un campo char en una base de datos o enviar por correo electrónico (donde podrían inyectarse nuevas líneas). ¿Realmente desea tomar datos de caracteres, convertirlos a bytes y luego volver a convertirlos en datos de caracteres, esta vez ilegibles y sin indicios de cuál era la codificación original?
bbsimonbb
¿Por qué debería importarnos la codificación original? Codificamos la cadena en los bytes usando la representación UTF8, que puede representar todos los caracteres de cadena posibles. Luego serializamos esos datos y en el otro extremo deserializamos esos datos y reconstruimos la misma cadena que teníamos originalmente (el objeto de cadena no contiene la información sobre la codificación utilizada de todos modos). Entonces, ¿por qué hay alguna preocupación relacionada con la codificación utilizada? Podemos considerarlo como una forma patentada de representar los datos serializados, en lo que no deberíamos estar interesados ​​de todos modos.
Mladen B.

Respuestas:

1668

Codificar

public static string Base64Encode(string plainText) {
  var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
  return System.Convert.ToBase64String(plainTextBytes);
}

Descodificar

public static string Base64Decode(string base64EncodedData) {
  var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
  return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
Kevin Driedger
fuente
41
Nulo comprueba las cadenas de entrada en ambas funciones y la solución es perfecta :)
Sverrir Sigmundarson
22
@SverrirSigmundarson: Eso o hacerlos métodos de extensión.
TJ Crowder
73
@SverrirSigmundarson - ¿Por qué hacer un cheque nulo? Él no es el que hace referencia a la cadena de entrada. Las comprobaciones nulas deben evitarse NullReferenceExceptionen su propio código, no en el de otra persona.
Ken
16
@ken Y alguien más dirá "solo debe exponer errores en su propio código, no en el de otra persona", invocando el principio de la menor sorpresa, aderezado con "fallar temprano" y "encapsulación adecuada". A veces esto significa errores de envoltura de componentes de nivel inferior, a veces algo completamente diferente. En este caso, estaré de acuerdo en que envolver un error deref es definitivamente dudoso (además, todos estamos lentamente de acuerdo con el hecho de que nulo como concepto es un poco complicado para empezar), pero aún podemos ver algunos efectos de lo contrario: el nombre del parámetro dado en la excepción podría no ser correcto si no se marca.
TNE
66
return System.Text.Encoding.UTF8.GetString (base64EncodedBytes, 0, base64EncodedBytes.Length); para windows phone 8
steveen zoleko
46

Estoy compartiendo mi implementación con algunas características interesantes:

  • utiliza métodos de extensión para la clase de codificación. La razón es que alguien puede necesitar soportar diferentes tipos de codificaciones (no solo UTF8).
  • Otra mejora está fallando con gracia con el resultado nulo para la entrada nula: es muy útil en escenarios de la vida real y admite equivalencia para X = decodificar (codificar (X)).

Observación: Recuerde que para usar el Método de extensión debe (!) Importar el espacio de nombres con la usingpalabra clave (en este caso using MyApplication.Helpers.Encoding).

Código:

namespace MyApplication.Helpers.Encoding
{
    public static class EncodingForBase64
    {
        public static string EncodeBase64(this System.Text.Encoding encoding, string text)
        {
            if (text == null)
            {
                return null;
            }

            byte[] textAsBytes = encoding.GetBytes(text);
            return System.Convert.ToBase64String(textAsBytes);
        }

        public static string DecodeBase64(this System.Text.Encoding encoding, string encodedText)
        {
            if (encodedText == null)
            {
                return null;
            }

            byte[] textAsBytes = System.Convert.FromBase64String(encodedText);
            return encoding.GetString(textAsBytes);
        }
    }
}

Ejemplo de uso:

using MyApplication.Helpers.Encoding; // !!!

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Test1();
            Test2();
        }

        static void Test1()
        {
            string textEncoded = System.Text.Encoding.UTF8.EncodeBase64("test1...");
            System.Diagnostics.Debug.Assert(textEncoded == "dGVzdDEuLi4=");

            string textDecoded = System.Text.Encoding.UTF8.DecodeBase64(textEncoded);
            System.Diagnostics.Debug.Assert(textDecoded == "test1...");
        }

        static void Test2()
        {
            string textEncoded = System.Text.Encoding.UTF8.EncodeBase64(null);
            System.Diagnostics.Debug.Assert(textEncoded == null);

            string textDecoded = System.Text.Encoding.UTF8.DecodeBase64(textEncoded);
            System.Diagnostics.Debug.Assert(textDecoded == null);
        }
    }
}
andrew.fox
fuente
55
Volver nullen caso de nulles un comportamiento muy inconsistente. Ninguna otra API .net que funciona con cadenas hace eso.
t3chb0t
44
@ t3chb0t no dude en ajustarlo a sus necesidades. Como la forma en que se presenta aquí se ajustó a la nuestra. Esta no es una API pública;)
andrew.fox
1
¿Ahora no tiene que enviar 2 variables a la otra parte en su comunicación (a quien está enviando datos codificados en base64)? ¿Necesita enviar tanto la codificación utilizada como los datos base64 reales? ¿No es más fácil si usa una convención en ambos lados para usar la misma codificación? De esa manera solo tendrías que enviar datos de base64, ¿verdad?
Mladen B.
38

Basado en las respuestas de Andrew Fox y Cebe, lo cambié y las hice extensiones de cadena en lugar de extensiones Base64String.

public static class StringExtensions
{
    public static string ToBase64(this string text)
    {
        return ToBase64(text, Encoding.UTF8);
    }

    public static string ToBase64(this string text, Encoding encoding)
    {
        if (string.IsNullOrEmpty(text))
        {
            return text;
        }

        byte[] textAsBytes = encoding.GetBytes(text);
        return Convert.ToBase64String(textAsBytes);
    }

    public static bool TryParseBase64(this string text, out string decodedText)
    {
        return TryParseBase64(text, Encoding.UTF8, out decodedText);
    }

    public static bool TryParseBase64(this string text, Encoding encoding, out string decodedText)
    {
        if (string.IsNullOrEmpty(text))
        {
            decodedText = text;
            return false;
        }

        try
        {
            byte[] textAsBytes = Convert.FromBase64String(text);
            decodedText = encoding.GetString(textAsBytes);
            return true;
        }
        catch (Exception)
        {
            decodedText = null;
            return false;
        }
    }
}
j2associates
fuente
1
Agregaría un ParseBase64 (este texto de cadena, codificación de codificación, texto de decodificación de cadena) (para completar la excepción si es necesario, y llamar a eso en TryParseBase64
João Antunes
22

Una ligera variación en la respuesta de andrew.fox, ya que la cadena para decodificar podría no ser una cadena codificada en base64 correcta:

using System;

namespace Service.Support
{
    public static class Base64
    {
        public static string ToBase64(this System.Text.Encoding encoding, string text)
        {
            if (text == null)
            {
                return null;
            }

            byte[] textAsBytes = encoding.GetBytes(text);
            return Convert.ToBase64String(textAsBytes);
        }

        public static bool TryParseBase64(this System.Text.Encoding encoding, string encodedText, out string decodedText)
        {
            if (encodedText == null)
            {
                decodedText = null;
                return false;
            }

            try
            {
                byte[] textAsBytes = Convert.FromBase64String(encodedText);
                decodedText = encoding.GetString(textAsBytes);
                return true;
            }
            catch (Exception)
            {
                decodedText = null;
                return false;   
            }
        }
    }
}
Cebe
fuente
13

Puede usar la siguiente rutina para convertir cadenas a formato base64

public static string ToBase64(string s)
{
    byte[] buffer = System.Text.Encoding.Unicode.GetBytes(s);
    return System.Convert.ToBase64String(buffer);
}

También puede usar una muy buena herramienta en línea OnlineUtility.in para codificar cadenas en formato base64

chetan chaphekar
fuente
Las herramientas en línea no ayudan en esta situación: está preguntando cómo CODIFICARLO. A menudo me pregunto por qué la gente dice "¡Mira esta herramienta en línea!", Porque el OP no pidió una herramienta en línea: D
Momoro
9
    using System;
    using System.Text;

    public static class Base64Conversions
    {
        public static string EncodeBase64(this string text, Encoding encoding = null)
        { 
            if (text == null) return null;

            encoding = encoding ?? Encoding.UTF8;
            var bytes = encoding.GetBytes(text);
            return Convert.ToBase64String(bytes);
        }

        public static string DecodeBase64(this string encodedText, Encoding encoding = null)
        {
            if (encodedText == null) return null;

            encoding = encoding ?? Encoding.UTF8;
            var bytes = Convert.FromBase64String(encodedText);
            return encoding.GetString(bytes);
        }
    }

Uso

    var text = "Sample Text";
    var base64 = text.EncodeBase64();
    base64 = text.EncodeBase64(Encoding.UTF8); //or with Encoding
Sameera R.
fuente
4

URL segura Base64 Codificación / Decodificación

public static class Base64Url
{
    public static string Encode(string text)
    {
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(text)).TrimEnd('=').Replace('+', '-')
            .Replace('/', '_');
    }

    public static string Decode(string text)
    {
        text = text.Replace('_', '/').Replace('-', '+');
        switch (text.Length % 4)
        {
            case 2:
                text += "==";
                break;
            case 3:
                text += "=";
                break;
        }
        return Encoding.UTF8.GetString(Convert.FromBase64String(text));
    }
}
juliushuck
fuente
1
La pregunta no se refería a la codificación de URL, pero seguía siendo útil .
Momoro
Whoops, lo publicó bajo la pregunta incorrecta
juliushuck
No hay problema, sigue siendo interesante ver cómo codificar / decodificar una URL :)
Momoro
3

Puedes mostrarlo así:

var strOriginal = richTextBox1.Text;

byte[] byt = System.Text.Encoding.ASCII.GetBytes(strOriginal);

// convert the byte array to a Base64 string
string strModified = Convert.ToBase64String(byt);

richTextBox1.Text = "" + strModified;

Ahora, convirtiéndolo de nuevo.

var base64EncodedBytes = System.Convert.FromBase64String(richTextBox1.Text);

richTextBox1.Text = "" + System.Text.Encoding.ASCII.GetString(base64EncodedBytes);
MessageBox.Show("Done Converting! (ASCII from base64)");

¡Espero que esto ayude!

Momoro
fuente
1

Para aquellos que simplemente quieren codificar / decodificar dígitos de base64 individuales:

public static int DecodeBase64Digit(char digit, string digit62 = "+-.~", string digit63 = "/_,")
{
    if (digit >= 'A' && digit <= 'Z') return digit - 'A';
    if (digit >= 'a' && digit <= 'z') return digit + (26 - 'a');
    if (digit >= '0' && digit <= '9') return digit + (52 - '0');
    if (digit62.IndexOf(digit) > -1)  return 62;
    if (digit63.IndexOf(digit) > -1)  return 63;
    return -1;
}

public static char EncodeBase64Digit(int digit, char digit62 = '+', char digit63 = '/')
{
    digit &= 63;
    if (digit < 52)
        return (char)(digit < 26 ? digit + 'A' : digit + ('a' - 26));
    else if (digit < 62)
        return (char)(digit + ('0' - 52));
    else
        return digit == 62 ? digit62 : digit63;
}

Hay varias versiones de Base64 que no están de acuerdo sobre qué usar para los dígitos 62 y 63, por lo que DecodeBase64Digitpueden tolerar varios de estos.

Qwertie
fuente