PyCrypto 如何检查文件是否已使用 AES 加密?
from Crypto.Cipher import AES
def encrypt_file(key, in_filename, out_filename=None, chunksize=64*1024):
""" Encrypts a file using AES (CBC mode) with the
given key.
key:
The encryption key - a string that must be
either 16, 24 or 32 bytes long. Longer keys
are more secure.
in_filename:
Name of the input file
out_filename:
If None, '<in_filename>.enc' will be used.
chunksize:
Sets the size of the chunk which the function
uses to read and encrypt the file. Larger chunk
sizes can be faster for some files and machines.
chunksize must be divisible by 16.
"""
if not out_filename:
out_filename = in_filename + '.enc'
iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
encryptor = AES.new(key, AES.MODE_CBC, iv)
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += ' ' * (16 - len(chunk) % 16)
outfile.write(encryptor.encrypt(chunk))
这是我加密文件的方法,但如果你对同一个文件运行这个程序两次或更多次,它会不停地加密这个文件,毫不犹豫。我想加一个检查,看看这个文件是否已经用AES加密过?这样做可以吗?
2 个回答
2
除非你有某种神奇的头部信息可以被检测到(比如在Linux系统中,LUKS加密的磁盘镜像有一个头部块来提供额外的功能,但DM-Crypt就没有),否则很难判断输入的字符串是否被加密。
参考链接:如何判断数据是否被加密?
5
最常用的解决方案是在加密文件的开头写一个“魔法”字符串,后面跟着加密的内容。如果在读取文件时找到这个字符串,就会拒绝进一步的解密。解密时会读取这个字符串,以确认这是我们加密的文件,但其他内容就不管了。
想象一下,你用“ MyCrYpT”作为这个魔法字符串(其实用什么都无所谓,只要它比较独特就行)。
magic = "MyCrYpT"
# writing the encrypted file
with open(out_filename, 'wb') as outfile:
outfile.write(magic) # write the identifier.
outfile.write(struct.pack('<Q', filesize)) # file size
outfile.write(iv)
# et cetera
现在,在读取文件时,我们会读取所有的数据,然后检查这是不是我们的文件。如果是的话,就把这个魔法字符串丢掉,处理剩下的内容。
with open(in_filename, 'rb') as infile:
data = infile.read()
if data[:len(magic)] != magic:
raise ValueError('Not an encrypted file')
filedata = data[len(magic):]
# Proces the file data