现代密码学——流密码系统(实验报告).docx
《现代密码学——流密码系统(实验报告).docx》由会员分享,可在线阅读,更多相关《现代密码学——流密码系统(实验报告).docx(17页珍藏版)》请在冰点文库上搜索。
安全SnoWolF/百度B英俊制作
课程名称现代密码学实验实验项目名称流密码系统
练习一流密码系统
【实验目的】
理解流密码加密解密过程,通过程序的实现掌握Geffe、JK触发器和LFSR的工作过程。
【实验人数】
1人
【系统环境】
Windows
【网络环境】
交换网络结构
【实验工具】
VisualStudio2019
【实验类型】
综合型
【实验原理】
1.流密码体制模型
2.分类
根据加密器中记忆元件的存储状态是否依赖于输入的明文字符可分为两类:
1.同步流密码#独立于明文字符
2.自同步流密码#依赖于输入的明文字符
目前最常用的流密码体制是二元加法流密码,是一种同步流密码,其加密变换可表示为异或函数。
3.线性反馈移位寄存器
移位寄存器是流密码长产生密钥流的一个主要组成部分。
线性反馈移位寄存器(LFSR)是指,给定前一状态的输出,将该输出的线性函数再用作输入的移位寄存器。
异或运算是最常见的单比特线性函数:
对寄存器的某些位进行异或操作后作为输入,再对寄存器中的各比特进行整体移位。
线性反馈移位寄存器输出序列的性质完全由其反馈函数决定。
1、n级线性反馈移位寄存器最多有2n个不同的状态
2、n级n级线性反馈移位寄存器的状态周期小于等于2n-1
3、周期达到最大值的序列称为m序列
仅能被非0常数或自身的常数倍除尽,但不能被其他多项式除尽的多项式称为即约多项式或不可约多项式。
n级LFSR产生的序列有最大周期2n-1的必要条件是其特征多项式为不可约的。
若n次不可约多项式p(x)的阶为2n-1,则称p(x)是n次本原多项式。
{ai}为m序列的充要条件为p(x)是本原多项式。
4.伪随机序列
Golomb对伪随机周期序列提出了应满足的如下3个随机公设:
(1)在序列的一个周期内,0与1的个数相差至多为1。
(2)在序列的一个周期内,长为1的游程占游程总数的1/2,长为2的游程占游程总数的1/4,长多为i的游程占游程总数的1/2i,且在等长的游程中0的游程个数和1的游程个数相等。
(3)异自相关函数是一个常数。
n长m序列满足Golomb的3个随机性公设,具有如下性质:
(1)在一个周期内,0和1出现的次数分别为2n-1-1和2n-1。
(2)在一个周期内,总游程数为2n-1;对1≤i≤n-2,长为i的游程有2n-i-1个,且0和1游程各半;长为n-1的0游程一个,长为n的1游程一个。
【实验内容】
自行查找相关资料,结合上次实验的主函数框架,实现流密码系统。
具体内容:
线性反馈寄存器(LFSR)+一个非线性组合子系统(Geffe序列生成器或J-K触发器)
1)可参考网上资料。
2)结合参考教材上pp17的图2-10,pp27的图2-12,图2-14。
3)不要求输出密钥流是m序列,但需给出周期大小。
4)实验报告需明确给出LFSR的线性反馈函数的递推形式,初始状态。
流秘钥生成器的输出。
加密解密的输入输出过程。
【实验过程与结果】
1. 实验源码
#include
#include
#include
#include //定义二进制bitset所需的头文件
#include //文件读写操作所需的头文件
usingnamespacestd;
#defineCHAR_SIZE 26
#defineDECRYPT_FILE "Caesar密文.txt"
#defineENCRYPT_FILE "Caesar明文.txt"
#defineN8 //常量N指定二进制位大小,也是LFSR最大级数限定
typedefstruct
{
bitsetlfsrInit; //LFSR初始态
intscale=8; //级数,默认为8
stringkey; //周期密钥流
intlfsrCycle=0; //周期
}LFSR;
typedefstruct
{
LFSRregister1; //LFSR1
LFSRregister2; //LFSR2
LFSRregister3; //LFSR3
stringkeyStream; //扩展后真正被使用到的密钥流
}GEFFE;
//返回命令提示信息
voidUsage(constchar*appname)
{
printf("\n\tusage:
stream-e明文文件密钥k\n");
printf("\tusage:
stream-d密文文件密钥k\n");
}
//校验应用程序入口参数,若参数合法返回true,否则返回false
boolCheckParse(intargc,char**argv)
{
if(argc!
=5||
(argv[2][1]!
='e'&&argv[2][1]!
='d'))
{
Usage(argv[1]);
returnfalse;
}
returntrue;
}
//加/解密结果输出到当前目录磁盘文件中,strOut指向输出字符缓冲区,strFile为输出文件
boolFileOut(conststringstrOut,stringstrFile)
{
if(strOut.empty()) //判断字符缓冲区是否为空
returnfalse;
ofstreamfileOut(strFile); //打开文件
fileOut< fileOut.close(); //关闭文件
returntrue;
}
//加/解密内容输入到字符缓冲区中,strIn指向输出字符缓冲区,strFile为输入文件
boolFileIn(char*strIn,constchar*strFile)
{
ifstreamfileIn(strFile); //打开文件
if(!
fileIn.is_open()) //判断文件是否成功打开
{
std:
:
cout<<"Erroropeningfile";
returnfalse;
}
while(!
fileIn.eof()) //直到读取到文件末尾
{
fileIn.getline(strIn,100); //读取文件,每次读100byte
}
returntrue;
}
//线性反馈寄存器LFSR
voidLfsr(LFSR&lfsr,intk)
{
bitsetbint(lfsr.lfsrInit); //将初始态存为二进制数
bitsetstr(bint);
strings1;//保存输出结果
cout<<"初始状态为:
";
/*for(inti=lfsr.scale-1;i>=0;i--) //遍历bint中的数字
cout< cout< do//生成LFSR的状态变化
{
intj=bint[lfsr.scale-1]^bint[0];//所有LFSR递归式设置为f(a1,...an)=an^a1
bint.operator>>=
(1);//向右移1位
bint[lfsr.scale-1]=j;//第1个数据和第n个数据异或然后赋值给第n个
for(inti=lfsr.scale-1;i>=0;i--)
cout< cout< bitset<1>binTemp(bint[k%lfsr.scale]);//根据密钥k,每次取移位后二进制数据的第k位
s1=binTemp.to_string();//把binTemp转换成string放入s1
lfsr.key.push_back(s1[0]);//转成char,放入LFSR密钥流
++lfsr.lfsrCycle; //周期递增
}while(str.to_string()!
=bint.to_string());//直到移位后数据与初始态相同
cout<<"输出周期密钥流序列为:
"< cout<<"周期为:
"<}
//Geffe序列生成器,连同加密解密的操作,k为密钥
boolGeffe(GEFFE&geffe,conststringstrIn,string:
:
size_typestrLen,string&strOut,string:
:
size_typek)
{//k对序列生成器的影响:
从拓展后密钥流的第k位开始,对明/密文进行加/解密操作
if(strIn.empty()) //判断输入字符缓冲区是否为空
returnfalse;
intiCount=0;
for(string:
:
size_typei=k;i {//
bitset<1>bitvec1(geffe.register1.key,i%geffe.register1.key.size(),1);//从LFSR1中周期序列取1位
bitset<1>bitvec2(geffe.register2.key,i%geffe.register2.key.size(),1);//从LFSR2中周期序列取1位
bitset<1>bitvec3(geffe.register3.key,i%geffe.register3.key.size(),1);//从LFSR3中周期序列取1位
bitset<1>bitvecKey((bitvec1&bitvec2)^(bitvec3&(~bitvec2)));//运算得1位密钥
bitset<1>bitvecIn(strIn,iCount,1);//从明/密文中取1位
bitset<1>bitvecOut(bitvecKey^bitvecIn);//加/解密操作
strOut+=bitvecOut.to_string(); //将1位结果写入输出缓冲区
geffe.keyStream+=bitvecKey.to_string(); //保存使用的密钥
}
returntrue;
}
//初始化geffe和LFSR
voidInit(GEFFE&geffe,char**argv)
{
geffe.register1.scale=7; //设置LFSR级数
geffe.register2.scale=5;
geffe.register3.scale=3;
geffe.register1.lfsrInit=64; //设置初始态
geffe.register2.lfsrInit=16;
geffe.register3.lfsrInit=4;
cout<<"LFSR1:
"< Lfsr(geffe.register1,atoi(argv[4]));//传入LFSR1和密钥k
cout<<"LFSR2:
"< Lfsr(geffe.register2,atoi(argv[4]));
cout<<"LFSR3:
"< Lfsr(geffe.register3,atoi(argv[4]));
}
intmain(intargc,char**argv)
{
if(!
CheckParse(argc,argv)) //检查命令行参数
return0;
charstrin[1024]; //输入字符缓冲区
if(!
FileIn(strin,argv[3])) //读取文件到字符缓冲区
{
cout<<"文件读取失败"< return0;
}
stringstrIn=strin,strOut,fileName="C:
\\Users\\Administrator\\Desktop\\输出.txt";
GEFFEgeffe;
Init(geffe,argv); //初始化Geffe和LFSR
booloperate=false;
operate=Geffe(geffe,strIn,strIn.size(),strOut,atoi(argv[4])); //进行加/解密操作
if(argv[2][1]=='e'&&operate==true)
cout<<"加密成功!
"< elseif(argv[2][1]=='d'&&operate==true)
cout<<"解密成功!
"< else
{
cout<<"操作失败!
"< return0;
}
if(!
FileOut(strOut,fileName)) //将输出字符缓冲区写入输出文件
{
cout<<"文件写入失败"< return0;
}
cout<<"密钥k为:
\t\t"< cout<<"输入为:
\t\t"< cout<<"实际使用密钥流:
\t"< cout<<"输出为:
\t\t"< return0;
}
2. 设计思路
(1)整体框架:
流密码系统需要包括1.读取输入文件,2.写入输出文件,3.LFSR,4.Geffe序列生成器,5.利用密钥流进行加/解密操作,共5个部分。
(2)输入输出文件,利用C++的头文件可以简单实现,用string类型将需要输入和输出的字符保存起来。
(3)LFSR部分,创建了LFSR结构体,包含初始态、级数、周期密钥流、周期的属性。
这部分还需要针对每一个LFSR根据初始态生成其对应的周期密钥流并存储起来。
生成周期密钥流过程中还需要受到密钥k的控制。
(4)Geffe序列生成器,创建了GEFFE结构体,包含三个LFSR和实际使用的密钥流的属性。
这部分包含加解密操作,根据公式和实际需要一位一位地输出密钥流序列,同时做加解密操作,最后将实际使用密钥流作保存。
生成序列密钥流的过程中需要受到密钥k的控制。
密钥k一定,得到的密钥流也一定。
3. 实验结果+调试结果图+结果分析
(1)默认设置
LFSR1级数为7,初始态a7a6a5a4a3a2a1=1000000,递推关系为f(a1,a2,a3,a4,a5,a6,a7)=a1^a7,周期为127;
LFSR2级数为5,初始态a5a4a3a2a1=10000,递推关系为f(a1,a2,a3,a4,a5)=a1^a5,周期为21;
LFSR3级数为3,初始态a3a2a1=100,递推关系为f(a1,a2,a3)=a1^a3,周期为7。
由于Geffe序列生成器对应的LFSR的级数互素,因此根据课本的结论,Geffe序列生成器的序列周期为(2^7-1)*(2^5-1)*(2^3-1)=127*31*7=27559。
(2)加密过程,密钥k=5
明文为:
101011001010011
密钥流:
110101001010101
密文为:
011110000000110
结果正确。
(3)解密过程,密钥k=5
密文为:
011110000000110
密钥流:
110101001010101
明文为:
101011001010011
结果正确。
(4)以k=5,级数为5的LFSR2为例,分析LFSR密钥流生成过程
如下图,10000为初始状态,根据递推关系为f(a1,a2,a3,a4,a5)=a1^a5,则输出为1^0=1,同时向右移位生成新序列,将输出放在高位a5,新序列为11000。
以此类推。
直到产生的新序列与初始状态10000相同,则计算总共进行了多少次移位操作,次数即为该密钥流的周期。
根据密钥k=5,对新序列的取值做限定。
例如第一个新序列11000,第0位(低位)为0,第4位(高位)为1,而k=5>4,因此做求余操作,循环至第0位,因此取11000的第0位“0”。
以此类推,取每个新序列的第0位,生成周期密钥流。
如图所示。
(5)以k=5为例,分析Geffe密钥流序列生成过程
LFSR1密钥流序列为:
1111111010101001100111011101001011000110111101101011011001001000111000010111110010101110011010001001111000101000011000001000000
LFSR2密钥流序列为:
000111110101001100010
LFSR3密钥流序列为:
1101001
由于k=5,因此从k+1(6)位开始在LFSR中取密钥流序列。
根据输入文的长度为15,因此取密钥流15位。
LFSR1取:
110101010011001
LFSR2取:
111010100110001
LFSR3取:
011101001110100
按照公式:
a1&a2^a3&(~a2)
a1&a2=110000000010001
~a2=000101011001110
a3&~a2=000101001000100
得密钥流=110101001010101
结果正确。
(6)加密过程,k=4
明文为:
101011001010011
密钥流:
110111010010101
密文为:
011100011000110
结果正确。
(7)解密过程,k=4
密文为:
011100011000110
密钥流:
110111010010101
明文为:
101011001010011
结果正确。
(8)加密过程,k=12
明文为:
101011001010011
密钥流:
100110010001110
密文为:
001101011011101
结果正确。
(9)解密过程,k=12
密文为:
001101011011101
密钥流:
100110010001110
明文为:
101011001010011
结果正确。
【实验评估】
1.实验分析
实验结果证明了,
(1)根据密钥流的加密解密过程结果无误;
(2)当密钥k一定时,能够保证密钥流的唯一性;
(3)当密钥k取不同值时,产生的密钥流也不同;
(4)Geffe序列生成器加长了密钥流序列的周期,达到了伪随机性的效果;
(5)Geffe序列生成器的序列输出,0和1的分布大致平衡。
2.实验心得
通过阅读课本和查阅网上资料充分了解了流密码加密解密过程,再而程序编写的实现使我掌握了密钥流、密钥序列的生成原理,对Geffe序列生成器、JK触发器和LFSR的工作过程有了深刻的理解。
实验过程中,因纠结如何得出求Geffe序列生成器周期的算法而耗费了大量时间,后感觉太过于复杂而放弃。
课本仅给出当3个LFSR级数互素时的周期求解方式,也说明当级数不互素时,Geffe序列生成器的周期并不容易得出来且没有规律。
实验过程中,尝试将LFSR的级数设为8,与级数为7的LFSR进行周期对比,结果发现级数为7的LFSR的周期大于级数为8的LFSR。
因此LFSR的周期不仅受级数的影响,也与初始态相关。