Байтовый массив в строку и обратно: восстановленный байтовый массив НЕ соответствует исходному байтовому массиву в Java

Я преобразовал байтовый массив в строку следующим образом в Java:

String str_bytearray = new String(bytearray_original);

и затем я восстановил оригинальный байтовый массив, используя строку, как показано ниже:

byte[] bytearray_recovered = str_bytearray.getBytes();

но мне было интересно, когда я сравнил bytearray_original и bytearray_recovered. результат следующий:

[48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, -115, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, -112, -30, -110, 115]

[48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, 63, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, 63, -30, -110, 115]

как видите, два байта отличаются от исходного байтового массива, то есть -115 to 63 а также -112 to 63, Возможно ли решить эту проблему?

Примечание. Фактически и исходный, и восстановленный байтовый массив являются открытым ключом. Сначала открытый ключ преобразуется в строку для хранения в файле, а затем после считывания строкового значения открытого ключа его необходимо восстановить для проверки подписи.

Bytearray_original генерируется следующим образом:

PublicKey signPublicKey = keypair.getPublic(); 
byte [] bytearray_original = signPublicKey.getEncoded();

Я ценю любую помощь.

С уважением

3 ответа

Решение

Вы не можете преобразовать произвольную последовательность байтов в String и ожидать обратного преобразования в работу. Вам нужно будет использовать такую ​​кодировку, как Base64 сохранить произвольную последовательность байтов. (Это доступно из нескольких мест - встроено в Java 8, а также доступно от Guava и Apache Commons.)

Например, с Java 8,

String encoded = Base64.getEncoder().encodeToString(myByteArray);

обратим с

byte[] decoded = Base64.getDecoder().decode(encoded);

В качестве альтернативы ответу Луи Вассермана и до тех пор, пока у вас есть BouncyCastle в вашем проекте, вы можете использовать org.bouncycastle.util.encoders.Hex служебный класс:

import org.bouncycastle.util.encoders.Hex;
import java.util.Arrays;

class EncodingTest {
    public static void main(String[] args) {
        byte[] bytearray_original = new byte[]{48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, -115, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, -112, -30, -110, 115};
        String str_bytearray = Hex.toHexString(bytearray_original);
        byte[] bytearray_recovered = Hex.decode(str_bytearray);
        System.out.println("Results are equal: " + Arrays.equals(bytearray_original, bytearray_recovered));
    }
}

Эта опция требует внешней библиотеки, но не требует Java 8.

Это может помочь указать кодировку, такую ​​как UTF-8.

И конструктор String, и getBytes позволят вам сделать это, например:

String str_bytearray = new String(bytearray_original, "UTF-8");
byte[] bytearray_recovered = str_bytearray.getBytes("UTF-8");

Это должно привести к тому же массиву байтов.

РЕДАКТИРОВАТЬ: Как указывает RealSkeptic, вам необходимо выяснить, какая кодировка является вашим исходным байтовым массивом, и использовать его вместо "UTF-8" в приведенном выше коде.

Другие вопросы по тегам