一、密码学中的随机数
许多密码系统的安全性都依赖于随机数的生成,例如DES加密算法中的密钥,RSA加密和数字签名中的素数。
序列密码的保密性完全取决于密钥的随机性。
如果密钥是真正的随机数,则这种体制在理论上就是不可破译的。但这种方式所需的密钥量大得惊人,在实际上是不可行的。目前一般采用伪随机序列来代替随机序列作为密钥序列,也就是序列存在着一定的循环周期。这样序列周期的长短就成为保密性的关键。如果周期足够长,就会有比较好的保密性。现在周期小于10的10次方的序列很少被使用,周期长达10的50次方的序列也并不少见。
伪随机数产生器(PRNG):
何谓伪随机数产生器(PRNG)?假定需要生成介于1和10之间的随机数,每一个数出现的几率都是一样的。理想情况下,应生成0到1之间的一个值,不考虑以前值,这个范围中的每一个值出现的几率都是一样的,然后再将该值乘以10。
由任何伪随机数生成器返回的数目会受到0到N之间整数数目的限制。因为常见情况下,伪随机数生成器生成0到N之间的一个整数,返回的整数再除以N。可以得出的数字总是处于0和1之间。对生成器随后的调用采用第一次运行产生的整数,并将它传给一个函数,以生成0到N之间的一个新整数,然后再将新整数除以N返回。
二、序列密码的概念及模型
- 密钥发生器(也称滚动密钥发生器)输出一系列比特流(记为k1,k2,k3...ki),密钥流(也称滚动密钥)跟明文比特流(记为m1,m2...mi)进行异或运算产生密文比特流。
- 在解密端,密文流与完全相同的密钥流异或运算恢复出明文流。
事实上,序列密码算法的安全性依赖于简单的异或运算和一次一密乱码本。密钥流发生器生成的看似随机的密钥流实际上是确定的,在解密的时候能很好的将其再现。密钥流发生器输出的密钥越接近随机,对密码分析者来说就越困难。
一次一密乱码本:一种理想的加密方案,可以简单理解为每个密钥仅对一个消息使用一次。
如果密钥流发生器每次都生成同样的密钥流的话,就很容易被破译。假设Alice得到一份密文和相应的明文,她就可以将两者异或恢复出密钥流。或者,如果她有两个用同一个密钥流加密的密文,她就可以让两者异或得到两个明文互相异或而成的消息,接着就可以用明文和密文异或得出密钥流。在这种情况下,她就可以解密拦截到的任何密文消息,并阅读以前截获到的消息。
因此,流密码强度完全依赖于密钥序列的随机性和不可预测性。
所有序列密码都有密钥,且密钥发生流的输出是密钥的函数。
三、流密码的分类
序列密码体制关键就在于这个产生密钥序列的方法,也就是密钥序列产生器应具有良好的随机性,让密钥序列不可预测。不过一般都是伪随机。分组密码的关键是加解密算法让明文密文关联尽可能复杂。
序列密码分为同步序列密码和自(异)同步序列密码。啥区别呢,就是前者密钥序列独立于明文序列和密文序列。后者并不独立。
同步序列密码:
密钥流的产生于明文消息流相互独立,即密钥序列产生算法与明文无关,所产生的密钥序列也与明文无关。在通信过程中,通信的双方必须保持精确的同步,收方才能正确解密,如果失步收方将不能正确解密。例如,如果通信中丢失或增加了一个密文字符,则收方的解密将一直错误。
同步序列密码就是密钥流的每一位是前面固定数量密文位的函数。如上图,其中,内部状态是前面n比特密文的函数,该算法的密码复杂性在于输出函数,它收到内部状态后生成密钥序列位。
实际上,序列密码不可能做到“一次一密”,但若密钥流生成器生成的密钥周期足够长,且随机性好,其安全强度可以得到保证!因此,序列密码的设计核心在于密钥流生成器的设计,序列密码的安全强度取决于密钥流生成器生成的密钥周期、复杂度、随机(伪随机)特性等。
自同步序列密码:
密钥流的产生于之前已经产生的若干密文有关,即密钥序列产生算法与明文(密文)相关,则所产生的密钥序列与明文(密文)相关。
https://wenku.baidu.com/view/56ffd3c20c22590103029d04.html
https://max.book118.com/html/2016/1207/69368879.shtm
A5-1 序列密码算法:
https://github.com/RangeNetworks/liba53/blob/master/a53test.cpp
1、假设有以下三个初始移位寄存器(先只要知道有三个移位寄存器(就是普通寄存器),分别有19位,22位,23位)
2、然后是如何开始生成秘钥的,假设有三个寄存器目前的状态是这样:
3、接下来开始进行规定的流程(这是规定,别问我为什么这样做)
(1)首先找到X8=1,Y10=0,Z10=1
(2)取数量最多的作为结果M=Maj(X8,Y10 , Z10 )= Maj(1,0, 1)=1;(如果是M=Maj(0,0,1)=0)
(3)因为M=1,且X8=1,M=X8,所以X寄存器需要左移一位,那么因为左移,第一位就空出来了,则 X0= (移位前的)=1
所以最后X寄存器变为
同理,再看Y寄存器,因为M=1,Y10=0,所以Y寄存器不需要进行移位,保持不变(如果是M=Y10 Z0=)
同理,Z寄存器,因为M=1,Z10=1,所以Z寄存器需要左移一位,第一位Z0==0
所以最后Y寄存器变为
所以最后得到的三个移位寄存器是
秘钥是S0==1,
就这样得到了第一位秘钥,如果需要64位秘钥,则按照上述进行循环64次操作即可。
RC4序列密码算法:
RC4算法加密流程:包括密钥调度算法KSA和伪随机子密码生成算法PRGA两大部分(以密钥长度为256个字节为例)。
密钥调度算法:首先初始化状态矢量S,矢量S中元素的值被按升序从0到255排列,即S[0]=00, S[1]=1, …, S[255]=255.同时建立一个临时矢量T,如果密钥K的长度为256字节,则将K赋给T。否则,若密钥长度为keylen字节,则将K的值赋给T的前keylen个元素,并循环重复用K的值赋给T剩下的元素,直到T的所有元素都被赋值。
在介绍RC4算法原理之前,先看看算法中的几个关键变量:
1、密钥流:RC4算法的关键是根据明文和密钥生成相应的密钥流,密钥流的长度和明文的长度是对应的,也就是说明文的长度是500字节,那么密钥流也是500字节。当然,加密生成的密文也是500字节,因为密文第i字节=明文第i字节^密钥流第i字节;
2、状态向量S:长度为256,S[0],S[1].....S[255]。每个单元都是一个字节,算法运行的任何时候,S都包括0-255的8比特数的排列组合,只不过值的位置发生了变换;
3、临时向量T:长度也为256,每个单元也是一个字节。如果密钥的长度是256字节,就直接把密钥的值赋给T,否则,轮转地将密钥的每个字节赋给T;
4、密钥K:长度为1-256字节,注意密钥的长度keylen 与明文长度、密钥流的长度没有必然关系,通常密钥的长度趣味16字节(128比特)。
RC4的原理分为三步:
1、初始化S和T
for i=0 to 255 do
S[i] =i;
T[i]=K[ imodkeylen ];
2、初始排列S
for i=0 to 255 do
j= ( j+S[i]+T[i])mod256;
swap(S[i],S[j]);
3、产生密钥流
for r=0 to len do //r为明文长度,r字节
i=(i+1) mod 256;
j=(j+S[i])mod 256;
swap(S[i],S[j]);
t=(S[i]+S[j])mod 256;
k[r]=S[t];
https://github.com/kholia/RC4-40-brute-office
ZUC序列密码算法:
https://blog.csdn.net/weixin_41656797/article/details/81182638
分组密码与序列密码的区别
分组密码:是对一个大的明文数据块(分组)进行固定变换的操作。
序列密码:是对单个明文位的随时间变换的操作。
尽管分组和序列密码非常不同,但分组密码也可作为序列密码使用,反之亦然。两者的区别主要体现在实现上:
1. 每次只能对一个数据位进行加密和解密的序列密码并不适用于软件实现。分组密码算法就可以很容易地用软件实现,因为它可以避免耗时的位操作,并且它易于处理计算机界定大小的数据分组。
2. 序列密码更适合用硬件实现,因为使用硅材料可以非常有效地实现它。