这篇文章来谈谈流密码,这也是我本人的研究方向。
假设老王是一个工作在国外的特工,需要把获得的紧急情报传回国内总部。但是敏感的网络都会有监视,所以他不能直接发明文,必须把情报加密以后才能发出去。假设情报是电子版的,内容比较多,可能有好几 G,老王必须尽可能快的把消息发出去,那么老王应该怎样加密,才能既保证安全性(不被对手破译),又能兼顾效率(国内的同事可以很快解密)呢?
这可难不倒老王。情报么,就是一串有规律的 0-1 序列而已;加密么,就是用某种自己人才能 "看得懂" 的方式把它打乱变成一串没有规律的 0-1 序列而已。经过权衡比较,老王决定采用流密码的加密方法:他先生成一串与明文同样长度的、随机的 0-1 序列,这个序列我们称之为密钥流,然后用这个密钥流与明文相加(即异或运算),得到的新的序列就是要发送的密文。国内的同事收到密文之后,把密文与密钥流再进行一次异或运算就还原出了明文。过程很简单,是不是?(这里需要假定老王的同事是知道这个密钥流的,比如是和老王出发前商量好的)
这个过程说的直观点,就是用一串随机的 0-1 序列像桌布一样 “覆盖” 在明文上,解密的时候把这层布拿掉即可。
这里需要解释一下为什么要采用随机的密钥流。随机的意思就是密钥的各个比特之间是独立的,这样对方即使截获了你的密文并且知道其中一段对应的明文,从而得出这一段密钥,但是由于密钥的随机性,他无法由此段密钥推出密钥流的其余部分,这样就保护了其余的密文的安全。
如果密钥不是随机的呢?比如老王偷个懒,设置成 110110110110 ... 无限循环会怎样?那敌人拿到一段明文和对应的密文以后一对比,哇擦!这人太厚道了!看数字找规律,这游戏小学生都会,于是剩下的明文直接就赤裸裸的呈现在敌人面前了。
所以流密码的一个基本原则,就是生成的密钥流必须是随机的,至少看起来是随机的。
说起来容易做起来难,生成足够长的随机序列可是计算机科学里面的一大难题。有人说这好办,找个均匀的硬币反复地扔,正面朝上记作 1,反面朝上记作 0,得到的就是随机序列。还有人说,鼠标的移动基本是随机的,写个监视程序记录老王鼠标的移动,然后转换成二进制序列不就行了。且不说几个 G 的情报这么加密老王这辈子搞不搞的完,他怎么把生成的随机序列告诉他的同事?要是能安全的把几个 G 的密钥流传回去,那还费心思加密做什么?直接传明文不就得了?
所以只能想办法生成一段伪随机的密钥流。这里一个序列是伪随机序列的意思是表面看起来它是随机的,但实际是用一个确定的算法作用在一小部分随机的比特上得到的。或者说,这个密钥流是从一个比较短的密钥 $K$ 出发,用一个确定的函数 $f$ 生成的。老王只要和同事事先定好这个短密钥 $K$ 和扩张函数 $f$ 即可。
那么这个函数 $f$ 应该满足怎样的性质呢?应该怎么选择呢?这里面的学问可真不少。