11-按顺序读取数据
1.3.1 按顺序读取数据
以下示例将用一次性密码本方案加密一个 srt 。Python 3的 str 类型有一种用法可被视为UTF-8字节序列(UTF-8是一种Unicode字符编码)。通过 encode() 方法可将 str 转换为UTF-8字节序列(以 bytes 类型表示)。同理,用 bytes 类型的 decode() 方法可将UTF-8字节序列转换回 str 。
一次性密码本的加密操作中用到的假数据必须符合3条标准,这样最终的结果才不会被破解。假数据必须与原始数据长度相同、真正随机、完全保密。第1条标准和第3条标准是常识。如果假数据因为太短而出现重复,就有可能被觉察到规律。如果其一个密钥不完全保密(可能在其他地方被重复使用或部分泄露),那么攻击者就能获得一条线索。第2条标准给自己出了一道难题:能否生成真正随机的数据?大多数计算机的答案都是否定的。
本例将会用到 secrets 模块的伪随机数据来生成函数 token_ bytes() (自Python 3.6开始包含在于标准库中)。这里的数据并非是真正随机的,因为 secrets 包在幕后采用的仍然是伪随机数生成器,但它已足够接近目标了。下面就来生成一个用作假数据的随机密钥,具体代码如代码清单1-15所示。
代码清单1-15 unbreakable_encryption.py
from secrets import token_bytes
from typing import Tuple
def random_key(length: int) -> int:
# generate length random bytes
tb: bytes = token_bytes(length)
# convert those bytes into a bit string and return it
return int.from_bytes(tb, "big")
以上函数将创建一个长度为 length 字节的 int ,其中填充的数据是随机生成的。 int. from_bytes() 方法用于将 bytes 转换为 int 。如何将多字节数据转换为单个整数呢?答案就在1.2节。在1.2节中已经介绍过 int 类型可为任意大小,而且还展示了 int 能被当作通用的位串来使用。本节以同样的方式使用 int 。例如, from_bytes() 方法的参数是7字节(7字节×8位/字节= 56位),该方法会将这个参数转换为56位的整数。为什么这种方式很有用呢?因为与对序列中的多字节进行操作相比,对单个 int (读作“长位串”)进行位操作将更加简单高效。下面将会用到XOR位运算。