c# - Descodificación Base32




.net (4)

Aquí está mi solución rápidamente anotada. Solo funciona en cadenas que son un múltiplo de 8 caracteres base32. Funciona, sin embargo.

public class Base32
{
  /// <summary>
  /// Decode a Base32 string
  /// This will only work on a multiple of 40 bits (5 bytes)
  /// http://www.garykessler.net/library/base64.html
  /// </summary>
  public static byte[] Decode(string Base32String)
  {
    // Ignore hyphens
    string str = Base32String.Replace("-", "");

    // Convert it to bits
    List<byte> bits = new List<byte>();
    foreach (char c in str)
    {
      int i = CharToValue(c);
      bits.Add((byte)((i & 16) > 0 ? 1 : 0));
      bits.Add((byte)((i & 8) > 0 ? 1 : 0));
      bits.Add((byte)((i & 4) > 0 ? 1 : 0));
      bits.Add((byte)((i & 2) > 0 ? 1 : 0));
      bits.Add((byte)((i & 1) > 0 ? 1 : 0));
    }

    // Convert bits into bytes
    List<byte> bytes = new List<byte>();
    for (int i = 0; i < bits.Count; i += 8)
    {
      bytes.Add((byte)(
        (bits[i + 0] << 7) +
        (bits[i + 1] << 6) +
        (bits[i + 2] << 5) +
        (bits[i + 3] << 4) +
        (bits[i + 4] << 3) +
        (bits[i + 5] << 2) +
        (bits[i + 6] << 1) +
        (bits[i + 7] << 0)));
    }

    return bytes.ToArray();
  }

  static int CharToValue(char c)
  {
    char cl = char.ToLower(c);
    if (cl == 'a') return 0;
    if (cl == 'b') return 1;
    if (cl == 'c') return 2;
    if (cl == 'd') return 3;
    if (cl == 'e') return 4;
    if (cl == 'f') return 5;
    if (cl == 'g') return 6;
    if (cl == 'h') return 7;
    if (cl == 'i') return 8;
    if (cl == 'j') return 9;
    if (cl == 'k') return 10;
    if (cl == 'l') return 11;
    if (cl == 'm') return 12;
    if (cl == 'n') return 13;
    if (cl == 'o') return 14;
    if (cl == 'p') return 15;
    if (cl == 'q') return 16;
    if (cl == 'r') return 17;
    if (cl == 's') return 18;
    if (cl == 't') return 19;
    if (cl == 'u') return 20;
    if (cl == 'v') return 21;
    if (cl == 'w') return 22;
    if (cl == 'x') return 23;
    if (cl == 'y') return 24;
    if (cl == 'z') return 25;
    if (cl == '2') return 26;
    if (cl == '3') return 27;
    if (cl == '4') return 28;
    if (cl == '5') return 29;
    if (cl == '6') return 30;
    if (cl == '7') return 31;
    throw new Exception("Not a base32 string");
  }
}

Tengo una cadena base32 que necesito convertir a una matriz de bytes. Y tengo problemas para encontrar un método de conversión en .NET Framework. Puedo encontrar métodos para base64 pero no para base32.

Convert.FromBase64String : algo así para base32 sería perfecto.

¿Existe tal método en el marco o tengo que hacer el mío?


Aquí están mis funciones para codificar y decodificar. Siento que son mucho más cortas y concisas que las otras sugerencias. Entonces, si necesitas uno pequeño, prueba estos.

public static string BytesToBase32(byte[] bytes) {
    const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    string output = "";
    for (int bitIndex = 0; bitIndex < bytes.Length * 8; bitIndex += 5) {
        int dualbyte = bytes[bitIndex / 8] << 8;
        if (bitIndex / 8 + 1 < bytes.Length)
            dualbyte |= bytes[bitIndex / 8 + 1];
        dualbyte = 0x1f & (dualbyte >> (16 - bitIndex % 8 - 5));
        output += alphabet[dualbyte];
    }

    return output;
}

public static byte[] Base32ToBytes(string base32) {
    const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    List<byte> output = new List<byte>();
    char[] bytes = base32.ToCharArray();
    for (int bitIndex = 0; bitIndex < base32.Length * 5; bitIndex += 8) {
        int dualbyte = alphabet.IndexOf(bytes[bitIndex / 5]) << 10;
        if (bitIndex / 5 + 1 < bytes.Length)
            dualbyte |= alphabet.IndexOf(bytes[bitIndex / 5 + 1]) << 5;
        if (bitIndex / 5 + 2 < bytes.Length)
            dualbyte |= alphabet.IndexOf(bytes[bitIndex / 5 + 2]);

        dualbyte = 0xff & (dualbyte >> (15 - bitIndex % 5 - 8));
        output.Add((byte)(dualbyte));
    }
    return output.ToArray();
}

He creado mi propia implementación genérica de codificador / decodificador Base32 para VB.NET. He verificado los resultados a través de sitios web independientes, por lo que parece ser bastante preciso.

Cualquier comentario sobre cómo se pueden hacer mejoras al código será bienvenido.

Option Compare Text
Imports System.ComponentModel

Public Structure Base32(Of T)

        Private Const csValidStandardBase32Chars As String = "0123456789ABCDEFGHIJKLMNOPQRSTUV"

        <EditorBrowsable(EditorBrowsableState.Never)> _
        Class Base32Nibble

                <EditorBrowsable(EditorBrowsableState.Never)> _
                Friend mStore As New BitArray(5, False)

                Public ReadOnly Property Value As Byte
                        Get
                                Dim result As Byte = 0
                                For index As Byte = 0 To mStore.Count - 1
                                        If mStore(index) Then
                                                result += (2 ^ index)
                                        End If
                                Next
                                Return result
                        End Get
                End Property

                Public Overrides Function ToString() As String
                        Dim nibbleString As String = Nothing
                        For Each bit As Boolean In mStore
                                nibbleString = Math.Abs(CInt(bit)).ToString() & nibbleString
                        Next
                        Return nibbleString
                End Function

        End Class

        Private Shared mNibbles As List(Of Base32Nibble)

        Public ReadOnly Property Count As Long
                Get
                        Return mNibbles.Count
                End Get
        End Property

        Default Public ReadOnly Property Item(ByVal index As Integer) As Base32Nibble
                Get
                        Return DirectCast(mNibbles(index), Base32Nibble)
                End Get
        End Property

        Public Sub New(ByVal Value As T)
                Dim temp As Object = CType(Value, T)
                getNibbles(BitConverter.GetBytes(temp))
        End Sub

        Public Sub New(ByVal Value As Byte())
                getNibbles(Value)
        End Sub

        Public Shared Widening Operator CType(ByVal Value As T) As Base32(Of T)
                Return New Base32(Of T)(Value)
        End Operator

        Public Shared Widening Operator CType(ByVal Value As Byte()) As Base32(Of T)
                Return New Base32(Of T)(Value)
        End Operator

        Public ReadOnly Property Value As String
                Get
                        Dim result As String = Nothing
                        For Each Nib As Base32(Of T).Base32Nibble In mNibbles
                                result = csValidStandardBase32Chars(Nib.Value) & result
                        Next
                        Return result.TrimStart("0")
                End Get
        End Property

        Public Function ToNumeric(ByVal Base32String As String) As T
                Dim result As T = CType(CType(0, Object), T)
                Try
                        If Base32String.Trim.Length > 0 Then
                                Dim pos As Integer = 0
                                Do
                                        Dim temp As Object = getBase32Value(Base32String, pos)
                                        result = result + temp
                                        pos += 1
                                Loop While (pos < Base32String.Length)
                        End If
                Catch ex As Exception
                        ' Catch overflow errors if the generic type T doesn't have enough
                        ' room to store the result
                        System.Diagnostics.Debug.Print(ex.Message)
                End Try
                Return result
        End Function

        Private Shared Sub getNibbles(ByVal Value As Byte())

                Dim valueBytes As New BitArray(Value)
                Dim nib As Base32Nibble = Nothing

                mNibbles = New List(Of Base32Nibble)

                Dim padding As Byte = (1 - (valueBytes.Length / 5 - (valueBytes.Length \ 5))) * 5
                valueBytes.Length = valueBytes.Length + padding

                For element As Short = 0 To valueBytes.Count - 1
                        If (element Mod 5 = 0) Then
                                nib = New Base32Nibble()
                                mNibbles.Add(nib)
                        End If
                        nib.mStore.Item(element Mod 5) = valueBytes.Item(element)
                Next

        End Sub

        Private Function getBase32Char(ByVal InputString As String, ByVal InputPosition As Integer) As String
                Return csValidStandardBase32Chars.IndexOf(Mid(InputString, InputPosition + 1, 1))
        End Function

        Private Function getBase32Value(ByVal InputString As String, ByVal InputPosition As Integer) As T
                Return CType(CType((getBase32Char(InputString, InputPosition) * (32 ^ (InputString.Length - 1 - InputPosition))), Object), T)
        End Function

End Structure

Aquí hay un ejemplo de conversión de 123456789 a Base32

Dim value As Base32(Of Int64) = 123456789
Console.WriteLine( "123456789 in Base32 = " & value.Value)

He escrito algunas implementaciones basadas en estándares flexibles de varios métodos de codificación / decodificación Base32 y Base64. Notablemente: base64url (por rfc4648) y su base32 equivalente.

Por defecto, la clase Base32Url codifica con solo los caracteres de la A a la Z y de 2 a 7. No se utilizan guiones, guiones bajos, más, barras o iguales, lo que lo hace utilizable como un token de URL en casi todas las circunstancias. Base32Url también admite alfabetos personalizados, sensibilidad / insensibilidad de mayúsculas y minúsculas, relleno / sin relleno, etc.

Esto se publica en el proyecto de código.





base32