1、XXXX学院 课程设计报告 DH密钥协商算法 课程名称: 密码算法程序设计 学生姓名: 学生学号: 专业班级: 任课教师: 2014年12 月 1日 指导老师评阅成绩表 学习与工作态度(30%) 选题意义(10%) 研究水平与设计能力(25%) 课程设计说明说(论文)撰写质量(25%) 设计创新(10%) 总分 指导老师签名:
2、 年 月 日 课程设计答辩记录及评价表 学生 讲述情况 教师主要 提问记录 学生回答 问题情况 答辩评分 评分项目 分值 评价参考标准 评分 总分 优 良 中 及格 差 选题意义 10 9 8 7 6 4 研究水平与设计能力 25 23 20 18 15 10 课程设计说明书(论文)撰写质量 25 23 20 18 15 10 设计创新 10 9 8 7 6 4 答辩效果 3
3、 答辩小组成员签名 答辩小组组长签名: 年 月 日 课程设计成绩评定表 成绩汇总 评分项目 评分 比例 分数 课程设计总分 指导老师评分 50% 答辩小组评分 50% 目 录 1、 选题背景 1 2、 DH密钥协商算法 1 2、1 算法得产生ﻩ1 2、2 算法得描述 2 2、3 算法得安全性ﻩ3 3、DH密钥协商算法得实现 4 3、1 设计要求 4 3、1、1 功能要求ﻩ4 3、2 模块划分及实现 5 3
4、2、1 小素数试除ﻩ5 3、2、2 模重复平方法ﻩ5 3、2、3 Miller-Rabin检测算法ﻩ7 3、2、4 原根得产生 8 3、2、5 产生随机素数 11 4、测试报告 12 结 论 17 参考文献ﻩ17 附源代码 18 1、 选题背景 密钥协商实际上就是一个协议,它通过两个或多个成员在一个公开得信道上通信联合地建立一个秘密密钥,一般情况下,一个密钥协商方案得密钥就是某个函数得值,其输入量由通信双方提供,协商过程就是由一系列得顺序步骤完成得。会话密钥由每个协议参与者分别产生得参数通过一定得计算得出。常见得密钥协商协议,如IKE。 密钥协商协议得生成方式则
5、可分为证书型与无证书型。证书型就是指在会话密钥得产生过程中,由一个可信得证书中心(CA)给参与密钥协商得各方各分发一个证书,此证书中含有此方得公钥,ID及其她信息。证书型密钥协商协议得优点就是提供认证,目前PKI(公钥密码体制)广泛部署,比较成熟,应用面广,且由PKG管理公私钥对有利于统一管理,缺点就是计算代价大,需要一个可信得CA,同时证书还需要维护。无证书型就是指各方在进行会话密钥得协商过程中不需要证书得参与,这就是目前密钥协商协议得主流种类,优点就是不需要CA得参与,减少了计算量,尤其就是在低耗环境下应用得更多,同时安全性也不比证书型弱。几乎没有明显得缺点,只就是设计一个安全得更加低耗得
6、无证书密钥协商方案不就是很容易。 现有得流行得密钥协商协议,都使用了Diffie-Hellman,它们基本上可以瞧成就是Diffie-Hellman得扩展。也就就是说,群组密钥协商协议可以理解成如何使用Diffie-Hellman来实现群得密钥交换。 2、 DH密钥协商算法 2、1 算法得产生 Diffie-Hellman密钥交换协议就是第一个被提出得密钥协商方案,就是美国斯坦福大学得W、Diffie与M、E、Hellman于1976年提出得,它就是第一个发表得公钥密码体制,Diffie-Hellman算法得唯一目得就就是使两个用户能安全得交换密钥,从而得到一个共享得会话密钥(秘密密钥
7、)。需要注意得就是,该算法本身不能用于加密解密,只能用于密钥得交换, 双方确定要用得密钥后,要使用其她对称密钥操作加密算法实际加密与解密消息。 2、2 算法得描述 1、 离散对数得概念: 1)原根:如果a就是素数p得一个原根,那么数值:a mod p,a^2 mod p,…,a^(p-1) mod p就是各不相同得整数,且以某种排列方式组成了从1 到p-1 得所有整数。 2)离散对数:如果对于一个整数b与素数p得一个原根a,可以找到一个唯一得指数i,使得b =(a^i)mod p,其中0≦i≦p-1,那么指数i称为b得以a为基数得模p得离散对数。 2、 算法有效性 Di
8、ffie-Hellman 算法得有效性依赖于计算离散对数得难度,其含义就是:当已知大素数p与它得一个原根a后,对给定得b,要计算 i ,被认为就是很困难得,而给定 i 计算b 却相对容易。 3、 Diffie-Hellman算法: 假如用户A与用户B希望交换一个密钥。取素数p与整数a,a就是p得一个原根,公开a与p。 1)A选择大得随机数RA(0<=RA<=p-2),并计算SA=(a^RA) mod p,并且把SA发送给用户B。 2)B选择随机数RB(0<=RB<=p-2),并计算SB=(a^RB) mod p,并且把SB发送给用户A。 3)A计算密钥得方式就是:K
9、SB) ^RA mod p,B计算密钥得方式就是:K=(SA) ^RB mod p, 证明: (SB)^ RA mod p = (a^RB mod p)^ RA mod p = (a^RB)^ RA mod p = (a^RA) ^RBmod p (-- 密钥即为 a^(RA*RB) mod p) =(a^RA mod p)^ RB mod p = (SA) ^RB mod p 由于RA与RB就是保密得,而第三
10、方只有p、a、SB、SA可以利用,只有通过取离散对数来确定密钥,但对于大得素数p,计算离散对数就是十分困难得。 4、 例子: 假如用户Alice与用户Bob希望交换一个密钥,取一个素数p =97与97得一个原根a =5,Alice与Bob分别选择秘密密钥RA=36与RB=58 ,并计算各自得公开密钥: SA=a^RA mod p =5^36 mod 97=50 SB=a^RB mod p =5^58 mod 97=44 Alice与Bob交换了公开密钥之后,计算共享密钥如下: Alice:K=(SB) ^RA mod p=
11、44^36 mod 97=75 Bob:K=(SA) ^RB mod p=50^58 mod 97=75 Diffie-Hellman密钥交换协议得基本模式如图2-1所示: SA=a^RA(mod p) 用户A 用户B SB=a^RB(mod p) 图2-1 Diffie-Hellman密钥交换协议得基本模式 2、3 算法得安全性 当然,为了使这个例子变得安全,必须使用非常大得RA, RB 以及p, 否则可以实验所有得可能取值。(总共有最多97个这样得值, 就算RA与RB很大也无济于
12、事)。 如果 p 就是一个至少 300 位得质数,并且RA与RB至少有100位长, 那么即使使用全人类所有得计算资源与当今最好得算法也不可能从a, p与a^(RA*RB) mod p 中计算出 RA*RB。ﻫ 这个问题就就是著名得离散对数问题。注意g则不需要很大, 并且在一般得实践中通常就是2或者5。在最初得描述中,迪菲-赫尔曼密钥交换本身并没有提供通讯双方得身份验证服务,因此它很容易受到中间人攻击。 ﻫ 一个中间人在信道得中央进行两次迪菲-赫尔曼密钥交换,一次与Alice另一次与Bob,就能够成功得向Alice假装自己就是Bob,反之亦然。而攻击者可以解密(读取与存储
13、任何一个人得信息并重新加密信息,然后传递给另一个人。因此通常都需要一个能够验证通讯双方身份得机制来防止这类攻击。ﻫ 有很多种安全身份验证解决方案使用到了迪菲-赫尔曼密钥交换。例如当Alice与Bob共有一个公钥基础设施时,她们可以将她们得返回密钥进行签名。 有攻击得Diffie-Hellman密钥交换协议如图2-2所示: SA=a^RA(mod p) SA’=a^RA’(mod p) 用户A 攻击者C 用户B SB=a^RB(mod
14、 p) SB’=a^RB’(mod p) 图2-2 有攻击得Diffie-Hellman密钥交换协议 3、 DH密钥协商算法得实现 3、1 设计要求 3、1、1 功能要求 (1)产生一个奇数p ,判断就是否就是素数。素数要求介于2^14-2^15。先用小于20得素数去试除,再使用Miller-Rabin概率检测算法进行检测; (2)求得模p 得一个原根,要求原根得值介于32-1024之间; (3)输出双方选择得随机数,随机数介于2^5-2^7,使用模重复平方法进行计算,输出双方得计算结果; (4)网络传输方面,可以就是C/S模式,也可
15、以就是B/S模式; (5)输出最后协商得密钥; 3、1、2 输出要求 (1)输出奇数得产生过程,用函数实现产生满足要求得奇数; (2)输出用小素数试除得判断过程,并输出每次试除之后得余数,用函数实现一次试除并返回试除之后得余数; (3)Miller-Rabin概率检测算法运行5次,输出检测过程及结果。用函数实现一次Miller-Rabin概率检测算法并返回检测结果; (4)如果不就是奇素数,输出下一个奇数产生得规则; (5)输出产生模得一个原根得过程; (6)输出使用模重复平方法进行计算得过程与结果。 3、2 模块划分及实现 3、2、1 小素数试除 算法描述:小素数
16、试除主要就是用随机产生得数来试除小于20得素数,以此简单判定该随机数就是否就是素数。 实现方式:以本次程序编写为例,取小素数数组S_PrimeTable[7] = { 3, 5, 7, 11, 13, 17, 19 },用产生得大随机数来除以数组中得元素,若所得余数不为0,则能暂时判断该随机数为素数。 具体实现代码如下: int SPrime(int odd) { int i, remainder, k = 0; for (i = 0; i<7; i++) { ﻩﻩremainder = odd % S_PrimeTable[i]; ﻩﻩprintf("第%d次小素数%
17、d试除得余数为%d、\n", i + 1, S_PrimeTable[i], remainder); ﻩ if (remainder == 0) k++; } if(!k) { ﻩ printf("小素数试除判断%d就是素数。\n\n",odd); } else ﻩ{ ﻩ printf("小素数试除判断%d不就是素数。\n\n",odd); } ﻩreturn !k; } 3、2、2 模重复平方法 算法描述: 模重复平方法就是对大整数模m与大整数e计算b^e(mod m)。在本次设计中,模重复平方法主要使用在米勒检测算余值部分、求原根部分、SA
18、与SB得计算以及最后密钥得计算过程中, 其中,SA与SB得计算以及最后密钥得计算要求输出计算过程。(为了界面显示美观,在此写了两个模重复平方算法得代码,思路相同,只就是在其中一个函数中写了输出计算过程,该函数用来计算SA与SB以及最后得密钥。) 实现方式:令a=1,并将十进制数e写成二进制,若二进制数值为1,则计算a≡(a*b)mod n,b≡(b*b)mod n;若二进制数值为0,则计算a≡a mod n,b≡(b*b)mod n。最后a即为最终计算结果。 具体实现代码如下: int MoChongFu(int m, int e,int n) { int binary[22
19、]; ﻩint count=0,i; int a=1,b; b=m; do{ ﻩ binary[count]=e%2; ﻩﻩe=e/2; ﻩﻩcount++; }while(e!=0); ﻩfor(i=0;i<count;i++) ﻩ{ if(binary[i]==1) ﻩﻩ{ ﻩﻩ a=(a*b)%n; ﻩﻩ b=(b*b)%n; //printf("a=%d, b=%d\n",a,b); } ﻩﻩif(binary[i]==0) ﻩ { ﻩﻩﻩa=a;
20、ﻩ ﻩb=(b*b)%n; //printf("a=%d, b=%d\n",a,b); ﻩ } ﻩ} return a; } 3、2、3 Miller-Rabin检测算法 算法描述:米勒检测在本次设计中主要用来检测在小素数判定了之后得随机数就是否就是素数。 实现方式:将待检测得数n写成n-1=2s*t,选取随机数a,计算b≡atmod n。若b mod n≡1,则n就是素数。否则,做如下循环,循环次数为1—s:如果b mod n≡-1,则b就是素数,否则,b≡b*b mod n。 具体实现代码如下: int milejiance(int odd) {
21、 int s=0,i,count=0; ﻩint a,b,t,num; ﻩnum=odd-1; while(1) ﻩ{ ﻩif(num%2==0) { ﻩ s++; ﻩ num=num/2; ﻩﻩ} else ﻩ { ﻩ ﻩt=num; ﻩﻩ break; } } ﻩprintf("将%d写成%d-1=2^%d*%d\t\t\n",odd,odd,s,t); a=rand()%(odd-3)+2; printf("产生得随机数a就是:%d\n",a); ﻩb=MoChongFu(a,t,odd);
22、 ﻩprintf("第1次算出得余值就是:%d\n",b); if(b%odd==1||b==(odd-1)) return 1; ﻩfor(i=0;i<s;i++) { ﻩ b=(b*b)%odd; ﻩprintf("第%d次算出得余值为%d \n",i+2,b); if(b==(odd-1)) ﻩﻩ{ ﻩﻩreturn 1; ﻩ }ﻩ } return 0; } 3、2、4 原根得产生 算法描述:要求一个素数一定范围内得原根,应该先求该素数得最小原根。根据定理:设m>1,m得欧拉函数a所有不同素因数就是q1,q2,…,qk,则g就
23、是模m得一个原根得充要条件就是 g^(a/qi)!=1(mod m),i=1,2,…k 实现方式: 先求大素数得欧拉函数得素因数a[n],并通过素因数求得g得指数c[n],接着验证g^c[n] 就是否同余于1,对g=2,3…,逐个验算,直到算出最小得g值满足g^c[n]均不同余于1,那么g便就是大素数m得最小原根,因为当c[n]遍历欧拉函数a得简化剩余系时,g^c[n]遍历模m得所有原根,所以可以通过欧拉函数得简化剩余系求得满足要求得原根。 具体实现代码如下: int yuangen(int yy) { int n=2,g=0,q,k,j=0,a[10]; int i=0
24、l=0;
ﻩint gg;
int c[10];
ﻩint count=0,flag=0;
q=yy-1;
while(1)
ﻩ{
ﻩﻩif (q%n==0)
ﻩ{
ﻩa[j]=n;
ﻩ j++;
ﻩﻩ q=q/n;
}
n++;
ﻩﻩif(q<n)
break;
ﻩ}
printf("模%d得欧拉函数分解质因数为:\n",yy);
for(n=0;n 25、ﻩ{
ﻩc[n]=(yy-1)/a[n];
ﻩprintf("%d ",c[n]);
ﻩ}
ﻩprintf("\n\n");
ﻩfor(g=2;;g++)
{
ﻩfor(n=0;n 26、u(g,c[n],yy),yy);
ﻩ}
ﻩﻩ}
ﻩﻩgg=g;
printf("所以%d就是最小原根。\n",gg);
ﻩﻩgoto ab;
cd: ;
ﻩ}ﻩ
ab:ﻩfor(g=3;;g++)
{
ﻩif((yy-1)%g!=0)
ﻩ {
k=MoChongFu(gg,g,yy);
ﻩif(k>32&&k<1024)
ﻩﻩ{
ﻩ printf("取介于2^5到2^10之间得一个原根值为:");
ﻩﻩ ﻩprintf("%d\n\n",k);
ﻩﻩ return k;
ﻩﻩ }ﻩ
ﻩﻩ}
ﻩ}
return 27、0;
}
3、2、5 产生随机素数
算法描述:使用srand()与rand()函数产生随机数n,然后通过判断n%2就是否为0来判断产生得就是否就是奇数。
具体实现代码如下:
int S_PrimeTable[7] = { 3, 5, 7, 11, 13, 17, 19 };
//产生一个随机数
int Random_Odd()
{
int odd = 0;
while (1)
{
ﻩsrand(time(NULL));
odd = rand() % (16385) + 16384;
if (odd % 2 != 0)
ﻩ break;
}
28、 //printf("%d\n", odd);
ﻩreturn odd;
}
4、 测试报告
⑴产生奇素数,用小素数试除并且输出试除得余数,再进行Miller-Rabin检测,若Miller-Rabin检测没有通过,则输出产生下一个随机数得规则并继续产生下一个随机数,直至产生满足条件得奇素数,如图4-1、4-2所示:
图 4-1 产生随机数并用小素数试除
图 4-2 米勒检测过程
⑵代码调试得最终结果如图4-3、图4-4、图4-5、图4-6、图4-7、图4-8所示:
图4-3 产生随机数并用小素数试除
图4-4 米勒检测过程
图4-5 大素数得欧拉函数分 29、解质因数
图4-6 求原根并计算各自得密钥
图4-7 模重复平方法计算过程
图4-8 计算共同密钥
结 论
本文就是在学习了相关C语言知识、密码学及相关信息安全数学知识之上进行得设计,本设计采用C语言实现,实现了DH密钥协商算法,用户A与用户B通过自己选取得随机数与公开得大素数通过离散对数得某些算法求得密钥,并相互交换密钥,通过交换得来得密钥产生共同得密钥。
由于学生水平有限,在程序可读性与规范性上有着一定得欠缺,略显不足,而在实现功能上也显得不就是很完善,需要在进一步得学习中得到提升。
在编写程序得过程中遇到了一些不可避免得错误与问题,但就是都通过书本以及同学 30、得帮助得以及时将这些问题解决,此次设计对我得逻辑性理解与编程能力都有一定得提高。
参考文献
[1] 谭浩强、 C程序设计[M]、北京:清华大学出版,1999、12
[2] 张仕斌、 应用密码学[M]、西安:西安电子科技大学出版,2009、12
[3] 陈恭亮、简明信息安全数学基础[M]、 北京:高等教育出版社, 20011、1
附源代码
#include 31、hongFu(int m, int e,int n);
int MoChongFua(int m, int e,int n);
int milejiance(int odd);
int yuangen(int yy);
int S_PrimeTable[7] = { 3, 5, 7, 11, 13, 17, 19 };
int main(void)
{
int yy=0;
ﻩint gg;
ﻩint A,B,Key,Key1,Key2;
int SA,SB;
ﻩint i,flag1,flag2;
do
{
q: ﻩprintf("************ 32、******\n\n\n");
ﻩ while(yy == Random_Odd());
ﻩﻩyy = Random_Odd();
ﻩprintf("产生得随机数就是:%d\n\n",yy);
ﻩﻩflag1=!SPrime(yy);
ﻩﻩfor(i=0;i<5;i++)
ﻩ{
ﻩ ﻩflag2=!milejiance(yy);
ﻩ if(flag2)
ﻩﻩ {
ﻩ printf("第%d次米勒检测未通过。\n\n",i+1);
ﻩﻩﻩ printf("因为第%d次米勒检测没有通过,所以随机数%d不就是素数,\n产生下一个随机数,先用小素数试除,再进行5 33、次米勒检测,如果小素数试除通过并且5次都通过,则说明该随机数就是大素数。",i+1,yy);
ﻩ printf("\n");
ﻩ ﻩgoto q;
ﻩ }
ﻩﻩ else
ﻩﻩ printf("第%d次米勒检测通过。\n\n",i+1);
ﻩ }
}
while(flag1||flag2);
gg=yuangen(yy);
ﻩsrand(time(NULL));
ﻩA = rand()%(96)+32;
ﻩB = rand()%(96)+32;
printf("Alice选择得随机数A就是:%d\n",A);
printf("Bob选择得随机 34、数B就是:%d\n\n",B);
printf("计算SA=(gg^A) mod yy:\n");
ﻩSA=MoChongFua(gg,A,yy);
ﻩprintf("\n");
ﻩprintf("计算SB=(gg^B) mod yy:\n");
SB=MoChongFua(gg,B,yy);
printf("所以SA与SB分别就是:%d,%d\n\n",SA,SB);
printf("计算Key1=(SB^A) mod yy:\n");
Key1=MoChongFua(SB,A,yy);
printf("\n");
printf("计算Key2=(SA^B) 35、 mod yy:\n");
Key2=MoChongFua(SA,B,yy);
printf("所以:Key1=%d,Key2=%d\n\n",Key1,Key2);
ﻩif(Key1==Key2)
ﻩﻩKey=Key1;
ﻩprintf("所以共同密钥Key就是:%d\n\n",Key);
ﻩreturn 0;
}
//产生一个随机数
int Random_Odd()
{
int odd = 0;
ﻩwhile (1)
ﻩ{
srand(time(NULL));
ﻩodd = rand() % (16384) + 16384;
ﻩif (odd 36、 2 != 0)
ﻩﻩ break;
ﻩ}
//printf("%d\n", odd);
ﻩreturn odd;
}
//如果就是素数得话返回1
int SPrime(int odd)
{
int i, r, k = 0;
ﻩfor (i = 0; i<7; i++)
{
r = odd % S_PrimeTable[i];
printf("第%d次小素数%d试除得余数为%d、\n", i + 1, S_PrimeTable[i], r);
ﻩﻩif (r == 0)
ﻩ k++;
}
ﻩif(!k)
{
ﻩprintf("小素数 37、试除判断%d就是素数。\n\n",odd);
ﻩ}
ﻩelse
{
ﻩﻩprintf("小素数试除判断%d不就是素数。\n\n",odd);
}
return !k;
}
int MoChongFu(int m, int e,int n)
{
int binary[22];
int count=0,i;
int a=1,b;
b=m;
ﻩdo{
ﻩbinary[count]=e%2;
ﻩe=e/2;
ﻩ count++;
ﻩ}while(e!=0);
ﻩfor(i=0;i< 38、count;i++)
{
ﻩif(binary[i]==1)
ﻩ{
ﻩ a=(a*b)%n;
ﻩb=(b*b)%n;
ﻩﻩ}
ﻩﻩif(binary[i]==0)
ﻩ {
ﻩﻩﻩa=a;
ﻩﻩb=(b*b)%n;
}
ﻩ}
return a;
}
int MoChongFua(int m, int e,int n)
{
int binary[22];
ﻩint count=0,i;
ﻩint a=1,b;
b=m;
ﻩdo{
ﻩ binary[count]=e% 39、2;
ﻩ e=e/2;
ﻩ count++;
ﻩ}while(e!=0);
ﻩfor(i=0;i 40、
ﻩint s=0,i,count=0;
int a,b,t,num;
num=odd-1;
while(1)
{
ﻩif(num%2==0)
ﻩﻩ{
ﻩ s++;
ﻩ num=num/2;
ﻩ }
ﻩ else
ﻩﻩ{
ﻩt=num;
ﻩ break;
ﻩﻩ}
ﻩ}
printf("将%d写成%d-1=2^%d*%d\t\t\n",odd,odd,s,t);
a=rand()%(odd-3)+2;
printf("产生得随机数a就是:%d\n",a);
b=MoChongFu(a,t,odd);
41、
ﻩprintf("第1次算出得余值就是:%d\n",b);
if(b%odd==1||b==(odd-1))
{
ﻩﻩreturn 1;
}
for(i=0;i<s-1;i++)
{
b=(b*b)%odd;
ﻩ printf("第%d次算出得余值为%d \n",i+2,b);
ﻩﻩif(b==(odd-1))
{
ﻩ return 1;
ﻩ }ﻩ
ﻩ}
ﻩreturn 0;
}
//欧拉函数得素因数与两者得商
int yuangen(int yy)
{
ﻩint n=2,g=0,q,k,j=0,a[10];
ﻩint gg; 42、
int c[10];
q=yy-1;
while(1)
ﻩ{
ﻩif (q%n==0)
ﻩ {
ﻩﻩﻩa[j]=n;
ﻩ j++;
while()
ﻩ q=q/n;
}
while(!(q%n))
ﻩﻩ {
ﻩ ﻩq=q/n;
ﻩ ﻩ}
if(q 43、or(n=0;n 44、",g,c[n],MoChongFu(g,c[n],yy),yy);
}
ﻩ }
ﻩ gg=g;
printf("所以%d就是最小原根。\n",gg);
goto ab;
cd: ;
}
ab:ﻩfor(g=3;;g++)
ﻩ{
ﻩ if((yy-1)%g!=0)
{
ﻩk=MoChongFu(gg,g,yy);
ﻩﻩﻩif(k>32&&k<1024)
ﻩ {
ﻩﻩﻩprintf("取介于2^5到2^10之间得一个原根值为:");
ﻩﻩﻩﻩprintf("%d\n\n",k);
ﻩﻩ ﻩreturn k;
ﻩ }ﻩ
ﻩﻩ}
}
return 0;ﻩ
}






