#java #string #byte
#java #строка #байт
Вопрос:
Я хочу преобразовать байты в строку для целей шифрования, а затем я хочу получить те же байты для расшифровки. Но проблема в том, что после генерации 16 байт IV я преобразую его в строку, и когда я пытаюсь получить тот же байт из строки, длина байтов изменяется. Ниже приведен пример программы для воспроизведения проблемы.
package com.prahs.clinical6.mobile.edge.util;
import java.security.SecureRandom;
import java.util.Random;
import javax.crypto.spec.IvParameterSpec;
public class Test {
public static void main(String[] args) {
Random rand = new SecureRandom();
byte[] bytes = new byte[16];
rand.nextBytes(bytes);
IvParameterSpec ivSpec = new IvParameterSpec(bytes);
System.out.println("length of bytes before converting to String: " ivSpec.getIV().length);
String ibString = new String(ivSpec.getIV());
System.out.println("length of bytes after converting to String: " ibString.getBytes().length);
}
}
Пожалуйста, кто-нибудь может подтвердить, почему это такое поведение и что мне нужно изменить, чтобы получить ту же длину байта, т.е.: 16 в данном случае.
Комментарии:
1. Почему вы преобразуете эти случайные байты в a
String
?2. Не переходите к string, из-за кодировки сохранение байтов — лучший способ заставить ваш алгоритм работать. Не ищите хитрый способ решить ВАШЕ странное решение: избегайте вашего странного решения.
3. В этом нет никакого смысла.
String
предназначен для хранения текста в Юникоде. Случайные байты, которые вы получаете от aSecureRandom
, не являются текстом. Вам нужно будет более конкретно рассказать о том, что вы пытаетесь сделать, чтобы получить дополнительную помощь.4. Поскольку случайно сгенерированный IV будет содержать много байтов, которые не могут быть закодированы как string (например, #00), вы НЕ должны преобразовывать его в строку таким образом. Если вы хотите объединить данные, сделайте это на основе byte[] . Если вам нужно их транспортировать (например, по почте), пожалуйста, закодируйте массив байтов в Base64, а затем декодируйте его обратно в массив байтов для последующего использования.
5. Я имею в виду: возможно, вам нужно решить эту проблему (строковую), НО лучшим способом было бы избежать этого вообще. Вы можете видеть, что в качестве комментария вы можете получить
Ответ №1:
Пожалуйста, не преобразуйте случайно сгенерированный массив байтов в строку, поскольку существует множество значений, которые не могут быть закодированы в строку — просто подумайте о x00.
Обычным способом «преобразования» такого массива байтов в строку является кодировка массива байтов Base64. Это удлинит строку примерно на 1/3, но вы можете без потерь перекодировать строку в массив байтов.
Пожалуйста, обратите внимание, что вы не должны использовать Random
but SecureRandom
в качестве источника этих данных.
вывод:
length of bytes before converting to String: 16
ivBase64: wQtdbbbFdvrorpFb6LRTw==
length of bytes after converting to String: 16
ivSpec equals to ivRedecoded: true
код:
import javax.crypto.spec.IvParameterSpec;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
public class Main {
public static void main(String[] args) {
//Random rand = new SecureRandom();
SecureRandom rand = new SecureRandom();
byte[] bytes = new byte[16];
rand.nextBytes(bytes);
IvParameterSpec ivSpec = new IvParameterSpec(bytes);
System.out.println("length of bytes before converting to String: " ivSpec.getIV().length);
//String ibString = new String(ivSpec.getIV());
String ivBase64 = Base64.getEncoder().encodeToString(ivSpec.getIV());
System.out.println("ivBase64: " ivBase64);
byte[] ivRedecoded = Base64.getDecoder().decode(ivBase64);
//System.out.println("length of bytes after converting to String: " ibString.getBytes().length);
System.out.println("length of bytes after converting to String: " ivRedecoded.length);
System.out.println("ivSpec equals to ivRedecoded: " Arrays.equals(ivSpec.getIV(), ivRedecoded));
}
}