Xor使用Python 3加密/解密文件

时间:2015-09-19 19:08:22

标签: python python-3.x encryption xor

我需要使用xor使用Python 3加密/解密文件,我有一个在Python 2中运行良好的代码,但是当我尝试将其改编为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。

1 个答案:

答案 0 :(得分:0)

a已经是int,因此您需要移除对ord(a)的调用:

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

如果没有.encode("utf-8"),你将无法将连接的字符串写入你的outfile,这将无法提供任何可用的输出,因此不确定你实际想要实现的目标。

您可以看到索引字节字符串时在python3中获取int:

n [1]: s = b"foo"

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

在python2中你得到str / char:

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

迭代或调用next也会给出整数值:

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,否则在打开二进制文件时(例如,rb用于二进制读取),您可能并不总是打扰添加b模式。   在Python 3下,二进制文件和文本文件明显不同,互不兼容;有关详细信息,请参阅io模块。因此,您必须决定文件是用于二进制访问(允许读取和/或写入二进制数据)还是文本访问(允许读取和/或写入文本数据)。您还应该使用io.open()来打开文件而不是内置的open()函数,因为io模块从Python 2到3是一致的,而内置的open()函数则不是(在Python 3中它实际上是io.open())。

     

str和bytes的构造函数对于Python 2和&amp;之间的相同参数具有不同的语义。 3.在Python 2中将整数传递给字节将为您提供整数的字符串表示形式:bytes(3) == '3'。但是在Python 3中,字节的整数参数将为您提供一个字节对象,只要指定的整数,填充空字节:bytes(3) == b'\x00\x00\x00'。将bytes对象传递给str时,需要类似的担心。在Python 2中,您只需返回字节对象:str(b'3') == b'3'。但是在Python 3中,您将获得bytes对象的字符串表示形式: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&#39; 123&#39;,1)。