我最近开始学习Python,我选择通过尝试解决一个我觉得有趣的问题来学习东西。这个问题是获取一个文件(二进制或非二进制)并使用一种简单的方法对其进行加密,例如将其中的每个“1001 0001”替换为“0010 0101”,反之亦然。
然而,我没有找到办法去做。读取文件时,我可以使用 read() 方法创建一个数组,其中每个元素包含一个字节的数据。但是,如果这个字节是我选择替换的字节之一,我该如何用另一个字节替换它,然后将结果信息写入输出加密文件?
提前致谢!
交换字节
10010001
和00100101
:
#!/usr/bin/env python
import string
a, b = map(chr, [0b10010001, 0b00100101])
translation_table = string.maketrans(a+b, b+a) # swap a,b
with open('input', 'rb') as fin, open('output', 'wb') as fout:
fout.write(fin.read().translate(translation_table))
read() 返回一个不可变字符串,因此您首先需要将其转换为字符列表。然后遍历列表并根据需要更改字节,最后将列表加入新字符串以写入输出文件。
filedata = f.read()
filebytes = list(filedata)
for i, c in enumerate(filebytes):
if ord(c) == 0x91:
filebytes[i] = chr(0x25)
newfiledata = ''.join(filebytes)
我很抱歉这个有点相关的文字墙——我只是在教学中。
如果你想优化这样的操作,我建议使用numpy。优点是整个翻译操作是通过单个 numpy 操作完成的,而且这些操作是用 C 编写的,所以它和使用 python 一样快。
在下面的示例中,我使用查找表简单地对每个字节与0b11111111
进行
XOR——第一个元素是
0b0000000
的翻译,第二个是0b00000001
的翻译,第三个是0b00000010
,依此类推。通过更改查找表,您可以在文件中进行任何类型的翻译。
import numpy as np
import sys
data = np.fromfile(sys.argv[1], dtype="uint8")
lookup_table = np.array(
[i ^ 0xFF for i in range(256)], dtype="uint8")
lookup_table[data].tofile(sys.argv[2])
为了突出它的简单性,我没有进行参数检查。像这样调用脚本:
python name_of_script.py input_file.txt output_file.txt
直接回答你的问题,如果你想交换
0b10010001
和0b00100101
,你用这个替换lookup_table = ...
行:
lookup_table = np.array(range(256), dtype="uint8")
lookup_table[0b10010001] = 0b00100101
lookup_table[0b00100101] = 0b10010001
当然,没有使用 频率分析 不容易破解的查找表加密。但正如您所知,使用一次性密码本的加密是牢不可破的,只要密码本是安全的。这个修改后的脚本使用一次一密来加密或解密(你必须自己创建,存储到一个文件,并以某种方式(有摩擦)安全地传输给消息的预期接收者):
data = np.fromfile(sys.argv[1], dtype="uint8")
pad = np.fromfile(sys.argv[2], dtype="uint8")
(data ^ pad[:len(data)]).tofile(sys.argv[3])
示例用法(linux):
$ dd if=/dev/urandom of=pad.bin bs=512 count=5
$ python pytrans.py pytrans.py pad.bin encrypted.bin
收件人然后做:
$ python pytrans.py encrypted.bin pad.bin decrypted.py
中提琴!在 python 中使用三行(加上两行导入)进行快速且牢不可破的加密。