Я работаю над программой, которая является реализацией алгоритма шифрования RSA, так же как и личное упражнение, не защищая никому информацию или что-то еще. Я пытаюсь понять, как толковый интерпретатор интерпретируется численно, позволяя ему зашифровать. Я понимаю, что большинство символов UTF-8 заканчиваются только использованием 1 байта пробела, а не двух байтов, о которых можно подумать, но об этом. Вот мой код:
BigInteger ONE = new BigInteger("1");
SecureRandom rand = new SecureRandom();
BigInteger d, e, n;
BigInteger p = BigInteger.probablePrime(128, rand);
BigInteger q = BigInteger.probablePrime(128, rand);
BigInteger phi = (p.subtract(ONE)).multiply(q.subtract(ONE));
n = p.multiply(q);
e = new BigInteger("65537");
d = e.modInverse(phi);
String string = "test";
BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
BigInteger cipherText = plainText.modPow(e, n);
BigInteger originalMessage = cipherText.modPow(d, n);
String decrypted = new String(originalMessage.toByteArray(),"UTF-8");
System.out.println("original: " + string);
System.out.println("decrypted: " + decrypted);
System.out.println(plainText);
System.out.println(cipherText);
System.out.println(originalMessage);
System.out.println(string.getBytes("UTF-8"));
byte byteArray[] = string.getBytes("UTF-8");
for(byte littleByte:byteArray){
System.out.println(littleByte);
}
Он выводит:
original: test
decrypted: test
1952805748
16521882695662254558772281277528769227027759103787217998376216650996467552436
1952805748
[B@60d70b42
116
101
115
116
Может быть, более конкретно я интересуюсь этой строкой:
BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
Имеет ли каждая буква "тест" значение, и они объединяются здесь вместе? Например, t = 1, e = 2, s = 3, t = 1, например, если вы получите байты из этой строки, вы получите 7 или значения, которые только что собраны, как 1231? И почему
BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
выход 1952805748
Я пытаюсь понять, как толковый интерпретатор интерпретируется численно, позволяя ему зашифровать.
Это действительно сводится к пониманию того, что делает эта строка:
BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
Давайте сломаем его.
Начнем с строки (string
). Строка Java представляет собой последовательность символов, представленных в виде кодовых точек Unicode (закодированных в UCS-16...).
Затем getBytes("UTF-8")
кодирует символы как последовательность байтов и возвращает их в недавно выделенный массив байтов.
Конструктор BigInteger(byte[])
интерпретирует массив байтов как число. Как говорится в javadoc:
Переводит массив байтов, содержащий двоичное представление двоичного дополнения BigInteger в BigInteger. Предполагается, что входной массив находится в байтовом порядке большого байта: самый старший байт находится в нулевом элементе.
Метод, который используется здесь, не дает интригически значимого числа, только одного, которое соответствует строке, закодированной в байтах. И переход от байтового массива к числу - это просто обработка байтов как битовой последовательности, которая представляет целое число в форме 2 дополнения... что является наиболее распространенным представлением для целых чисел на современном оборудовании.
Главное, что преобразование из текста в (незашифрованный) BigInteger является без потерь и обратимым. Можно использовать любое другое преобразование с этими свойствами.
Рекомендации:
BigInteger(byte[])
String.getBytes(String)
Я все еще не совсем понимаю, как значения UTF-8 для каждого символа в "тесте", 116, 101, 115, 116, собраны вместе, чтобы сформировать 1952805748?
См. Шаблон?
Ответ на выходе, "тест" закодирован в массив из 4 байтов [116, 101, 115, 116]. В этом случае BigInteger взаимодействует как двоичное целочисленное представление. Значение может быть рассчитано таким образом
value = (116 << 24) + (101 << 16) + (115 << 8) + 116;
BigInteger plainText = new BigInteger(string.getBytes("UTF-8"));
выход 1952805748