这是我的问题:我有一个像这样的加密字节文件:
localStorage.getItem()
我想用PyCrypto对其解密,但是我发现了一个类似以下的困惑错误:
此处的代码:
[w\x84\x7f@\xc6\xab\xc8
如果我运行此命令,它将引发错误:
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)
我打印s的值:
ValueError Traceback (most recent call last)
<ipython-input-3-4fcf0e8076ca> in <module>()
----> 1 cipher.decrypt(s)
D:\Python\anaconda\lib\site-packages\Crypto\Cipher\blockalgo.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 = b'[w\\x84\\x7f@\\xc6\\xab\\xc8'
也就是说,我认为我必须在字节文件中将>>> cipher.decrypt(b'[w\x84\x7f@\xc6\xab\xc8')
b'test aaa'
替换为\\\\
,但是我无法以正确的方式执行。有谁知道如何解决这个问题?
答案 0 :(得分:3)
文件中没有双反斜杠。当您查看repr
对象的bytes
时,它会显示所有转义的反斜杠,以避免\n
(换行符)和\\n
(反斜杠)之间的混淆后跟n
)。
例如:
>>> s = rb'\x84'
>>> s
b'\\x84'
>>> s[0]
92
>>> chr(s[0])
'\\'
因此,您要询问的问题不存在。您的文件中只有一个反斜杠。
实际的问题是,您不希望四个字节的反斜杠x,8和4,而是想要单个字节b'\x84'
,也称为chr(0x84)
。但是这四个字节就是文件中的字节。
因此,您的错误是在用于创建此文件的任何代码中进行的。不知何故,您没有将字节转储到文件中,而是转储了这些字节的反斜杠转义的字符串表示形式。修复此错误的正确位置是在创建文件的代码中。不写损坏的数据总是比写损坏的数据总要好,然后再设法弄清它们。
但是,如果为时已晚,例如,如果您使用该破损的代码来加密一堆您不再可以访问的纯文本,现在您需要尝试恢复它,那么这种转换就会发生是可逆的。您只需分两个步骤进行操作。
首先,您使用反斜杠转义或更通用的Unicode转义编解码器解码字节:
>>> s=rb'[w\x84\x7f@\xc6\xab\xc8'
>>> s
b'[w\\x84\\x7f@\\xc6\\xab\\xc8'
>>> s.decode('unicode-escape')
'[w\x84\x7f@Æ«È'
然后将每个Unicode字符转换为与相同数字匹配的字节,或者显式地:
>>> bytes(map(ord, s.decode('unicode-escape')))
b'[w\x84\x7f@\xc6\xab\xc8'
...,或者说有点诡异,依靠Python对Latin-1的解释: 1
>>> s.decode('unicode-escape').encode('latin-1')
b'[w\x84\x7f@\xc6\xab\xc8'
同样,这些反斜杠实际上不在字符串中,这就是Python表示bytes
的方式。例如,如果将其放在b
中,则hex(b[2])
对于字节0x84
是\x84
,而不是反斜杠字符0x5c
。
您的创建代码是真正的问题:
with open(file,'a') as f:
f.write(str(encrypt_text).split("b'")[1].split("'")[0])
f.close()
您正在将字节转换为它们的字符串表示形式-带有b
前缀,其周围的引号以及每个不可打印ASCII的字节的反斜杠转义,然后剥离{{1} }和引号,然后通过将其写入文本模式文件将其编码为UTF-8。
您要做的只是以二进制模式打开文件并将字节写入其中:
b
(而且,您不想调用with open(file, 'ab') as f:
f.write(encrypt_text)
; f.close()
语句已经解决了这个问题。)
然后,您可以以二进制模式读取文件,然后按原样解密字节。
(或者,如果您确实希望文件是可人工编辑的或类似的东西,则希望选择一种设计为可人工编辑且易于可逆的格式,例如with
或hexlify
,而不是“ Python为表示base64
对象进行调试所做的一切”。)
1。对于Latin-1中的所有字符,均保证Unicode与Latin-1对齐。 Python解释说这意味着Latin-1应该将0-255中的每个字节编码为代码点0-255,而不仅仅是ISO-8859-1中实际定义的字节。这是有效的,因为ISO-8859-1并未说明如何处理未定义的字节,但并非每个工具都同意Python。
答案 1 :(得分:1)
发生这种情况是因为文件包含字节字符串的文本表示形式([w\x84\x7f@\xc6\xab\xc8
),但实际上不是字节本身。您是否正确写入文件:
with open('/tmp/file', 'wb') as f:
f.write(b'[w\x84\x7f@\xc6\xab\xc8')
那么您阅读它就不会有问题了
>>> with open('/tmp/file', 'rb') as f: f.read()
<<< b'[w\x84\x7f@\xc6\xab\xc8'
或者通过ast.literal_eval
解释保存在文件中的表示形式,尽管在这种情况下确实不建议这样做。
最重要的是:始终知道您使用的是什么类型-字符串(unicode)或字节,并且请记住,当您在控制台中打印字节时,您会看到表示形式(类似于\ xa0的东西) ,而不是字节本身,因为某些字节没有可打印的格式。