当前位置:嗨网首页>书籍在线阅读

12-加密和解密

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

1.3.2 加密和解密

如何将假数据与待加密的原始数据进行合并呢?这里将用XOR操作来完成。XOR是一种逻辑位操作(二进制位级别的操作),当其中一个操作数为真时返回 true ,而如果两个操作数都为真或都不为真则返回 false 。可能大家都已猜到了,XOR代表“异或”。

Python中的XOR操作符是“^”。在二进制位的上下文中, 0^11^0 将返回 1 ,而 0^01^1 则会返回 0 。如果用XOR合并两个数的二进制位,那么把结果数与其中某个操作数重新合并即可生成另一个操作数,这是一个很有用的特性。

A ^ B = C
C ^ B = A
C ^ A = B

上述重要发现构成了一次性密码本加密方案的基础。为了生成结果数据,只要简单地将原始 str 以字节形式表示的 int 与一个随机生成且位长相同的 int (由 random_key() 生成)进行异或操作即可。返回的密钥对就是假数据和加密结果。具体代码如代码清单1-16所示。

代码清单1-16 unbreakable_encryption.py(续)

def encrypt(original: str) -> Tuple[int, int]:
    original_bytes: bytes = original.encode()
    dummy: int = random_key(len(original_bytes))
    original_key: int = int.from_bytes(original_bytes, "big")
    encrypted: int = original_key ^ dummy  # XOR
    return dummy, encrypted

注意 int.from_bytes() 要传入两个参数。第一个参数是需要转换为 intbytes 。第二个参数是这些字节的字节序(endianness) " big " 。字节序是指存储数据所用的字节顺序。首先读到的是最高有效字节(most significant byte),还是最低有效字节(least significant byte)?在本示例中,只要加密和解密时采用相同的顺序就无所谓,因为实际只会在单个二进制位级别操作数据。如果是在编码过程的两端不全由自己掌控的其他场合,字节序可能是至关重要的因素,所以请务必小心!

解密过程只是将 encrypt() 生成的密钥对重新合并而已。只要在两个密钥的每个二进制位之间再次执行一次XOR运算,就可完成解密任务了。最终的输出结果必须转换回 str 。首先,用 int.to_bytes()int 转换为 bytes 。该方法需要给定 int 要转换的字节数。只要把总位长除以8(每字节的位数),就能获得该字节数。最后,用 bytes 类型的 decode() 方法即可返回一个 str 。具体代码如代码清单1-17所示。

代码清单1-17 unbreakable_encryption.py(续)

def decrypt(key1: int, key2: int) -> str:
    decrypted: int = key1 ^ key2  # XOR
    temp: bytes = decrypted.to_bytes((decrypted.bit_length()+ 7) // 8, "big")
    return temp.decode()

在用整除操作( // )除以8之前,必须给解密数据的长度加上7,以确保能“向上舍入”,避免出现边界差一(off-by-one)错误。如果上述一次性密码本的加密过程确实有效,那么应该就能毫无问题地加密和解密Unicode字符串了。具体代码如代码清单1-18所示。

代码清单1-18 unbreakable_encryption.py(续)

if __name__ == "__main__":
    key1, key2 = encrypt("One Time Pad!")
    result: str = decrypt(key1, key2)
    print(result)

如果控制台输出了“ One Time Pad! ”,就万事大吉了。