Search code examples
vb.netencodingbase64formatexception

VB.net invalid length for a base 64 char array or string


I have an issue with conversion from a base-64 string to normal, readable text. I did some research and found that base 64 strings have to be of a length that is a multiple of 4. So I used padRight to give it a valid length, but I keep getting the same error. For example, I enter "hi" and it encodes as "⚫aGk====", which seems like 8 characters to me (which is obviously a multiple of 4). When I try to read it, it reads in with a length of 1. I'm also using a custom file extension that I just called ".bgs". I'm not sure if that does anything. Writing to this file as a base64 string and reading/decoding it is the only thing I'm trying to do.

Here is my code:

Public Class Form1

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Me.Close()
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Using bs As New BinaryWriter(File.Open("saveFile.bgs", FileMode.Create))

        Dim originText As String = TextBox1.Text
        Dim cipherText As String

        Dim byteArray As Byte() = System.Text.Encoding.UTF8.GetBytes(originText)
        cipherText = Convert.ToBase64String(byteArray)

        Dim realLength As Integer = cipherText.Length() + 1
        Dim len As Integer = (realLength Mod 4)
        If (len > 0) Then bs.Write(cipherText.PadRight(realLength + (3 - len), "="))


        bs.Close()

    End Using
End Sub

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    Using bs As New BinaryReader(File.Open("saveFile.bgs", FileMode.Open))

        Dim cipherText2 As String = bs.Read()
        Dim originText2 As String = "Failed"

        TextBox2.Text = cipherText2.Length() 'reports length of 1
        Try
            Dim byteArray2 As Byte() = Convert.FromBase64String(cipherText2)
            originText2 = System.Text.Encoding.UTF8.GetString(byteArray2)
        Catch ex As Exception

        End Try

        'TextBox2.Text = originText2

    End Using
End Sub

Any help is much appreciated!

Update: it looks like the first character (the dot in the case above) seen in the .bgs file when I open it with notepad controls the contents of cipherText2, which is just a number, explaining why the length is so low.


Solution

  • Base64 encodes using only printable ASCII characters.

    You are seeing the dot because you are using binary writer which prefixes strings with their length when writing to file.

    Then you are using Read instead of ReadString so you read the string length as a number (which is then implicitly converted to string because you are not using Option Strict On like you should).

    You can fix it by using ReadString instead of Read, but it would be easier if you used a text writer.

    You also should not try to pad results of ToBase64String. It already gives you the correct string.

    I would rewrite your code as:

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
        Dim originText As String = TextBox1.Text
        Dim cipherText As String = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(originText))
    
        System.IO.File.WriteAllText("saveFile.bgs", cipherText, System.Text.Encoding.ASCII)
    End Sub
    
    Private Sub Button3_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button3.Click
        Dim cipherText2 As String = System.IO.File.ReadAllText("saveFile.bgs", System.Text.Encoding.ASCII)
        Dim originText2 As String = "Failed"
    
        originText2 = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(cipherText2))
    
        'TextBox2.Text = originText2
    End Sub