如何在字节文件中将';\';替换为';。
问题描述
我的问题是:我有一个加密的字节文件,如下所示:
[wx84x7f@xc6xabxc8
我想用PyCrypto解密,但我发现了一个令人困惑的错误,如下所示:
代码在此:
from Crypto.Cipher import DES
key = 'jsfghutp'
cipher = DES.new(key, DES.MODE_ECB)
s = open('d:/Thu-Aug-2018.bin','rb').read()
cipher.decrypt(s)
如果我运行此命令,它将引发错误:
ValueError Traceback (most recent call last)
<ipython-input-3-4fcf0e8076ca> in <module>()
----> 1 cipher.decrypt(s)
D:Pythonanacondalibsite-packagesCryptoCipherlockalgo.py in
decrypt(self, ciphertext)
293 return res
294
--> 295 return self._cipher.decrypt(ciphertext)
296
ValueError: Input strings must be a multiple of 8 in length
我打印%s的值:
s = b'[w\x84\x7f@\xc6\xab\xc8'
但是这是不对的,我需要的是以下结果:
>>> cipher.decrypt(b'[wx84x7f@xc6xabxc8')
b'test aaa'
也就是,我想我必须将bytes文件中的\\
替换为,但我没有用正确的方法做到这一点。有人知道如何解决这个问题吗?
解决方案
文件中没有双反斜杠。查看bytes
对象的repr
时,它会显示所有反斜杠都进行了转义,以避免混淆,例如
(换行符)和\n
(反斜杠后跟n
)。
例如:
>>> s = rb'x84'
>>> s
b'\x84'
>>> s[0]
92
>>> chr(s[0])
'\'
所以,您所询问的问题并不存在。您的文件中只有一个反斜杠。
实际问题是,您不想要四个字节的反斜杠、x、8和4,您想要单字节b'x84'
,也就是chr(0x84)
。但这四个字节是您文件中的内容。
所以您的错误存在于您用来创建此文件的代码中。不知何故,您没有将字节转储到文件中,而是转储了这些字节的反斜杠转义字符串表示。修复它的正确位置是在创建该文件的代码中。不写入损坏的数据总是比写入损坏的数据,然后尝试找出如何恢复损坏的数据要好。
但如果为时已晚--例如,如果您使用破解的代码加密了一堆您不再有权访问的明文,而现在您需要尝试恢复它-那么这种转换恰好是可逆的。你只需分两步完成。首先,使用反斜杠转义或更通用的Unicode转义编解码器对字节进行解码:
>>> s=rb'[wx84x7f@xc6xabxc8'
>>> s
b'[w\x84\x7f@\xc6\xab\xc8'
>>> s.decode('unicode-escape')
'[wx84x7f@Æ«È'
然后将每个Unicode字符转换为与相同数字匹配的字节,显式:
>>> bytes(map(ord, s.decode('unicode-escape')))
b'[wx84x7f@xc6xabxc8'
…或者,有点粗俗地依赖于Python对拉丁语-1的解释:1
>>> s.decode('unicode-escape').encode('latin-1')
b'[wx84x7f@xc6xabxc8'
同样,这些反斜杠实际上并不在字符串中,这只是Python表示bytes
的方式。例如,如果您将其放在b
中,hex(b[2])
对于字节x84
是0x84
,而不是0x5c
对于反斜杠字符。
您的创建代码才是真正的问题:
with open(file,'a') as f:
f.write(str(encrypt_text).split("b'")[1].split("'")[0])
f.close()
您要将字节转换为它们的字符串表示形式--使用b
前缀、前后的引号和每个不能打印的ASCII字节的反斜杠进行转义,然后去掉b
和引号,然后通过将其写入文本模式文件将整个内容编码为UTF-8。
您要做的就是以二进制模式打开文件并向其中写入字节:
with open(file, 'ab') as f:
f.write(encrypt_text)
(另外,您也不希望调用f.close()
;with
语句已经处理了这一点。)
然后您可以以二进制模式读取文件,并按原样解密字节。
(或者,如果您真的希望文件是可供人类编辑的或其他什么,您希望选择一种设计为可供人类编辑且易于逆转的格式,如hexlify
或base64
,而不是"无论Python执行什么操作来表示bytes
调试对象"。)
1.对于拉丁文-1中的所有字符,Unicode保证与拉丁文-1对齐。Python将其解释为拉丁文-1应该将从0到255的每个字节编码为码位0-255,而不仅仅是ISO-8859-1中实际定义的码位。这是有效的,因为ISO-8859-1没有说明如何处理它没有定义的字节,但并不是每个工具都会同意Python.
相关文章