Проблема декодирования и кодирования. Различные реализации класса Base64 в android.util.* и java.util.*?

Я пишу приложение, которое делает следующее с заданной строкой str:

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

Сервер получает строку в кодировке Base64, которая затем декодируется -> расшифровывается -> декодируется, чтобы получить отправленную строку str из приложения.

К сожалению, это не работает для всех строк, длинные строки приводят к длинной строке Base64, и мой сервер выдает следующее исключение:

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)

Строка имеет формат «[строка, строка, ..., строка]» без «s.

Как я упоминал выше, для не слишком длинных строк (извините, я пока не могу определить длину) это работает. Так что я думаю, что реализовал это правильно.

Что странно, если я его не отправлю, а расшифрую(расшифрую(декодирую(stringToBytearray(str))))); Строка на самом устройстве, все работает отлично.

Моя установка: JDK 7, eclipse (adt-bundle, разработка для Android) (Windows 7)

JDK 8, eclipse («нормальная» Java) (Linux (xubuntu))

Это потому, что оба класса (Base64) реализованы по-разному? Если да, то как я могу заставить его работать?

Вот методы кодирования/декодирования:

Кодировка (Устройство: в 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);
}

Декодирование (сервер: на Linux, jdk 8):

import java.util.Base64

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

Все строки де-/кодируются с использованием одной и той же кодировки (utf-8)! Кодирование/декодирование: Base64

Криптовалюта: AES

Если вам нужна дополнительная информация, просто спросите, но я думаю, что предоставил всю необходимую информацию.

Редактировать:

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;
}

person user3469811    schedule 27.03.2014    source источник
comment
0x5b — это [, и, как я уже сказал, формат String — это [string, ..., string]. Но почему все кодирование/декодирование работает на устройстве, а не на сервере, когда строка слишком длинная. (я сравнил обе длинные строки, и они равны)   -  person user3469811    schedule 27.03.2014
comment
Ваш сервер обрезает параметр запроса, когда длина слишком велика? Просто попробуйте повторить полученное сообщение base-64 и проверить, точно ли они равны. Потому что усеченная строка больше не может быть допустимым сообщением, зашифрованным с помощью Base-64.   -  person D3V    schedule 27.03.2014
comment
Я только что узнал, что второй вызов encode не применяется (хотя я думал, что проверил это). Пока спасибо за все предложения! Я попытаюсь выяснить, почему это не так.   -  person user3469811    schedule 28.03.2014
comment
Я немного боролся с разными кодировщиками в java.util.Base64. Вы пробовали Base64.getDecoder() вместо Base64.getUrlDecoder()?   -  person Johannes Brodwall    schedule 17.04.2017


Ответы (3)


Вы должны использовать JSONObjects для отправки строки Base64 на сервер. Если это так, то JSONObject добавит escape-символы " \ " в строку, которая является недопустимыми символами Base64. Все, что вам нужно сделать, это

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

на стороне сервера перед использованием полученной строки.

Необязательно

Также на стороне сервера используйте

import javax.xml.bind.DatatypeConverter;

и

String result = DatatypeConverter.printBase64Binary(bytearrayToDecode);

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

вместо.

Он не только выполняет свою работу, но и намного быстрее кодирует/декодирует (как здесь).

person Mohsin Ali    schedule 31.08.2015
comment
Мне кажется, что printBase64Binary убирает для вас обратную косую черту. Спасибо за понимание. У меня была та же проблема, что и у ОП. - person cloudsurfin; 21.03.2016

Если в закодированной строке есть пробел, который является недопустимым символом в base64. Если вы удалите его, он по-прежнему будет генерировать то же изображение/данные в конвертере, на который вы ссылались, и теперь он также может быть декодирован вашим кодом.

ОБНОВЛЕНИЕ: некоторые декодеры (например, тот, на который вы ссылаетесь, или Base64.getMimeDecoder() в Java) игнорируют недопустимые символы, другие (например, Base64.getDecoder()) их не допускают.

person Anand Varkey Philips    schedule 10.08.2017

Используйте для кодирования:

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

и расшифровать:

byte[] decodedBytes = Base64.getDecoder().decode(yourString);
String stringDecode = new String(decodedBytes, "UTF-8");
person Leonardo Borges    schedule 19.09.2017