2015-09-19 2 views
3

Мне нужно зашифровать/дешифровать файл с помощью xor с помощью Python 3, у меня есть код, который отлично работает в Python 2, но при попытке адаптировать его к Python 3 дает мне некоторые ошибки, которые я не могу решить.Xor шифрование/дешифрование файла с помощью Python 3

Этот код прекрасно работает в Python 2.7:

from itertools import cycle 


def xore(data, key): 
    return ''.join(chr(ord(a)^ord(b)) for (a, b) in zip(data, cycle(key))) 

with open('inputfile.jpg', 'rb') as encry, open('outputfile.jpg', 'wb') as decry: 
    decry.write(xore(encry.read(), 'anykey')) 

Ошибка при попытке запустить без изменений в Python 3:

Traceback (most recent call last): 
    File "ask.py", line 8, in <module> 
    decry.write(xore(encry.read(), 'anykey')) 
    File "ask.py", line 5, in xore 
    return ''.join(chr(ord(a)^ord(b)) for (a, b) in zip(data, cycle(key))) 
    File "ask.py", line 5, in <genexpr> 
    return ''.join(chr(ord(a)^ord(b)) for (a, b) in zip(data, cycle(key))) 
TypeError: ord() expected string of length 1, but int found 

Пожалуйста, если кто-то может объяснить и помочь мне адаптировать этот код на Python 3.

+0

Попробуйте это: 'return '' .join (chr (ord (str (a))^ord (str (b))) для (a, b) в zip (данные, цикл (ключ))) ' –

+0

Вы открываете файл с' b', поэтому 'a' является int каждый раз,' '' .join (chr (a^ord (b)) для (a, b) в zip (данные, цикл (ключ)))) ' –

+1

Если они уже запущены, не могли бы вы просто удалить вызов' ord'? –

ответ

0

a уже есть int, поэтому вам нужно будет удалить звонок по номеру ord(a):

def xore(data, key): 
    return ''.join(chr(a^ord(b)) for (a, b) in zip(data, cycle(key))) 

Вы не сможете писать соединяемых строку вашего OUTFILE без .encode("utf-8"), который не даст вам никакой полезной выходной поэтому не уверен, что вы на самом деле пытаетесь достичь.

Вы можете видеть, когда индекс строка байт вы получаете Int в Python3:

n [1]: s = b"foo" 

In [2]: s[0] 
Out[2]: 102 # f 

Где в python2 вы получаете ул/обугленного:

In [1]: s = b"foo" 
In [2]: s[0] 
Out[2]: 'f' 

итерации или вызова следующий также дает вы целочисленное значение:

In [12]: it = iter(s) 
In [13]: next(it) 
Out[13]: 102 
In [14]: for ele in s: 
     print(ele) 
    ....:  
102 
111 
111 

В python2 вы просто получите каждого персонажа. Таким образом, в вашем коде, когда вы перебираете объекты байтов, возвращенные с encry.read(), вы получаете целые значения, поэтому ord(some_int) явно не работает.

Существует глубокое объяснение text-versus-binary-data, который объясняет различия между python2 и Python3 сниппета из которых:

В рамках этой дихотомии вы также должны быть осторожны об открытии файлов. Если вы не работали в Windows, есть вероятность, что вы не всегда пытались добавить режим b при открытии двоичного файла (например, rb для двоичного чтения). В Python 3 двоичные файлы и текстовые файлы четко различаются и взаимно несовместимы; Подробнее см. модуль io. Поэтому вы должны принять решение о том, будет ли файл использоваться для двоичного доступа (позволяющий читать и/или записывать двоичные данные) или текстовый доступ (позволяющий читать и/или записывать текстовые данные). Вы также должны использовать io.open() для открытия файлов вместо встроенной функции open(), поскольку модуль io совместим с Python с 2 по 3, тогда как встроенная функция open() отсутствует (в Python 3 это фактически io.open()).

Конструкторы и ул и байтов, имеют различную семантику для одних и тех же аргументов между Python 2 & 3. Попутные целое число байтов в Python 2 даст вам строковое представление целого числа: bytes(3) == '3'. Но в Python 3 целочисленный аргумент в байтах даст вам объект байта, если задано целое число, заполненное нулевыми байтами: bytes(3) == b'\x00\x00\x00'. Подобное беспокойство необходимо при передаче объекта bytes на str. В Python 2 вы просто возвращаете объект bytes: str(b'3') == b'3'. Но в Python 3 вы получите строковое представление объекта байтов: str(b'3') == "b'3'".

Наконец, индексирование двоичных данных требует тщательной обработки (нарезка не требует специальной обработки). В Python 2, b'123'[1] == b'2' в то время как в Python 3 b'123'[1] == 50. Поскольку двоичные данные представляют собой просто набор двоичных чисел, Python 3 возвращает целое значение для байта, на который вы индексируете. Но в Python 2, поскольку bytes == str, индексирование возвращает единичный кусок байта. Шесть проектов имеют функцию с именем six.indexbytes(), которая вернет целое число, как в Python 3: six.indexbytes (b'123 ', 1).

Смежные вопросы