Decoding and Encoding issue. Different implementations of Base64 Class in android.util.* and java.util.*?

user3469811 picture user3469811 · Mar 27, 2014 · Viewed 15.7k times · Source

I am writing an App which does the following with a given String str:

encode(encrypt(encode(stringToBytearray(str))));

The Server receives the Base64 encoded String, which is then decoded -> decrypted -> decoded, to get the sent String str from the App.

Unfortunately it doesnt work for all Strings, long Strings lead to a long Base64 String and my Server throws the following Exception:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal base64 character 5b
 at java.util.Base64$Decoder.decode0(Base64.java:714)
 at java.util.Base64$Decoder.decode(Base64.java:526)
 at Main.decode(Main.java:113)
 at Main.main(ain.java:33)

The String has the format "[string, string, ..., string]" without "s.

Like I mentioned above, for Strings which are not too long (sorry I cant quantify the length yet), this works. So I think I implemented it right.

Whats weird is, that if I dont send it, but decode(decrypt(decode(stringToBytearray(str)))); the String on the Device itself, it all works perfectly.

My Setup: JDK 7, eclipse (adt-bundle, android development) (Windows 7)

JDK 8, eclipse ('normal' java) (Linux (xubuntu))

Is it because both Classes (Base64) are implemented diffrently? If so, how can I make it work?

Here are the Encoding/Decoding Methods:

Encoding (Device: on Windows 7, adt-bundle, Android-Dev, jdk 7):

import android.util.Base64

public byte[] encode(byte[] bytearrayToEncode){
   return Base64.encode(bytearrayToEncode, Base64.NO_WRAP|Base64.URL_SAFE);
}

Decoding (Server: on Linux, jdk 8):

import java.util.Base64

public byte[] decode(byte[] bytearrayToEncode){
   return Base64.getUrlDecoder().decode(bytearrayToDecode);
}

Strings are all De-/Encoded with the same charset (utf-8)! Encoding/Decoding: Base64

Crypto: AES

If you need more Information, just ask, but I think I provided all neccessary informations.

Edit:

public String bytearrayToString(byte[] bytearray){
    String str = null;
    try {
        str = new String(bytearray, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return str;
}

public byte[] stringToBytearray(String str){
    byte[] bytearray = null;
    try {
        bytearray = str.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return bytearray;
}

Answer

Mohsin Ali picture Mohsin Ali · Aug 31, 2015

You must be using JSONObjects to send the Base64 String to the server. If so then the JSONObject will add " \ " escape characters to the string which are illegal Base64 characters. All you need to do is

String rectifiedString = Base64String.replace("\\","");

on the server end before using the acquired string.

Optional

Also on the server side use

import javax.xml.bind.DatatypeConverter;

and

String result = DatatypeConverter.printBase64Binary(bytearrayToDecode);

byte[] result = DatatypeConverter.parseBase64Binary(str);

instead.

It will not only get the job done but is much faster at encoding/decoding (as benchmarked here).