Я написал шифрование RSA на Java. Я пытаюсь превратить числа, которые он выводит в текст или символы. Например, если я кормлю его Hello, я получаю:

23805663430659911910

Однако онлайн-шифрование RSA возвращает что-то подобное:

GVom5zCerZ + dmOCE7YAp0F + N3L26L

Я просто хотел бы знать, как преобразовать мои числа во что-то подобное. Число, возвращаемое моей системой, BigInteger. Это то, что я пробовал до сих пор:

RSA rsa = new RSA("Hello");
BigInteger cypher_number = rsa.encrypt(); // 23805663430659911910
byte[] cypher_bytes = cypher_number.toByteArray(); // [B@368102c8
String cypher_text = new String(cypher_bytes); // J^��*���

// Now even though cypher_text is J^��*��� I wouldn't care as long as I can turn it back.

byte[] plain_bytes = cypher_text.getBytes(); // [B@6996db8 | Not the same as cypher_bytes but lets keep going.
BigInteger plain_number = new BigInteger(plain_bytes); // 28779359581043512470254837759607478877667261

// plain_number has more than doubled in size compared to cypher_number and won't decrypt properly.

Использование байтов это единственный способ, которым я могу думать. Может кто-нибудь помочь мне понять, что я должен делать, или если это вообще возможно?

1
MagneticFlux 20 Фев 2020 в 21:16

2 ответа

Лучший ответ

Обычно это двухэтапный процесс:

  1. преобразовать в двоичную кодировку числа;
  2. преобразовать двоичную кодировку в текстовую базовую кодировку.

Для обоих шагов возможны несколько схем.


Для двоичного кодирования: спецификации PKCS # 1 всегда включали тот, который преобразует число в целое число статического размера . Чтобы быть точным, он описывает число в виде строки без знака со старшим порядком байтов без знака. Строка октета является ничем иным, как байтовым массивом.

Теперь BigInteger.toByteArray возвращает строку октетов с байтовым порядком байтов в динамическом размере со знаком. Поэтому вам необходимо реализовать возможное изменение размера и удаление начального 00 байта в отдельном методе, который я описал в моем другом посте здесь. К счастью, вернуться к числу гораздо проще, так как реализация Java предоставляет конструктор BigInteger(int sign, byte[] value), который читает число без знака и пропускает начальные нулевые байты.

Наличие стандартизированной и статически заданной строки октетов может быть очень полезным, поэтому я бы не стал использовать другую схему.


Это оставляет преобразование в и из текста. Для этого вы можете (действительно) использовать класс java.util.Base64, который не требует особых пояснений. Единственное примечание, которое я должен сделать, - это то, что он конвертируется в ASCII byte[] для некоторых методов, поэтому вместо этого вам нужно использовать encodeToString(byte[] src).

Другим методом были бы шестнадцатеричные числа, но поскольку Java не содержит шестнадцатеричный кодер для байтовых массивов в базовых классах, я бы вместо этого выбрал base 64.

1
Maarten Bodewes 22 Фев 2020 в 19:42

Я нашел ответ. Если вы нашли это в поиске ответа, вам просто нужно закодировать числа в Base64.

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

// Encode
BigInteger numbers = new BigInteger("5109763");
byte[] bytes = Base64.getEncoder().encode(numbers.toByteArray());
String encoded = new String(bytes); // Encoded value

// Decode
byte[] decoded_bytes = Base64.getDecoder().decode(encoded.getBytes());
BigInteger numbers_again = new BigInteger(decoded_bytes); // Original numbers
1
Maarten Bodewes 22 Фев 2020 в 19:47