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

StackOverflow https://stackoverflow.com/questions/22696126

Question

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;
}
Was it helpful?

Solution

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).

OTHER TIPS

If you have a space in your encoded string, which is an illegal character in base64. If you remove it, it still generates the same image/data in the converter you linked to, and can be now decoded by your code as well.

UPDATE: Some decoders (like the one you linked, or Base64.getMimeDecoder() in Java) ignore illegal characters, others (like Base64.getDecoder()) don't allow them.

Use for encode:

Base64.getEncoder().encodeToString(yourString.getBytes("UTF-8"));

and decode:

byte[] decodedBytes = Base64.getDecoder().decode(yourString);
String stringDecode = new String(decodedBytes, "UTF-8");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top