自己写了一个名为 “imgSeed.py” 的模块,可以生成图种,也可以从图种中分离出文件。
import os
import base64
import time
__doc__ = """
This module aims at secret file transmission by attaching a secret file to
a cover file. By doing so, the secret file will be hidden in the cover file
and becomes invisible unless you know what it is.
Example:
import imgSeed
imgSeed.zipfile('cover.png', 'hidden.rar', out='output.png') # No encoding
# Without encoding, you can get the hidden file by merely changing it's extension
# into a proper form (here is '.rar'). Also, you can get the original file by
# using unzip function in this module.
imgSeed.zipfile('cover.png', 'hidden.rar', method='base64') # Encode by base64
imgSeed.unzip('output.png') # Decode the file
# With encoding, you need to use the unzip function in this module to decode
# the hidden file so that you can get it.
"""
__all__ = ['zipfile', 'unzip']
__methods__ = ['base16', 'base32', 'base64', 'ascii85', 'encodebytes']
def zipfile(cover, hidden, out=None, method=None):
"""
To hide a private file in any other file. You can encode the hidden file
then link it to the cover file. Also, you can merely link it to the cover file
directly without encoding, in order that you can read the hidden file
by changing it's extension into a proper form, which is so called image seed
also Tu Zhong in Chinese. You can find the output file in the given path or cover file's path.
:param cover: the cover file, which is visible.
:param hidden: the file to be hidden in the cover file.
:param out: the output file whose extension is the same as cover file's.
:param method: the method to encode the hidden file.
:return: None
"""
def encode(method_):
"""
To encrypt the private file then link it to anther file.
:param method_: equal to the previous parameter 'method'.
:return: None
"""
print('Linking...')
methods = {'b16': (base64.b16encode, 'base16'), 'base16': (base64.b16encode, 'base16'),
'b32': (base64.b32encode, 'base32'), 'base32': (base64.b32encode, 'base32'),
'b64': (base64.b64encode, 'base64'), 'base64': (base64.b64encode, 'base64'),
'a85': (base64.a85encode, 'base85'), 'ascii85': (base64.a85encode, 'ascii85'),
'eb': (base64.encodebytes, 'encodebytes'), 'encodebytes': (base64.encodebytes, 'encodebytes')}
with open(cover, 'rb') as reader:
cover_byte = reader.read()
with open(hidden, 'rb') as reader:
hidden_byte = reader.read()
num = 0
output_name = os.path.split(out)[1] if out else 'output'
output_path = os.path.split(out)[0] if out else '.'
if not os.path.exists(output_path):
output_path = '.'
output_ext = os.path.splitext(output_name)[1]
output_ext = output_ext if output_ext else os.path.splitext(cover)[1]
while True:
outfile = os.path.join(output_path, output_name + ('' if num == 0 else str(num)) + output_ext)
if os.path.exists(outfile):
num += 1
else:
break
method_ = methods[method_][1] if method_ in methods else None
hidden_byte = methods[method_][0](hidden_byte) if method_ else hidden_byte
cover_size = len(cover_byte)
hidden_size = len(hidden_byte)
file_info = (str(f'method={method_}&f1={cover_paths[1]}&f2={os.path.split(hidden)[1]}&f1_size={cover_size}&f2_size={hidden_size}\n')).encode('utf-8')
content = cover_byte + hidden_byte + file_info
with open(outfile, 'wb') as writer:
writer.write(content)
print('Done.')
if not os.path.exists(cover):
print(f'"{cover}" is not found.')
return
if not os.path.isfile(cover):
print(f'"{cover}" is not a file.')
return
cover_paths = os.path.split(cover)
if os.path.exists(hidden):
encode(str(method).lower())
elif os.path.exists(os.path.join(cover_paths[0], hidden)):
encode(str(method).lower())
else:
print(f'"{hidden}" is not found.')
def unzip(file, out=os.getcwd()):
"""
Get the original files. To divide the given file, which is generated by
the zipfile function in this module, into a cover file and a hidden file.
:param file: the path of the file to be divided.
:param out: the output directory.
:return: None
"""
if not os.path.exists(file):
print(f'"{file}" is not found.')
return
print('Separating...')
with open(file, 'rb') as reader:
lines = reader.readlines()[-1]
index = lines.index(b'method')
file_info = lines[index:]
reader.seek(0)
content_byte = reader.read()[:-len(file_info)]
date = time.strftime(' %Y-%m-%d_%H-%M-%S')
info = {kw.split('=')[0].strip(): kw.split('=')[1].strip() for kw in file_info.decode('utf-8').split('&')}
methods = {'b16': base64.b16decode, 'base16': base64.b16decode,
'b32': base64.b32decode, 'base32': base64.b32decode,
'b64': base64.b64decode, 'base64': base64.b64decode,
'a85': base64.a85decode, 'ascii85': base64.a85decode,
'eb': base64.decodebytes, 'encodebytes': base64.decodebytes}
file1 = os.path.splitext(info['f1'])
file1_size = int(info['f1_size'])
file2 = os.path.splitext(info['f2'])
file2_size = int(info['f2_size'])
if not os.path.exists(out):
out = '.'
with open(os.path.join(out, date.join(file1)), 'wb') as writer:
writer.write(content_byte[:file1_size])
with open(os.path.join(out, date.join(file2)), 'wb') as writer:
if info['method'] in methods:
writer.write(methods[info['method']](content_byte[-file2_size:]))
else:
writer.write(content_byte[-file2_size:])
print('Done!')
def main():
pass
if __name__ == '__main__':
main()