如何在字节文件中将'\'替换为'。

2022-04-18 00:00:00 python python-3.x python-3.5

问题描述

我的问题是:我有一个加密的字节文件,如下所示:

[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])对于字节x840x84,而不是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语句已经处理了这一点。)

然后您可以以二进制模式读取文件,并按原样解密字节。

(或者,如果您真的希望文件是可供人类编辑的或其他什么,您希望选择一种设计为可供人类编辑且易于逆转的格式,如hexlifybase64,而不是"无论Python执行什么操作来表示bytes调试对象"。)


1.对于拉丁文-1中的所有字符,Unicode保证与拉丁文-1对齐。Python将其解释为拉丁文-1应该将从0到255的每个字节编码为码位0-255,而不仅仅是ISO-8859-1中实际定义的码位。这是有效的,因为ISO-8859-1没有说明如何处理它没有定义的字节,但并不是每个工具都会同意Python.

相关文章