Search code examples
stringgobase64url-encoding

Decode base64 with white space


I have a base64 encoded string i'm trying to decrypt with go. The string contains white spaces which should be ignored. A sample code I'm trying:

s := "eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjEzZmU3MWQ0LWQxMGQtNDIyMC1hMjE2LTIwMDZkMWRkNGNiOCIsImFjc1RyY++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++W5zSUQiOiJkN2M0NWY5OS05NDc4LTQ0YTYtYjFmMi0xMDAwMDAwMDMzNjYiLCJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAyIn0%3D"

out, err := base64.URLEncoding.DecodeString(s)
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println(string(out))

This code returns:

illegal base64 data at input byte 93


After changing the string padding, and using StdEncoding instead of URLEncoding:

s= strings.Replace(s, "%3D", "=", -1)
out, err := base64.StdEncoding.DecodeString(s)
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println(string(out))

The output will be:

{"threeDSServerTransID":"13fe71d4-d10d-4220-a216-2006d1dd4cb8","acsTrc���������������������������������������������������������������������������nsID":"d7c45f99-9478-44a6-b1f2-100000003366","messageType":"CReq","messageVersion":"2.1.0","challengeWindowSize":"02"}


How can I decrypt the string correctly?


Solution

  • What you have is most likely "cut off" from a URL, and it is in URL-encoded form. So to get a Base64 string, you have to first decode it, you may use url.PathUnescape() for this.

    Once you have the unescaped string, you may decode it using the base64.StdEncoding encoder. Note that just because it is / was part of a URL, that doesn't make it a base64 string that used the alphabet of the URL-safe version of Base64.

    Also the + signs in the middle of it are really just "junk". They shouldn't be there in the first place, so double-check how you get your input, but now that they are there, you have to remove them. For that, you may use strings.Replace().

    Final code to decode your invalid input:

    s := "eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjEzZmU3MWQ0LWQxMGQtNDIyMC1hMjE2LTIwMDZkMWRkNGNiOCIsImFjc1RyY++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++W5zSUQiOiJkN2M0NWY5OS05NDc4LTQ0YTYtYjFmMi0xMDAwMDAwMDMzNjYiLCJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMS4wIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAyIn0%3D"
    s = strings.Replace(s, "+", "", -1)
    var err error
    if s, err = url.PathUnescape(s); err != nil {
        panic(err)
    }
    
    out, err := base64.StdEncoding.DecodeString(s)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(out))
    

    Complete output (try it on the Go Playground):

    {"threeDSServerTransID":"13fe71d4-d10d-4220-a216-2006d1dd4cb8",
       "acsTransID":"d7c45f99-9478-44a6-b1f2-100000003366","messageType":"CReq",
        "messageVersion":"2.1.0","challengeWindowSize":"02"}
    

    Note that the + sign is a valid symbol in the alphabet of the standard Base64, and you can even decode the Base64 without removing the + symbols, but then you get junk data remaining in the JSON keys in the result.