Побитовая операция XOR над строкой UTF-8 дает выход не UTF-8
Я построил базовую программу шифрования XOR, которая шифрует файл.txt с помощью ключа. Он работает нормально, но я бы хотел, чтобы файл содержал только символы UTF-8 даже после шифрования. На данный момент я получаю вывод, как это при просмотре в текстовом редакторе:
1GCh!/39hpj1GCCh
hpj1GjjCCCh!/3hpj~yGCC7fGGCChhpj1GjjCCCh!/3hpj~xGCC7fGGCChhpj1GjjCCCh!/3hpj~{GCC7fGGCChhpj1GjjCCCh!/3hpjyrGCC7fGGCChhpj1GjjCCCh!/3hpjyGCC7fGGCChhpj1GjjCCCh!/3hpjy|GCC7fGGCCh
hpj1GjjCCCh!/3hpjy}GCC7fGGCCh
hpj1GjjCCCh!/3hpj~zGCC7fGGCChhpj1GjjCCCh!/3hpjysGCC7fGGCChhpj1GjjCCCh!/3hpj{~GCC7fGGCChhpj1GjjCCCh!/3hpj{GCC7fGGCCh
hpj1GjjCCCh!/3hpj{|GCC7fGGCChhpj1GjjCCCh!/3hpj{}GCC7fGGCChhpj1GjjCCCh!/3hpjh=hGCC7fGGCChhpj1GjjCCCh!/3hpjh+hGCC7fGGCChhpj1GjjCCCh!/3hpjh9hGCC7fGGCCh
hpj1GjjCCCh!/3hpjh.hGCC7GC7G7G
Здесь есть много артефактов, которые я считаю результатом не-UTF символов.
Можно ли выполнить побитовую операцию XOR, чтобы получить только символы UTF?
Для справки, вот моя функция склепа:
static std::string XORCrypt(std::string key, std::string data) {
for (size_t i = 0; i != data.size(); i++) {
data[i] ^= key[i % key.size()];
}
return data;
}
3 ответа
Конечно, просто ограничьте измененные биты младшими 3 битами. Это единственная битовая зона в UTF-8, которая является произвольной для всех допустимых единиц кода UTF-8.
Вы можете запустить свой ключ через функцию расширителя, чтобы удлинить его, чтобы удовлетворить это требование.
И я думаю, что нам всем будет удобнее, если вы измените формулировку с "шифрование" на "обфускация".
Нет, ты не можешь. Каждый байт в последовательности UTF-8 имеет несколько фиксированных битов, а некоторые зависят от символа. Если байт имеет старший бит 0, то это символ ASCII, и вы можете представить себе только повторение младшего 7 бита (*), но это покажет, какие символы были ASCII в оригинале, что не очень хорошо. Если вы меняете старший бит, вы полностью нарушаете кодировку UTF-8.
Кроме того, простое xor-шифрование нарушается, если вы можете отправить одним известным открытым текстом.
Простой совет - не делать свое собственное шифрование.
(*) И аналогично, но сложнее для тех, у кого установлен старший бит.
UTF8 имеет переменную длину символов, что означает, что он определяет определенные последовательности байтов (1, 2 или более байтов) как некоторые конкретные символы. Существует много возможных комбинаций байтов, но допустимо только их подмножество, это подмножество можно увидеть, например, здесь. Здесь происходит то, что вы меняете только один байт из этой последовательности за раз. Это может изменить не только один символ, но и многие другие, следующие за ним, поскольку последовательности теперь становятся не выровненными. В дополнение к этому вы можете сгенерировать что-то, чего вообще нет в таблице. Поэтому, если вы хотите зашифровать текст UTF8, а криптограмма должна быть читаемой в UTF8, вам необходимо иметь логику, которая распознает символы UTF и изменяет их некоторым предсказуемым образом.