密码学课程设计实验报告.docx
《密码学课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《密码学课程设计实验报告.docx(23页珍藏版)》请在冰豆网上搜索。
![密码学课程设计实验报告.docx](https://file1.bdocx.com/fileroot1/2023-1/27/80c9163d-ca72-4322-8920-8827c9fdee41/80c9163d-ca72-4322-8920-8827c9fdee411.gif)
密码学课程设计实验报告
密码学课程设计实验报告
院系计算机科学与技术学院
专业信息安全
班级0703
学号xxxxxxxxxx
姓名xxxxxx
指导教师xxxxxxxx
2010年3月18日
目录
第一部分
一、实验目的4
二、实验环境及工具4
三、实验内容4
四、实验原理4
五、实验过程6
5.1设计思路6
5.2程序的实现部分11
六、程序测试12
6.1制定测试方案12
6.2测试效果12
七、源代码13
第二部分
一、实验目的14
二、实验环境及工具14
三、实验内容14
四、实验原理14
五、实验过程14
5.1设计思路14
5.2程序的流程图17
六、程序测试19
6.1制定测试方案19
6.2测试效果20
七、源代码20
第三部分
实验总结21
第一部分三圈DES的差分攻击
一、实验目的
通过课程设计,使学生进一步熟悉密码算法以及算法安全性的基本概念和原理;培养学生将密码理论和技术应用于实际的能力,使学生具备实施数据加/脱密和基本的密码分析的能力。
二、实验环境及工具
操作系统MicrosoftwindowsXPHomeEdition版本2002ServicePack3
IDE环境MicrosoftVisualC++6.0(SP6)
硬件环境Intel(R)Atom™CPUN270@1.60GHz,0.99GB的内存物理地址扩展
三、实验内容
题目:
三圈DES的差分攻击;
要求:
设计必需的界面环境,
(1)输入明文及其对应的密文,产生相应的密钥
(2)设计有好的窗口显示实验结果
四、实验原理
DES加密算法中的各种置换和扩展对差分没有影响,只有S盒可以阻挡差分;设△X=X1⊕X2,△Y=Y1⊕Y2,其中X1和X2是S盒的六位输入,Y1和Y2是相应的四位输出即X1->S=Y1,X2->S=Y2;那么我们就可以以△X为行索引,以△Y为列索引建立一个64*16的二维矩阵,矩阵中的元素为可能的X值,我们把这个矩阵称作S盒的差分表,如下表所示:
0
1
…
…
14
15
0
1
…
…
62
63
我们一共可以构造八个差分表,下面我们给出三圈DES的加密过程(省略了IP置换):
在选择明文攻击的情况下我们很容易保证△R0=0,那么我们就可以得到下列式子:
1)
-1
△A=E(△L3);
2)△B=P(△R3⊕△L0)
由于△L3、△R3、△L0在选择明文攻击时都是可求的,所以△A、△B也是可求的。
由于A是S盒的输入B是S盒的输出,我们又能求得△A、△B所以我们通过查差分表就可以把A局限在一个较小的范围内(在这个范围内穷举是可行的),又由于K3=A⊕C=A⊕E(L3),所以子密钥K3也被局限到了一个较小的范围内而DES的主密钥K的穷举时间是K3的256倍,所以穷举K也是可行的。
五、实验过程
5.1设计思路
其实具体的算法已经在实验原理中给出了,我就是按照此原理设计了一个CAttack类用来进行差分攻击,下面是它的头文件:
//Attack.h:
interfacefortheCAttackclass.
//
//////////////////////////////////////////////////////////////////////
#if!
defined(AFX_ATTACK_H__5C3E3C22_41EC_4D03_8249_6A9D80ECFA07__INCLUDED_)
#defineAFX_ATTACK_H__5C3E3C22_41EC_4D03_8249_6A9D80ECFA07__INCLUDED_
#if_MSC_VER>1000
#pragmaonce
#endif//_MSC_VER>1000
#include"DES.h"
#definePLAINTEXT00
#definePLAINTEXT11
#defineENCRYPTOGRAPH02
#defineENCRYPTOGRAPH13
#definePLAINTEXT24
#definePLAINTEXT35
#defineENCRYPTOGRAPH26
#defineENCRYPTOGRAPH37
classCAttack:
publicCDES
{
public:
CAttack();
virtual~CAttack();
/**************************************************************************
//名称:
InitAttack
//功能:
初始化8个S盒的差分表
//参数:
//返回:
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
voidInitAttack();
/**************************************************************************
//名称:
TryAttack
//功能:
进行差分攻击
//参数:
key:
[out]返回破解出来的密钥
//返回:
成功为TURE,否则为FALSE
//备注:
成功为TURE,否则为FALSE
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
BOOLTryAttack(CString&key);
/**************************************************************************
//名称:
SetData
//功能:
设置破解参数
//参数:
nFlag:
[in]参数标志
//str:
[in]参数值
//返回:
成功为TURE,否则为FALSE
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
BOOLSetData(UINTnFlag,CString&str);
protected:
/**************************************************************************
//名称:
CalcDelta
//功能:
计算各个差分值
//参数:
byPlaintext0:
[in]明文串0
//byEncryptograph0:
[in]密文串0
//byPlaintext1:
[in]明文串1
//byEncryptograph1:
[in]密文串1
//返回:
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
voidCalcDelta(BYTEbyPlaintext0[],BYTEbyEncryptograph0[],BYTEbyPlaintext1[],BYTEbyEncryptograph1[]);
/**************************************************************************
//名称:
BitToUint
//功能:
二进制位串到整型数据的转换
//参数:
byt:
[in]二进制串
//len:
[in]二进制串的长度
//返回:
转换结果
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
UINTBitToUint(BYTEbyt[],UINTlen);
/**************************************************************************
//名称:
UintToBit
//功能:
整型数据到二进制位串的转换
//参数:
byt:
[out]二进制串
//len:
[in]二进制串的长度
//n:
[in]整数
//返回:
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
voidUintToBit(BYTEbyt[],UINTlen,UINTn);
/**************************************************************************
//名称:
CalcSubkey
//功能:
计算所有可能的子密钥K3
//参数:
R:
[in]密文的右半部分
//delX:
[in]x的差分
//delY:
[in]y的差分
//subkey:
[out]可能的子密钥
//返回:
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
voidCalcSubkey(BYTER[],BYTEdelX[],BYTEdelY[],CListsubkey[]);
/**************************************************************************
//名称:
CalcSubkey
//功能:
穷举56位主密钥
//参数:
//返回:
成功为TURE,否则为FALSE
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
BOOLCalcMainKey();
/**************************************************************************
//名称:
Conjoin
//功能:
求子密钥交集的函数key2=key2交key1
//参数:
key2[in/out]:
子密钥key2集合
//key1[in]:
子密钥key1集合
//返回:
//备注:
//更新:
2010/3/10
//作者:
王凤伟
/**************************************************************************
voidConjoin(CListkey2[],CListkey1[]);
protected:
CListm_s[8][64][16];//用于保存差分表
CListm_Key1[8];//用于保存可能子密钥集合的链表
CListm_Key2[8];//用于保存可能子密钥集合的链表
BYTEm_byAttackedSubKey[ROUND][48];//3圈子密钥
BYTEm_byAttackedDesKey[56];//密钥
CStringm_strAttackedDesKey;//密钥串
BYTEm_byEncryptograph0[64];//密文0
BYTEm_byPlaintext0[64];//明文0
CStringm_strPlaintext0;//明文串0
CStringm_strEncryptograph0;//密文串0
BYTEm_byEncryptograph1[64];//密文1
BYTEm_byPlaintext1[64];//明文1
CStringm_strPlaintext1;//明文串1
CStringm_strEncryptograph1;//密文串1
BYTEm_byEncryptograph2[64];//密文2
BYTEm_byPlaintext2[64];//明文2
CStringm_strPlaintext2;//明文串2
CStringm_strEncryptograph2;//密文串2
BYTEm_byEncryptograph3[64];//密文3
BYTEm_byPlaintext3[64];//明文3
CStringm_strPlaintext3;//明文串3
CStringm_strEncryptograph3;//密文串3
BYTEm_byDeltaL0[32];//L0的差分
BYTEm_byDeltaL3[32];//L3的差分
BYTEm_byDeltaR3_L0[32];//R3的差分异或L0的差分
BYTEm_byDeltaA[48];//A的差分(S盒的输入)
BYTEm_byDeltaB[32];//B的差分(S盒的输出)
};
#endif//!
defined(AFX_ATTACK_H__5C3E3C22_41EC_4D03_8249_6A9D80ECFA07__INCLUDED_)
5.2程序的实现部分
既然原理已经很清楚了,那么设计算法就不在困难了,这里我进一步给出算法的流程图,算法的详细内容请参照文件夹DESAttacker中的源程序。
说明:
保存subkey时并不是真正的保存subkey的完整部分,而是将subkey
每6位分为一组保存,这样可以大大地减少存储空间(乘法原理)。
六、程序测试
6.1制定测试方案
为了便于测试,我编写了一个简单的三圈DES加密程序(DES3Rounds.exe),可以在DES3Rounds文件夹中找到,由用户自主选择密钥和满足条件的明密文对,然后把相应的参数输入到三圈DES差分攻击主程序(DESAttacker.exe)中,进行破译,最后与用户的密钥进行比较。
6.2测试效果
6.2.1生成破解参数
运行程序DES3Rounds.exe,输入相应的明文和密钥,生成参数
图6.2.1生成破解参数
6.2.1进行破译
运行DESAttacker.exe,并把刚才生成的破解参数复制到相应的编辑框中。
图6.2.1进行破译
七、源代码
由于该程序的主框架是由MFC的AppWizard生成的,代码量很大,所以就不把源代码放到实验报告里了,若要看源代码请打开当前目录下的DESAttacker文件夹。
一、实验目的
通过课程设计,使学生进一步熟悉密码算法以及算法安全性的基本概念和原理;培养学生将密码理论和技术应用于实际的能力,使学生具备实施数据加/脱密和基本的密码分析的能力。
二、实验环境及工具
操作系统MicrosoftwindowsXPHomeEdition版本2002ServicePack3
IDE环境MicrosoftVisualC++6.0(SP6)
硬件环境Intel(R)Atom™CPUN270@1.60GHz,0.99GB的内存物理地址扩展
三、实验内容
题目:
RSA解密密钥攻击;
要求:
设计必需的界面环境,
(1)加密密钥和解密密钥,求p、q,使n=p*q
(2)设计有好的窗口显示实验结果
四、实验原理
定理:
已知k1,k2求p和q,k1*k2=m*
(n)+1,若能求x*x=1(modn)的非平凡根,则可求p和q且p=(x+1,n),q=(x-1,n);
算法:
(1)k1*K2-1->r;0->s;
(2)i+1->s,n=r/2;
(3)若2|r,则转
(2),否则转(4);(
(2)-(3)步骤目的是求K1*K2=r*2^s)
(4)任取w,1=1,则p=(w,n);q=n/p,成功返回;否则转(5);
(5)w^r->V;若V=1,则转(4);否则转(6)
(6)r/2->r;V^r->tem;若tem=1则转(6);
若tem=-1,则转(4)
否则p=(tem+1,n),q=(tem-1,n),成功
说明:
算法的关键是第6步,在判断tem的值时,没有简单的判断tem=1或tem=-1时直接重新计算随机数W,而是对tem=1的情况进行了优化,即在tem=1时,把V的指数除二然后得到新的tem,这种优化是必要的,也是有效的。
因为
V^(2^s)是收敛于1的,也就是说在随着s的增大V^(2^s)=1的概率将越来越接近1,而若不把指数缩小很难找到tem!
=1的W值,这与利用穷举法分解N的效率相当。
我曾经在没有优化的情况下做过实验,当时分解一个20位(16进制)的N,大约需要30分钟,而且都是在(w,n)!
=1的条件下返回的(这正是穷举的结果),而经过优化后分解的时间只有几百毫秒的时间,而且都是在第六步返回的。
五、实验过程
5.1设计思路
具体的算法已经在实验原理中给出了,我就是按照此原理设计了一个CAttack类用来进行大数分解,而其中最关键的就是CAttack:
:
Attack()函数,下面给出了源代码:
#defineCHECK(x){if(!
(x))returnfalse;}
boolCAttack:
:
Attack()
{
staticBigIntr,tem,tem1,v,sem,m,rands,rands1;
UINTi=0;
//利用简单的加解密判断用户输入的参数是否正确
CHECK(m_OBigInt.PowMod(tem,m_OBigInt.Two,m_k1,m_n))
CHECK(m_OBigInt.PowMod(tem1,tem,m_k2,m_n))
CHECK(!
m_OBigInt.Cmp(tem1,m_OBigInt.Two))
CHECK(m_OBigInt.Mul(tem,m_k1,m_k2))
CHECK(m_OBigInt.Sub(sem,tem,m_OBigInt.One))
tem=sem;
//计算k1*k2-1=r*2^s
do
{
r=tem;
CHECK(m_OBigInt.Div(tem,rands,r,m_OBigInt.Two))
}while(!
m_OBigInt.Cmp(rands,m_OBigInt.Zero));
//2^s->m
CHECK(m_OBigInt.Div(m,tem1,sem,r))
//生成随机数rands1
CHECK(m_OBigInt.RandVal(rands1,m_n.len+1))
do
{
do
{
B:
if(i>CYCLE)
{
i=0;
CHECK(m_OBigInt.RandVal(rands1,m_n.len+1))
}
i++;
//生成满足条件1rands=rands1;
CHECK(m_OBigInt.Div(tem,rands,rands,m_n))
CHECK(m_OBigInt.Add(rands1,rands,m_OBigInt.One))
}while(!
rands.len||!
m_OBigInt.Cmp(rands,m_OBigInt.One)||!
m_OBigInt.Cmp(rands1,m_n));
//计算(rands,n)
CHECK(m_OBigInt.Glb(m_p,m_n,rands))
//(m_n,rands)=1,破解成功
if(m_OBigInt.Cmp(m_p,m_OBigInt.One))
{
CHECK(m_OBigInt.Div(m_q,tem,m_n,m_p))
CGfL:
:
HalfByteToStr(m_strP,m_p.bit,m_p.len);
CGfL:
:
HalfByteToStr(m_strQ,m_q.bit,m_q.len);
returntrue;
}
//计算rands^r->v
CHECK(m_OBigInt.PowMod(v,rands,r,m_n))
CHECK(m_OBigInt.Add(tem,v,m_OBigInt.One))
//若v=1或v=-1,则重新生成随机数
if(!
m_OBigInt.Cmp(v,m_OBigInt.One)||!
m_OBigInt.Cmp(tem,m_n))
{
gotoB;
}
tem1=m;//2^s->tem
loop:
CHECK(m_OBigInt.Div(tem1,tem,tem1,m_OBigInt.Two))//计算tem1/2->tem1
CHECK(m_OBigInt.PowMod(tem,v,tem1,m_n))//计算v^tem1->tem
//如果v^tem1=1,则计算v^(tem1/2)
if(!
m_OBigInt.Cmp(tem,m_OBigInt.One))