Я думаю, что теперь понимаю назначение.
Код должен кодировать одну строку сообщения , используя другую строку в качестве ключа. Base64 используется только для кодирования результата, поскольку он является двоичными данными и может (будет) содержать коды, которые нельзя распечатать - поэтому результат представляется в виде текста и, например, может быть отправлен по почте учителю.
Сначала отметим, что порядок строк не имеет значения, поэтому нет никакого реального различия между ключом и сообщением.
Далее мы можем декодировать результаты примера, например, используя linux command base64
(Я использовал GIT Bash, но для этого также доступны онлайн-сервисы). Я также передал результат в od
(утилита шестнадцатеричного дампа, чтобы увидеть шестнадцатеричные значения):
$ echo "AAxMTE8=" | base64 -d | od -t x1 -c
, которая возвращает
0000000 00 0c 4c 4c 4f
\0 \f L L O
Обратите внимание, что это * Длина 1019 * байтов, то же самое, что и длина входной строки - поэтому мы можем предположить, что строки не объединяются, что приведет к изменению длины, но байты каждой строки каким-то образом объединяются. Кроме того, каждый символ использует один байт, поэтому кодировка, вероятно, равна UTF-8
или даже ASCII
.
Далее мы видим, что результат заканчивается на "LLO"
, прописной версии конца самого длинного ввода "hello"
- похоже, что позиция байтов не изменилась, только значения, объединенные какой-либо операцией. Давайте рассмотрим некоторые операции, которые можно использовать для объединения байтов:
- Вычитание или деление : не будет работать, поскольку порядок ввода не имеет значения;
- Добавление или умножение : не очень хорошо из-за возможного переполнения / недостаточного заполнения
- Битовая И , NAND , ИЛИ или НОР : не сработает, потеря информации (например,
x AND 0
всегда 0
) - Битовая XOR (исключающее ИЛИ): (почти) идеально, легко зашифровать, легко расшифровать, порядок значения не имеет (но не очень сильный)
Позволяет проверить, что происходит с XOR :
input1: "hello" == [ 0x68, 0x65, 0x6c, 0x6c, 0x6f ] // using ASCII/UTF-8
input2: "hi" == [ 0x68, 0x69 ] // "
result: "∅∅LLO" == [ 0x00, 0x0c, 0x4c, 0x4c, 0x4f ] // ∅ not printable
0x68 ^ 0x68 == 0x00 // correct!
0x65 ^ 0x69 == 0x0f // "
0x6c ^ X == 0x4c // what is X?
0x6f ^ X == 0x4f // "
Теперь нам просто нужно посмотреть, что должно произойти с последними 3 байтами, один вход слишком короткий, то есть X
. Нетрудно выяснить, что 0x6c ^ 0x20 == 0x4c
и 0x6f ^ 0x20 == 0x4f
, на самом деле A ^ X == B
подразумевают, что A ^ B == X
. Таким образом, мы заключаем, что строка меньшего размера должна быть заполнена 0x20 или символом пробела ' '
.
Алгоритм должен быть примерно таким: сделать обе входные строки одинакового размера, добавив белую пробелы (' '
) до меньшей строки. Преобразовать оба входа в байтовый массив. Объедините байты каждого массива, используя исключительное ИЛИ. Кодируйте результат, используя Base64.