这个好像是最后一个实验了,同学们可以看一下以往的实验题目。
一、基础知识原理
这个EIGamal公钥加密算法其实非常有意思,但是我太菜了,我啥也不会。我除了说卧槽牛逼666也不会说啥了。
ppt我也截图下来了,突然想到同学们可能在写实验报告的时候公式可能不大好写,我这里也给出来吧。不想写公式的可以截个图啥的。
总体就分为三步密钥生成、加密、解密。
难点主要在于随机数g的生成,也就是求p的原根,这里通过翻各种求原根算法,终于找到了DH算法,DH算法用到了一个卧槽牛逼666的公式,能够很方便的求出模p的原根,即g若满足如下条件
则说明是g是 mod p的一个原根。
可以看这篇博客:
https://blog.csdn.net/borsyu/article/details/8240666
二、算法实现
1.环境
使用的是vc 6++ 和miracl大整数库。
资源见之前的博客。
2.Miracl库函数说明
1、
powmod2(v,one,c2,one,p,res);// res = v*c2 mod p
//感谢学长倾情相助的好函数。
这个是我在编程的时候遇到的一个坑。
在求C2时,有用到模p之下的乘积,就是
这里,因为当时不知好函数,只能先分别求模,再求乘积,然后再模p得到C2。
P.S.这个感觉代码的时间复杂度可能有点太高了,我的渣机子得跑十多秒才能找到p、q、g这几个随机数。
但是剩下的几个随机数好像找起来挺快的。
3.主要代码
代码如下:
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include"miracl.h"
#define N 150
int main()
{
FILE *fp;
miracl *mip = mirsys(90000, 10);
int i = 0;
int j = 0;
int flag = 1;
big p = mirvar(1);//随机数
big p1 = mirvar(0);//p-1
big p2 = mirvar(0);//p-2
big q = mirvar(1);//随机数q p = 2q + 1
big g = mirvar(1);//随机数
big a = mirvar(1);//随机数
big y = mirvar(1);//随机数
big c1 = mirvar(1);
big c1_1 = mirvar(1);// c1^-1
big c2 = mirvar(1);
big k = mirvar(1);//随机数
big v = mirvar(0);
big res = mirvar(0);
big temp = mirvar(0);
big temp1 = mirvar(0);
big temp2 = mirvar(0);
big m = mirvar(1);//明文
big one = mirvar(1);
big two = mirvar(2);
fp = fopen("secret3.txt","r");
if (fp == NULL)
{
printf("FILE ERROR\n");
return 0;
}
else
{
cinnum(m, fp);
printf("明文");
printf("\n------------------------------------------------------------------\n");
cotnum(m,stdout);
printf("------------------------------------------------------------------\n");
}
fclose(fp);
//密钥生成
//p、q生成
while(flag){
bigdig(150,10,q);
if(isprime(q)){
multiply(q,two,p);
add(p,one,p);
if(isprime(p)&&(numdig(p)==150))
flag = 0;//p = 2*q + 1 qiang su shu
}
else
flag = 1;
}
//g生成
flag = 1;
copy(p,temp);//temp = p
decr(p,1,p1); //temp-1
while(flag){
bigdig(150,10,g);
if((compare(p1,g)==1)&&(compare(g,one)==1)){//p-1<g g>one
powmod(g,two,p,temp1);//g^2 mod p!=1 且 g ^ q mod p!=1
powmod(g,q,p,temp2);
if(compare(temp1,one)&&compare(temp2,one))
flag = 0;
else
flag = 1;
}
}
decr(p,2,p2); //temp-1
//生成私钥a
while (1){
bigrand(p2,a);//a<p-2
if (compare(a,one) > 0)//a>1
break;
}
powmod(g, a, p, y);//y = g^a mod p
printf("公钥p、g、y");
printf("\n------------------------------------------------------------------\n");
cotnum(p, stdout);
cotnum(g, stdout);
cotnum(y, stdout);
printf("------------------------------------------------------------------\n");
printf("私钥a");
printf("\n------------------------------------------------------------------\n");
cotnum(a,stdout);
printf("------------------------------------------------------------------\n");
//加密
//k生成
while(1){
bigdig(150,10,k);
egcd(k,p1,temp);
if(compare(p1,k)==1&&compare(one,temp)==0)//p-1>k (k,p-1)=1
break;
}
powmod(g,k,p,c1);// y1 = g^k mod p 加密k=c1
powmod(y,k,p,temp); //temp = y^k mod p
powmod(m,one,p,temp1);
multiply(temp1,temp,temp2);
powmod(temp2,one,p,c2);//c2 = m*y^k mod p
printf("密文c1、c2");
printf("\n------------------------------------------------------------------\n");
cotnum(c1, stdout);
cotnum(c2, stdout);
printf("------------------------------------------------------------------\n");
//解密
xgcd(c1,p,temp,temp,temp);//temp = c1^-1 mod p
//xgcd(x,p,z,z,z); z = x^-1 mod p => z*x = 1 mod p
powmod(temp,a,p,v);//v = (c1^-1)^a mod p
powmod(c2,one,p,c2);//c2 = c2 mod p
//powmod2(v,one,c2,one,p,res);// res = v*c2 mod p
//可以求 m*y^k mod p
multiply(v,c2,temp2);
powmod(temp2,one,p,res);//res = v*c2 mod p
printf("解密后的明文");
printf("\n------------------------------------------------------------------\n");
cotnum(res, stdout);
printf("------------------------------------------------------------------\n");
if(compare(res,m)==0)
printf("恢复明文和原明文相同\n");
else
//pritnf("失败");
mirexit(); //清除MIRACL系统,释放所有的内部变量
getchar();
return 0;
}
三、总结
这个是此课程的第四个实验,经过了这么四个实验,感觉代码一个比一个长,一想到还有一个什么大作业,心情稀碎。
总而言之,这四个实验我都上传到CSDN了,所有代码也都给了。
希望大家给我点个赞啊!!!!!!!!!!!!!!!!!!!!!