Расшифровка XOR Python байт на байт

У меня есть зашифрованный файл XOR программой VB.net, использующей эту функцию для шифрования:

Public Class Crypter
    ...
    'This Will convert String to bytes, then call the other function.
    Public Function Crypt(ByVal Data As String) As String
        Return Encoding.Default.GetString(Crypt(Encoding.Default.GetBytes(Data)))
    End Function

    'This calls XorCrypt giving Key converted to bytes
    Public Function Crypt(ByVal Data() As Byte) As Byte()
        Return XorCrypt(Data, Encoding.Default.GetBytes(Me.Key))
    End Function

    'Xor Encryption.
    Private Function XorCrypt(ByVal Data() As Byte, ByVal Key() As Byte) As Byte()
        Dim i As Integer
        If Key.Length <> 0 Then
            For i = 0 To Data.Length - 1
                Data(i) = Data(i) Xor Key(i Mod Key.Length)
            Next
        End If
        Return Data
    End Function
End Class

и сохранил так:

Dim Crypter As New Cryptic(Key)
'open destination file
Dim objWriter As New StreamWriter(fileName)
'write crypted content
objWriter.Write(Crypter.Crypt(data))

Теперь мне нужно снова открыть файл с помощью Python, но у меня проблемы с получением отдельных байтов, это функция XOR в python:

def crypto(self, data):
    'crypto(self, data) -> str'
    return ''.join(chr((ord(x) ^ ord(y)) % 256) \
        for (x, y) in izip(data.decode('utf-8'), cycle(self.key))

Мне пришлось добавить % 256, так как иногда x > 256, т.е. не один байт.

Эта передача двух байтов не нарушает расшифровку, поскольку ключ остается "парным" со следующими данными.

Проблема в том, что некоторые расшифрованные символы при преобразовании неверны. Все эти символы представляют собой буквы с диакритическими знаками, такие как à, è, ì, но всего лишь несколько букв из общего числа букв с диакритическими знаками. Остальные все правильно восстановлены.

Я думаю, это может быть из-за мода 256, но без него я, конечно, получаю исключение chr...

Спасибо за поддержку


person neurino    schedule 10.05.2010    source источник
comment
Я надеюсь, что вы на самом деле не ожидаете реальной безопасности от этого.   -  person Glenn Maynard    schedule 11.05.2010
comment
Все, что мне нужно, это вернуть целостные данные, я получаю файлы, зашифрованные таким образом, безопасность не является моей обязанностью.   -  person neurino    schedule 11.05.2010


Ответы (4)


Действительно, следующая строка неверна:

Return Encoding.Default.GetString(Crypt(Encoding.Default.GetBytes(Data)))

Нет общей гарантии, что байты, возвращаемые из Crypt, допустимы для декодирования в виде строки. Вам лучше использовать Convert.ToBase64String, а затем передать эту строку в ваш код Python (где, очевидно, вам нужно будет декодировать байты с помощью Base-64.

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

person Damien_The_Unbeliever    schedule 11.05.2010
comment
спасибо, вы были почти правы, функция VB.net была не совсем той, которую я опубликовал, она использовала функцию для создания модуля Positive 256, чтобы предотвратить небайтовое значение. результат всегда = 0 и ‹= 255, хорошо удаляя все преобразования обратно в строку в коде vb.net и сохраняя в файл Byte напрямую. У меня правильно читаются символы python. Я близок к решению. Как я уже ответил, это не моя идея шифрования XOR, и я был бы признателен, если бы кто-нибудь сломал ее и причинил какой-то вред, поскольку я говорю это, но всем наплевать... ‹_‹ - person neurino; 11.05.2010

Ваши декодированные данные содержат символы Юникода со значениями выше 256. В Python 2.x chr может обрабатывать только значения ниже 256. Используйте unichr вместо chr и должно работать:

return ''.join(unichr((ord(x) ^ ord(y))) \
    for (x, y) in izip(data.decode('utf-8'), cycle(self.key))
person Mark Byers    schedule 10.05.2010
comment
У меня больше нет исключений, но данные неверны. У меня в документе много m², и большинство из них восстанавливаются как m\xc2\xb2, но некоторые как m\xe2\x80\xaa. Я бы подумал, что данные повреждены, но с помощью VB.net все м² правильно восстанавливаются. (конечно, это касается и букв с акцентом: большинство правильных, некоторые нет) - person neurino; 11.05.2010

правильно ли сохранять скремблированные данные в виде строки (т.е. перекодированные с кодировкой по умолчанию) с помощью StreamWriter? Было бы правильно сохранять байты напрямую? Или это одно и то же?

Dim objWriter As New StreamWriter(fileName)
objWriter.Write(Crypter.Crypt(data))

Какой Crypter.Crypt вызывается StreamWriter.Write?

Этот

Public Function Crypt(ByVal Data() As Byte) As Byte()

или это?

Public Function Crypt(ByVal Data As String) As String

Я не разбираюсь в Vb.net...


Я запустил это, чтобы узнать, какие символы участвуют в правильном/неправильном преобразовании «²».

for (x, y) in izip(data.decode('utf-8'), cycle(self.key.decode('utf-8'))):
    if (ord(x) ^ ord(y)) > 255 or chr(ord(x) ^ ord(y)) == '\xb2':
        print (x, y, chr((ord(x) ^ ord(y)) % 256),
               unichr(ord(x) ^ ord(y)), ord(x), ord(y))

Я получил это:

ù K ² ² 249 75
 p ² ² 194 112
Æ t ² ² 198 116
‚ 0 * ‪ 8218 48

последний неверен, потому что используется двойной байт... но если будет передан только один, вероятно, остальная часть расшифровки приведет к выходу из фазы

person neurino    schedule 11.05.2010
comment
если данные имеют тип string, то используется первая перегрузка Crypt (и ее реализация неверна, как я уже ответил). Если данные имеют тип Byte(), то вторая перегрузка. Если это какой-то другой тип, то это зависит от того, могут ли данные неявно преобразовываться либо в String, либо в Byte(). - person Damien_The_Unbeliever; 11.05.2010

Если вы открываете файл в текстовом режиме, он может быть интерпретирован как текст Unicode. Попробуйте открыть его в двоичном режиме, чтобы преобразовать все символы в байты. Это должно избежать проблем с chr. Если вы используете Python 3.x, помните, что при работе в двоичном режиме вы должны использовать байтовые литералы, а не строковые литералы, последние из которых являются строками Unicode по дизайну.

person Dustin    schedule 10.05.2010
comment
Я открываю файл в режиме «rb» в python 2.5, но мне все равно пришлось добавить data.decode («utf-8»), и даже с этим кажется, что я все еще не могу получить байты один за другим - person neurino; 11.05.2010