Xor encryption/decryption of a file with Python 3

浪子不回头ぞ 提交于 2019-12-12 13:43:16

问题


I need to encrypt / decrypt a file using xor with Python 3, I have a code that works fine in Python 2, but when trying to adapt it to Python 3, gives me some errors that I can't solve.

This code works fine in 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'))

The error when trying to run unchanged in 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

Please if someone could explain and help me adapt this code to Python 3.


回答1:


a is already an int so you would need to remove the call to ord(a):

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

You will not be able to write the joined string to your outfile without a .encode("utf-8") which will not give you any usable output so not sure what you are actually trying to achieve.

You can see when you index a byte string you get an int in python3:

n [1]: s = b"foo"

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

Where in python2 you get the str/char:

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

iterating or calling next also gives you the integer value:

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

In python2 you would just get each character. So in your code as you iterate over the bytes objects returned from encry.read() you are getting the integer values so ord(some_int) obviously fails.

There is a thorough explanation text-versus-binary-data which explains the differences between python2 and python3 a snippet of which is:

As part of this dichotomy you also need to be careful about opening files. Unless you have been working on Windows, there is a chance you have not always bothered to add the b mode when opening a binary file (e.g., rb for binary reading). Under Python 3, binary files and text files are clearly distinct and mutually incompatible; see the io module for details. Therefore, you must make a decision of whether a file will be used for binary access (allowing to read and/or write binary data) or text access (allowing to read and/or write text data). You should also use io.open() for opening files instead of the built-in open() function as the io module is consistent from Python 2 to 3 while the built-in open() function is not (in Python 3 it’s actually io.open()).

The constructors of both str and bytes have different semantics for the same arguments between Python 2 & 3. Passing an integer to bytes in Python 2 will give you the string representation of the integer: bytes(3) == '3'. But in Python 3, an integer argument to bytes will give you a bytes object as long as the integer specified, filled with null bytes: bytes(3) == b'\x00\x00\x00'. A similar worry is necessary when passing a bytes object to str. In Python 2 you just get the bytes object back: str(b'3') == b'3'. But in Python 3 you get the string representation of the bytes object: str(b'3') == "b'3'".

Finally, the indexing of binary data requires careful handling (slicing does not require any special handling). In Python 2, b'123'[1] == b'2' while in Python 3 b'123'[1] == 50. Because binary data is simply a collection of binary numbers, Python 3 returns the integer value for the byte you index on. But in Python 2 because bytes == str, indexing returns a one-item slice of bytes. The six project has a function named six.indexbytes() which will return an integer like in Python 3: six.indexbytes(b'123', 1).



来源:https://stackoverflow.com/questions/32672181/xor-encryption-decryption-of-a-file-with-python-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!